teidesu-scripts/scripts/infra/navidrome-remux-m4a.ts
2025-01-14 02:38:00 +00:00

66 lines
2.2 KiB
TypeScript

import { readFile, rm } from 'node:fs/promises'
import { join } from 'node:path'
import { $ } from 'zx'
import { downloadStream } from '../../utils/fetch.ts'
import { getEnv } from '../../utils/misc.ts'
import { fetchSongs } from '../../utils/navidrome.ts'
import { WebdavClient } from '../../utils/webdav.ts'
const webdav = new WebdavClient({
baseUrl: getEnv('NAVIDROME_WEBDAV_ENDPOINT'),
username: getEnv('NAVIDROME_WEBDAV_USERNAME'),
password: getEnv('NAVIDROME_WEBDAV_PASSWORD'),
})
const CHUNK_SIZE = 1000
for (let offset = 0; ; offset += CHUNK_SIZE) {
const songs = await fetchSongs(offset, CHUNK_SIZE)
if (songs.length === 0) break
for (const song of songs) {
const ext = song.path.split('.').pop()!
if (ext !== 'm4a') continue
console.log('❌ song %s is m4a, remuxing...', song.path)
const webdavPath = song.path.replace('/music/s3/', '/')
const res = await webdav.get(webdavPath).catch(() => null)
if (!res) {
console.log(' ❌ failed to get %s', webdavPath)
continue
}
const tmpfile = join('assets', `${song.id}.m4a`)
await downloadStream(res.body!, tmpfile)
console.log(' - downloaded to %s', tmpfile)
const probe = await $`ffprobe -v error -show_entries stream=codec_type,codec_name,index:stream_tags=title,language -of json ${tmpfile}`.json()
const audioStream = probe.streams.find(stream => stream.codec_type === 'audio')
if (!audioStream) {
console.log(' ❌ no audio stream found')
await rm(tmpfile)
continue
}
const codec = audioStream.codec_name
if (codec !== 'flac') {
console.log(` ❌ audio stream is ${codec}, not flac, skipping`)
await rm(tmpfile)
continue
}
console.log(' - audio stream is flac, remuxing')
// remux
const remuxed = join('assets', `${song.id}.flac`)
await rm(remuxed, { force: true })
await $`ffmpeg -i ${tmpfile} -c:a copy ${remuxed}`.quiet(true)
console.log(' - remuxed to %s', remuxed)
await rm(tmpfile)
await webdav.put(webdavPath.replace('.m4a', '.flac'), await readFile(remuxed))
await webdav.delete(webdavPath)
console.log(' - uploaded to %s', webdavPath.replace('.m4a', '.flac'))
await rm(remuxed)
}
}