如何快速获取任何音频文件的准确时长?

3
野外中有许多采用可变比特率编码的音频文件没有准确的持续时间标签,使用命令行FFMpeg会输出以下信息:
“从比特率估计持续时间,这可能不准确”
(实际上确实如此)
使用libav,我们可以看到测试是否具有持续时间信息使用了libavformat/utils.c中的has_duration()函数。
我有一个音频播放器需要使用libav获取准确的持续时间信息。我已经尝试完全解码文件并计算总解码样本数,这是通常的建议(且准确),但这会花费60分钟音频文件10秒以上,这是不可接受的。
我注意到有一些闭源音频解码器和音乐播放应用程序可以立即获得这些文件的准确持续时间。肯定存在一种廉价的方法来确定准确的持续时间?也许一小段代码或高层次描述可以帮助我。

“我已经尝试完全解码了文件……”你是否可以通过采样前几秒并进行外推来获得足够准确的估计,而不是整个文件? - Weather Vane
3
使用可变比特率的MP3文件时,扫描整个文件是唯一的方法。您不必完全解压缩文件,但需要读取每个MP3块头,这应该相对较快。 - selbie
否则,所有恒定比特率的音频文件在头部都有你需要的一切。我认为libavformat应该支持这个。 - selbie
1
我认为你应该能够使用libavformat仅进行“demux”(实际上没有任何复用,但它仍然会解析流中的数据包),而不是解码,这样处理速度应该非常快。但我想知道你是否做错了什么导致解码如此缓慢。我记得几十年前mp3解码已经超过500倍的实时速度,所以现在应该更快了... - R.. GitHub STOP HELPING ICE
ffmpeg -i *.mp3 -f null - 在我的新桌面预装的 ffmpeg 上,对于 60 分钟以上的曲目,速度为 1550x,仍需几秒钟的时间。在 Android(我的目标平台)上速度要慢得多。感谢提供了分离音频的提示,也许这是解决方案。 - Steve M
@SteveM 请尝试在您的命令中添加“-c copy”输出选项。 - llogan
1个回答

2

可以很快地“解复用”轨道并检查每个数据包的持续时间以确定轨道的总持续时间,不需要解码。

只需在循环中添加持续时间,直到达到EOF:

int read = av_read_frame(pFormatCtx, packet);
durationSeconds = packet->duration * (double) timebase;

在我的测试中,对于mp3格式,它给出的结果与formatContext->duration / AV_TIME_BASE相同,但并不准确。可能与第一帧和最后一帧具有编码器填充有关,但如果不解码整个文件,就无法检测到。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接