丢包隐藏(PLC)技术
概述
丢包隐藏(Packet Loss Concealment, PLC)是在接收端对丢失的音频包进行补偿的技术。与 FEC(前向纠错)和 NACK(重传)不同,PLC 不需要任何额外的网络传输——它完全在接收端本地完成,利用已收到的音频信息来"猜测"丢失的内容。
PLC 是实时通信中的最后一道防线:当 FEC 和 NACK 都无法恢复丢失的包时,PLC 负责生成替代音频,避免播放中断。
flowchart LR
A[丢包发生] --> B{FEC 能恢复?}
B -->|是| C[FEC 解码恢复]
B -->|否| D{NACK 来得及?}
D -->|是| E[重传恢复]
D -->|否| F[PLC 生成替代音频]
style F fill:#f96,stroke:#333
PLC 技术分类
类型 |
原理 |
质量 |
代表 |
|---|---|---|---|
静音插入 |
丢包处用静音填充 |
差(明显中断) |
最简单的实现 |
重复帧 |
重复最后一个正常帧 |
一般(有重复感) |
早期 VoIP |
基于波形 |
利用基音周期外推 |
好 |
G.711 Appendix I |
基于模型 |
利用编码器参数外推 |
很好 |
G.729 PLC, Opus SILK |
基于深度学习 |
神经网络预测 |
优秀 |
WaveNetPLC, LPCNet |
静音插入
最简单的 PLC——丢包时插入静音或零值:
正常: |~~~~∿~~~~|~~~~∿~~~~| |~~~~∿~~~~|
丢包: | 静音 |
↑ 听感:明显的"咔嗒"中断
缺点:即使 1% 的丢包率也会严重影响通话质量。唯一的优点是零复杂度。
重复帧
重复最后一个正常帧:
正常: |~~~~∿~~~~|~~~~∿~~~~| |~~~~∿~~~~|
丢包: |~~~~∿~~~~|
↑ 重复上一帧
比静音好,但连续丢包时会产生"机器人"般的重复感。通常加上逐渐衰减来改善。
基于波形的 PLC
利用语音信号的准周期性(基音周期),从已收到的波形中外推丢失的部分。
G.711 Appendix I 算法
这是最经典的波形 PLC 算法:
步骤:
1. 保存最近 48.75ms 的语音历史(390 samples @ 8kHz)
2. 丢包时,在历史缓冲中搜索基音周期
- 用自相关函数找到最强的周期性
- 搜索范围:40-120 samples(200-1000 Hz)
3. 用基音周期长度的波形片段重复填充丢失帧
4. 在拼接点做重叠相加(OLA)平滑
5. 连续丢包时逐渐衰减(每帧衰减约 10%)
/* 简化的基音周期搜索 */
int find_pitch(int16_t *history, int hist_len) {
float best_corr = -1.0;
int best_lag = 40;
for (int lag = 40; lag <= 120; lag++) {
float corr = 0, energy1 = 0, energy2 = 0;
for (int i = 0; i < 80; i++) {
int idx1 = hist_len - 80 + i;
int idx2 = idx1 - lag;
corr += history[idx1] * history[idx2];
energy1 += history[idx1] * history[idx1];
energy2 += history[idx2] * history[idx2];
}
float norm_corr = corr / sqrt(energy1 * energy2 + 1e-10);
if (norm_corr > best_corr) {
best_corr = norm_corr;
best_lag = lag;
}
}
return best_lag;
}
基于模型的 PLC
编解码器内置的 PLC 利用编码器的参数模型来生成替代帧,质量通常比波形 PLC 更好。
Opus SILK 模式 PLC
Opus 的 SILK 模式(语音)内置了高质量 PLC:
LP 系数外推:使用最后一帧的 LP 系数(频谱包络)
基音外推:使用最后一帧的基音周期和增益
激励信号:用随机噪声 + 基音周期的混合作为激励
能量衰减:每丢一帧,增益衰减约 2dB
抖动注入:对基音周期加入微小随机偏移,避免机械感
丢包帧生成:
LP 滤波器系数 = 上一帧的 LP 系数(略向平坦方向收缩)
基音延迟 = 上一帧的基音延迟 + 随机偏移(±1 sample)
激励 = 基音周期重复 × 衰减增益 + 随机噪声 × 噪声增益
输出 = LP 合成滤波器(激励)
Opus CELT 模式 PLC
Opus 的 CELT 模式(音乐/全带宽)使用不同的 PLC 策略:
保存最后一帧的 MDCT 频谱
丢包时,对频谱进行随机相位旋转
逆 MDCT 变换回时域
与前一帧做重叠相加
能量逐渐衰减
这种频域 PLC 对音乐信号效果更好,因为音乐的频谱结构比时域波形更稳定。
G.729 PLC
G.729 的内置 PLC:
使用最后一帧的 LP 系数和基音参数
自适应码本(基音预测)继续运行
固定码本用随机激励替代
增益逐帧衰减
连续丢包 > 6 帧后退化为舒适噪声
基于深度学习的 PLC
近年来,深度学习 PLC 取得了显著进展:
LPCNet PLC
Mozilla 的 LPCNet 将传统 LPC 分析与神经网络结合:
从历史帧提取 LPC 特征
神经网络预测丢失帧的 LPC 特征
用 LPCNet 声码器合成波形
质量接近原始信号
IETF DRED
Deep REDundancy (DRED) 是 Opus 的新扩展(正在标准化):
编码器用神经网络将最近几帧压缩为极低码率的冗余数据
冗余数据嵌入当前帧的 padding 中
丢包时,解码器用冗余数据 + 神经网络恢复丢失帧
可恢复长达数百毫秒的连续丢包
PLC 质量评估
评估 PLC 效果的方法:
方法 |
说明 |
工具 |
|---|---|---|
PESQ/POLQA |
与原始信号对比的客观评分 |
ITU-T P.862/P.863 |
PLCMOS |
微软开源的 PLC 专用 MOS 预测 |
|
主观测试 |
人工听音评分 |
ITU-T P.800 方法 |
频谱分析 |
观察 PLC 帧的频谱连续性 |
Audacity, MATLAB |
不同丢包率下的 PLC 效果参考(Opus SILK @ 16 kbps):
丢包率 |
无 PLC (MOS) |
有 PLC (MOS) |
说明 |
|---|---|---|---|
0% |
4.0 |
4.0 |
基准 |
5% |
2.5 |
3.6 |
PLC 效果显著 |
10% |
1.8 |
3.2 |
仍可接受 |
20% |
1.2 |
2.5 |
质量明显下降 |
30% |
1.0 |
1.8 |
勉强可用 |
小结
PLC 是实时通信音频质量的最后保障。从简单的帧重复到基于深度学习的预测,PLC 技术在不断进化。
对于 WebRTC 开发者,好消息是 Opus 和 NetEQ 已经内置了高质量的 PLC,通常不需要自己实现。但理解 PLC 的原理有助于:
选择合适的编解码器(Opus 的 PLC 远优于 G.711)
调优 FEC/NACK 策略(PLC 是最后手段,应优先用 FEC/NACK)
排查音频质量问题("机器音"可能是 PLC 过度触发)