【问题标题】:FFMPEG Seeking brings audio artifactsFFMPEG Seeking 带来音频神器
【发布时间】:2011-11-03 02:24:41
【问题描述】:

我正在使用 ffmpeg 实现音频解码器。 虽然读取音频甚至搜索已经有效,但我无法找到一种在搜索后清除缓冲区的方法,因此当应用程序在搜索后立即开始读取音频时,我没有任何伪影。

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

sn-p的代码很简单:

av_seek_frame(audioFilePack->avContext, audioFilePack->stream, posInTimeFrame, AVSEEK_FLAG_ANY);
avcodec_flush_buffers(audioFilePack->avContext->streams[audioFilePack->stream]->codec);

解释:

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

关于我应该怎么做才能寻找并获得没有残留音频的任何想法? 谢谢!

【问题讨论】:

  • 拜托,没有想法?我试图解决这个问题将近 2 周,但对可能导致此问题的原因没有任何想法......它应该按原样工作吗?
  • 消息也发送到 ffmpeg-user 官方邮件列表。仍然需要帮助。
  • 您能更详细地描述工件吗?它们是点击和弹出吗?

标签: c++ c audio ffmpeg seek


【解决方案1】:

这是 ffmpeg 中的一个错误。内部缓冲区没有被刷新,因此当您在刷新后获取数据包/帧时,您将获得预搜索数据。它似乎在 2012 年 3 月 16 日已修复,因此您可以自己合并此修复程序,或升级 ffmpeg。

http://permalink.gmane.org/gmane.comp.video.libav.devel/23455

作为更新,上面的错误确实是一个问题,但还有第二个专门针对 AAC 的错误。

五个月前,另一位用户发现了此错误,并报告已修复。 https://ffmpeg.org/trac/ffmpeg/ticket/420

修复是在 aacdec.c 中添加了一个刷新函数,该函数会清除其内部缓冲区。 问题是在 aacdec.c 中定义了两个解码器,并且只有一个被赋予了 flush 函数指针。如果您使用其他(更常见的)解码器,它仍然无法正确清除。

如果您能够自己构建 ffmpeg,解决方法是添加 .flush = 冲洗, 到 AVCodec ff_aac_decoder 定义的底部(在文件的底部。)

我会让 ffmpeg 人知道,希望它可以包含在主分支中。

【讨论】:

  • 顶一下,希望原发帖人能看到
  • 非常感谢!我将重新编译它并放弃我的替代方式......这很丑但有效......
【解决方案2】:

我从未编写过具有搜索功能的音频播放器,但我怀疑是这样的。每个音频包都解码为原始声波的 sn-p。通常,这些 sn-ps 顺序地相互邻接,结果是一个连续波,人们将其作为没有伪影的音频听到。当你寻找时,你迫使两个来自文件不同部分的 sn-ps 相互邻接。这通常会在生成的声波中引入不连续性,耳朵将其感知为咔哒声或爆破声,或者正如您所说的(我猜是)人工制品。

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-20
    • 2017-01-04
    • 2018-01-23
    • 1970-01-01
    • 2014-07-23
    • 2014-10-31
    • 2021-10-26
    相关资源
    最近更新 更多