把 120 首現場錄音的歌單時長算準:我用 ffprobe 對拍的笨辦法

这篇内容暂时只有 繁體中文 版本,以下是原文。

上個月整理一批現場錄音,來源是 2019 到 2023 年間自己錄的 120 個片段,格式有 WAV 也有從影片抽出來的 AAC,取樣率從 44.1kHz 到 48kHz 混在一起。問題出在歌單:我想把這些片段接成一份可以連續播放的順序,但每一首的實際長度跟播放器顯示的不一樣,導出的 m3u 放進 foobar2000 後,總時長誤差累積到快 40 秒,尾段整段對不上我原本排的節奏。

我的做法很土,先不碰 DAW,直接用 ffprobe 把每個檔案的容器時長、音訊流時長、以及最後一個 packet 的結束時間都抓出來,寫成 TSV:

for f in *.wav *.m4a; do
  ffprobe -v error -show_entries format=duration \
    -show_entries stream=codec_name,sample_rate,duration \
    -of default=nw=1 "$f" | paste -sd '\t' \
    >> probe.tsv
done

接著用一個小腳本比對 format.duration 和 stream.duration,差距超過 0.15 秒的挑出來,總共 17 個。這 17 個大多是有靜音前導或尾端被截掉的 AAC,容器時長比音訊流長。我把這些檔案的實際音訊邊界用 ffmpeg -af silencedetect 標一次,再手動修歌單裡的時間點。剩下的 103 個直接信 stream duration。

為什麼不用播放器顯示的長度?因為那通常是讀容器 header,遇到可變位元率或錄音中斷的檔案就會偏。ffprobe 給的 stream duration 是解碼後算的,慢,但對這種幾十秒到幾分鐘的現場片段夠準。代價是要多跑一輪解碼,120 個檔案大概花了四分鐘,而且我這台機器沒有 SSD,I/O 是瓶頸。

會失效的地方很明確:取樣率中途改變的檔案,stream duration 會報錯或給出離譜的值,我有 3 個這種檔,最後只能整段重聽手動記時間。另外,若檔案尾端有極低電平的殘響,silencedetect 的門檻設 -50dB 會把殘響也切掉,我踩過一次,歌單尾段突然變得很乾。門檻我後來改成 -60dB,並且只信任前 0.5 秒的靜音判斷。

你們在排這種長度不一的現場歌單時,是直接信播放器給的時長,還是會另外量一次音訊邊界?如果會,門檻都怎麼設?

0
赞同度 100% · 0 条评论 · 3 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。