音视频对抗弱网技术详解
背景
在网络条件不理想的情况下,如何保证音视频通话的相对流畅体验?本文主要想讨论这个问题
一、什么是弱网?
弱网是指网络条件较差的环境,通常表现为以下特征:
| 指标 | 正常网络 | 弱网 |
|---|---|---|
| 带宽 | 稳定充足 | 波动大、可用带宽低 |
| 延迟 | < 100ms | > 300ms 甚至更高 |
| 丢包率 | < 2% | 5%~30% 甚至更高 |
| 抖动 | 小 | 波动剧烈 |
弱网场景
- 移动网络(地铁、电梯、地下室)
- 跨国/跨地区通信
- 网络拥塞(高峰时段)
- WiFi 信号弱
- 网损仪
二、核心对抗技术
1. FEC(前向纠错)
原理:发送端添加冗余数据,接收端根据冗余数据恢复丢失的包,无需重传。
原始数据:[A][B][C][D]
FEC 数据(异或):[A⊕B][C⊕D]
如果 [B] 丢失,可通过 [A] 和 [A⊕B] 恢复
这种方法优点在于不会增加额外的时延,适合实时的音频传输,因为音频的包本身比较小,不过对于带宽也会增加,丢包率太高(大于20%)也不可用。所以只能适用于有限场景,如果冗余的异或包也丢失了,就可能就无法恢复了
2. ARQ(自动重传请求、NACK)
Automatic Repeat Request
原理:接收端检测到丢包后,请求发送端重传。
发送端 → [1][2][3][4] → 接收端
↓ (3 丢失)
接收端 → [NACK:3] → 发送端
发送端 → [3] → 接收端
这种方法在于不会增加额外的带宽,基本任意的丢包都可以恢复,不过因为增加了重传了,可能会阻塞带来了网络时延。不过结合最大重传次数和超时处理,可以算是一个很不错的方案了
3. 自适应码率(ABR)
原理:根据网络状况动态调整编码码率。
// 伪代码示例,一般是带宽估计算法 + 码率控制
function adjustBitrate(networkQuality) {
if (networkQuality.bandwidth < 500kbps) {
setVideoBitrate(300kbps);
setAudioBitrate(20kbps);
} else if (networkQuality.bandwidth < 2000kbps) {
setVideoBitrate(1000kbps);
setAudioBitrate(40kbps);
} else {
setVideoBitrate(3000kbps);
setAudioBitrate(64kbps);
}
}
这个常见的算法有GCC, BBR, WebRTC内置的拥塞控制,一般都是检测可用的带宽、丢包率,网络抖动JitterBuffer,缓冲区的大小(实时音视频不看这个指标)。
4. 抖动缓冲(Jitter Buffer)
原理:在接收端缓存数据包,平滑网络抖动,按正确顺序和时机播放
网络到达:[1]---[3][2]-----[4]---> (乱序、间隔不均)
Jitter Buffer 整理后:
播放输出:[1][2][3][4] (均匀间隔)
这个对时延要求高的场景不可用,一般适用于点播的场景
5. 包丢失隐藏(PLC)
原理:当音频包丢失时,根据前后数据插值生成替代数据。
这个按照我理解有点像是丢包了,但是自己用前后两个数据来作为参考直接生成一个新的数据,有点类比于NVIDIA显卡的DLSS自动插帧的原理。接触不多,等有了解了,再补充
在未来,说不定有AI的算法介入有可能可以实现本地的部分数据推测出来,也是相当的有可能。
三、WebRTC 中的实现
WebRTC 内置了多种弱网对抗机制:
WebRTC 内置机制:
- NACK/PLI/FIR 反馈
- GCC 拥塞控制
- NetEq 音频处理(含 PLC)
- 动态码率调整
五、性能监控与调优
关键监控指标
| 指标 | 阈值告警 | 说明 |
|---|---|---|
| 丢包率 | > 5% | 上行 + 下行 |
| RTT | > 300ms | 往返延迟 |
| 卡顿率 | > 2% | 播放卡顿时间占比 |
| 码率波动 | > 50% | 码率变化幅度 |
六、总结
对抗弱网没有银弹,需要根据场景组合使用多种技术:
| 技术 | 延迟影响 | 带宽开销 | 适用丢包率 |
|---|---|---|---|
| FEC | 低 | 高 | < 20% |
| ARQ | 高 | 低 | 任意 |
| 自适应码率 | 低 | 低 | 任意 |
| 抖动缓冲 | 中 | 无 | 抖动场景 |
| PLC | 低 | 无 | 音频丢包 |
最佳实践:
- 实时监控网络质量
- 动态调整策略组合
- 根据场景、对音频和视频做出一定的取舍
- 优雅降级优于直接断开