FFMPEG寻求带来音频伪像

Gab*_*ões 6 c c++ audio ffmpeg seek

我正在使用ffmpeg实现音频解码器.在阅读音频甚至寻求已经有效的时候,我无法找到一种方法来清除缓冲区后寻求所以当应用程序在搜索后立即开始读取音频时我没有任何文物.

avcodec_flush_buffers似乎对内部缓冲区没有任何影响.所有解码器(mp3,aac,wma,...)都会出现此问题,但PCM/WAV(由于未压缩音频,因此不使用内部缓冲区来保存数据以进行解码).

代码片段很简单:

av_seek_frame(audioFilePack->avContext, audioFilePack->stream, posInTimeFrame, AVSEEK_FLAG_ANY);
avcodec_flush_buffers(audioFilePack->avContext->streams[audioFilePack->stream]->codec);
Run Code Online (Sandbox Code Playgroud)

解释:

audioFilePack->avContext = FormatContext
audioFilePack->stream = Stream Position (also used to read audio packets)
audioFilePack->avContext->streams[audioFilePack->stream]->codec = CodecContext for the codec used
Run Code Online (Sandbox Code Playgroud)

关于我应该做什么的任何想法,我可以寻求并获得没有剩余的音频?谢谢!

Ran*_*ook 2

我从未编写过具有搜索功能的音频播放器,但我怀疑正在发生的事情是这样的。每个音频数据包都会解码为原始声波的片段。通常,这些片段顺序地彼此邻接,结果是一个连续的波,人们听到的声音是没有伪影的音频。当您进行查找时,您会强制文件不同部分的两个片段彼此相邻。这通常会给产生的声波带来不连续性,耳朵将其视为咔嗒声或爆裂声,或者如您所说(我猜)是伪影。

这是一个更具体的例子。假设您在搜索之前已经播放了前 ​​25 个音频数据包。假设数据包 25 解码为最后一个样本为 12345 的波形。当数据包 25 呈现给扬声器时,您会寻找数据包 66。假设数据包 66 的第一个样本是 -23456。因此,数字音频流在整个搜索过程中从 12345 跳到 -23456。这是一个巨大的不连续性,并且会听到流行声。

我认为一种解决方案是在开始查找之前获取一个额外的数据包(在我的示例中为数据包 26),将其解码到离线缓冲区,应用淡出,然后将其放入播放队列。找到所需位置后,获取第一个数据包(在我的示例中为 66),将其解码到另一个离线缓冲区,应用淡入,然后将其放入播放队列中。这应该确保平滑的声波和无伪影的搜索。

如果您足够聪明,您可以根据需要将淡出和淡入设置为短或长。我认为只需几毫秒就足以防止伪影。您甚至可以对新旧数据包应用交叉淡入淡出。仅仅记下查找之前最后一个数据包中的最后一个样本值,并在几个样本中逐渐将其降至零,而不是立即将其拉至零,也可能就足够了。这可能比解码额外的数据包更容易。

这是我对如何解决这个问题的猜测。这显然是一个已解决的问题,因此我鼓励您也查看开源音频播放器并了解它们如何实现搜索。Audacity、Totem、Banshee、RhythmBox、Amarok 或 VLC 等程序或 GStreamer 等框架可能是值得学习的好例子。如果您发现他们采用了值得注意的技术,请在此处报告主题。我认为人们会想了解他们是什么。祝你好运!