NetEq 总览 · 自适应抖动缓冲 + 丢包隐藏

NetEq 是 WebRTC 音频接收侧的明珠——自适应抖动缓冲兼丢包隐藏器。这一章读 modules/audio_coding/neteq 的 g3doc:它 InsertPacket 收包、GetAudio 出音频的两个核心接口,以及它「平滑播放、低瑕疵、低延迟」三个相互冲突的目标怎么权衡。

作者 David更新于 第 66 篇(共 112 篇)

NetEq 总览 · 自适应抖动缓冲 + 丢包隐藏

音频接收侧的核心,是一个 WebRTC 里公认精妙的模块——NetEq。它的 g3doc 一句话定义了它:

NetEq is the audio jitter buffer and packet loss concealer.

它同时是抖动缓冲和丢包隐藏器——把音频接收侧最难的两件事融为一体。第 7 部分接下来五章都在讲它。先总览。

三个冲突的目标

NetEq 的 g3doc 点明它要同时追求三个相互冲突的目标:

NetEq 要同时:① 平滑播放(smooth playout)② 低瑕疵(少改动原始音频)③ 低延迟——而这三者两两冲突。

NetEq 的全部精妙,就在于在这个三角里,根据实时网络状况动态找最优点——网络好就压低延迟、少缓冲;网络抖就多缓冲、动用各种修复手段保平滑。它是“自适应”的(“adaptive jitter buffer”),缓冲延迟持续优化,不是固定值。

两个接口:InsertPacket 与 GetAudio

NetEq 的 API 出奇地简单——就两个函数(api/neteq/neteq.h):

// api/neteq/neteq.h(概念)
InsertPacket(packet);        // 网络来了个音频包,塞进来
GetAudio(&output, ...);      // 声卡要一小段音频,给出来

NetEq 由两股节奏驱动:网络“不规律地”塞包(InsertPacket),声卡“极规律地”要音频(GetAudio)——NetEq 的使命就是把前者的参差,变成后者的平稳。

这个“输入不规律、输出必须规律”的错位,是 NetEq 一切复杂性的根源。声卡不等人——它每 10ms 准时来敲门,NetEq 手里有包就解码给它(Normal),没包就得变戏法(时间伸缩、丢包隐藏)。把“网络的混乱”翻译成“声卡的秩序”,且尽量不让人听出破绽——这就是 NetEq 每 10ms 都在做的事。

GetAudio 的六种可能

每次 GetAudio,NetEq 会根据当前状态(缓冲多少、包到没到),从六种操作里选一个来产出这段音频(g3doc 列得很清楚,下下章详解):Normal(正常解码)、Acceleration(加速)、Preemptive expand(减速)、Expand(丢包隐藏)、Merge(拼接)、Comfort noise(舒适噪声)。这六种操作就是 NetEq 的“戏法”——先记住有这么六种,后面逐个看。

它在哪

NetEq 住在 ACM 的接收侧内部,被声卡的取音频回调驱动 GetAudio。它可替换(neteq_factory),但默认实现就是这套久经打磨的算法。

小结与下一章

NetEq 是音频接收侧的明珠——自适应抖动缓冲 + 丢包隐藏器,追求三个冲突目标(平滑、低瑕疵、低延迟)的动态最优。两个接口:InsertPacket(网络不规律塞包,分析抖动)、GetAudio(声卡极规律要音频,必须每次都给)。这个“输入乱、输出必须齐”的错位是它复杂性的根源。每次 GetAudio 从六种操作选一个产出音频。它住在 ACM 内。

先看它怎么管缓冲、以及“该缓冲多少”这个自适应的核心。👉 NetEq 缓冲与延迟。

参考资料

  • [1] libwebrtc 源码.modules/audio_coding/neteq/g3doc/index.md、api/neteq/neteq.h(InsertPacket / GetAudio)。
  • [2] libwebrtc 源码.modules/audio_coding/neteq/neteq_impl.h / .cc。
  • [3] 关联视频抖动缓冲——同类问题的音频版。

本页目录