NetEq 缓冲与延迟 · 该攒多少音频

NetEq 自适应的核心,是「目标延迟」——该攒多少音频才能既抗抖动又不太延迟。这一章讲清包缓冲区怎么按时间戳存包、延迟管理器怎么从包间到达时间估出抖动、进而算出动态的目标缓冲水平,以及这个自适应如何随网络实时调整。

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

NetEq 缓冲与延迟 · 该攒多少音频

NetEq 是自适应的,而“自适应”的核心,就是一个数——目标延迟(target delay):该攒多少音频在缓冲里?攒多了延迟大,攒少了抖动一来就断音。算准这个数,是 NetEq 的第一要务。这一章看它怎么算。

包缓冲区:按时间戳排队

InsertPacket 塞进来的包,先进包缓冲区(packet buffer)。它按 RTP 时间戳给包排序——网络可能乱序送达,缓冲区把它们重新排好,等到播放时刻按顺序取出。缓冲区有容量上限(满了会丢弃,罕见),太晚到的包(错过播放时刻的)直接丢弃。它就是那个“蓄水的水库”,攒着一小段未来要播的音频。

延迟管理器:估抖动,定目标

“该攒多少”由 延迟管理器(DelayManager) 算,依据是观测到的网络抖动:

延迟管理器分析包的到达间隔,估出网络抖动有多大,据此算出“目标缓冲水平”——抖动越大,目标越高(多攒点扛抖动);抖动越小,目标越低(少攒点降延迟)。

怎么估?InsertPacket 时,NetEq 记录每个包该来的时间和实际来的时间之差——这个差的波动就是抖动。如果包大多准时到、偶尔晚一点点,抖动小,目标延迟就可以压得很低(如 40ms);如果包到得忽早忽晚、时有大延迟,抖动大,目标延迟就得抬高(如 200ms),否则缓冲频繁见底、断音。延迟管理器用统计方法(如追踪到达间隔的某个高分位数)量化“要扛住绝大多数包的延迟,得攒多少”,给出目标。它把“网络有多不稳”翻译成“该攒多少音频”——这是 NetEq 自适应的大脑。

缓冲和目标的差,驱动操作

有了“当前缓冲量”和“目标缓冲量”,每次 GetAudio 时,NetEq 比较两者,决定做哪种操作:

当前缓冲 vs 目标缓冲的差,直接决定 NetEq 该加速、减速、还是正常播:

妙处在于:这些加速 / 减速是通过时间伸缩实现的,不改变音调(不像快进磁带会变尖),听感上几乎察觉不到。于是 NetEq 能悄悄地、持续地微调播放节奏,让缓冲量始终贴着目标——网络抖动被这套“弹性播放”吸收得神不知鬼不觉。这是 NetEq 比视频抖动缓冲精细得多的地方:视频只能“多缓冲或少缓冲”,音频还能“弹性地伸缩时间”来主动调节。

目标随网络实时变

延迟管理器持续更新目标——你从 Wi-Fi 走到信号差的地方,抖动变大,它悄悄抬高目标(多攒点,你可能感觉到延迟略增但不断音);回到好网络,它慢慢压低目标(追回低延迟)。这个目标从不固定,一直跟着网络呼吸——正是“自适应”的体现。它和拥塞控制的闭环一样,是 WebRTC “实时追踪网络”哲学在音频侧的落地。

小结与下一章

NetEq 自适应的核心是目标延迟。包缓冲区按时间戳排队存包(乱序重排、太晚丢弃)。延迟管理器分析包间到达时间估抖动,算出“目标缓冲水平”(抖动大则目标高)。当前缓冲 vs 目标的差驱动操作:多了加速追回、少了减速攒回、刚好正常播——靠**不变调的时间伸缩**悄悄调节。目标随网络实时变。

缓冲和目标的比较,产出六种操作之一。下一章把这六种操作和背后的决策逻辑讲全。👉 NetEq 的六种操作。

参考资料

  • [1] libwebrtc 源码.modules/audio_coding/neteq/packet_buffer.h、delay_manager.h、g3doc/index.md。
  • [2] libwebrtc 源码.modules/audio_coding/neteq/decision_logic.h。
  • [3] 关联视频抖动缓冲的流畅 vs 延迟权衡。

本页目录