teidesu-scripts/scripts/infra/navidrome/find-broken.ts
2025-05-09 06:46:50 +00:00

42 lines
No EOL
1.2 KiB
TypeScript

import { $, ProcessOutput } from 'zx'
import { fetchSongsIter } from '../../../utils/navidrome.ts'
import { asyncPool } from '@fuman/utils'
import { join } from 'path/posix'
// async function checkIfBroken(path: string) {
// const r = await $`ffprobe -v error -show_entries stream=codec_type,codec_name,index:stream_tags=title,language -of json ${path}`.json()
// }
// for await (const song of fetchSongsIter()) {
// }
const broken: string[] = []
await asyncPool(fetchSongsIter({
onChunkProcessed: (page, items) => {
console.log(`Processed page ${page} with ${items} items`)
},
}), async (song) => {
const fullPath = join(song.libraryPath, song.path)
const path = fullPath.replace('/music/s3/', '/mnt/tank/enc/media/music/')
try {
const r = await $`ffmpeg -v error -i ${path} -f null -`.quiet()
if (r.exitCode !== 0 || r.stderr.trim() !== '') throw r
} catch (e) {
if (!(e instanceof ProcessOutput)) throw e
console.log('%s - %s (%s) seems broken:', song.artist, song.title, path)
console.log(e.stderr)
broken.push(path)
}
}, { limit: 8 })
if (broken.length > 0) {
console.log('Found %d broken files:', broken.length)
for (const path of broken) {
console.log(' %s', path)
}
process.exit(1)
}