丢包恢复方案总览:FEC、ARQ、PLC 与前向/后向纠错对比

各位同学,欢迎来到第四章。前面我们聊了 RTSP 推流中丢包是怎么发生的,也看了 RTP 序列号和时间戳怎么帮我们「发现」丢包。但发现只是第一步,真正要命的是——发现了,然后呢?

这一章,我们把所有丢包恢复手段摆上桌面,做个全景式的对比。我个人习惯把方案分成两大类:前向纠错和后向纠错。说白了,一个是在发送前就「打预防针」,一个是丢包了再「亡羊补牢」。两种思路各有各的适用场景,没有银弹。

4.1 三大核心恢复技术速览

先给个总览。目前业界主流的丢包恢复技术,归纳起来就三个:FEC、ARQ、PLC。我画了张图,帮你快速建立全局认知。

丢包恢复方案总览 丢包恢复方案 前向纠错 (FEC) 后向纠错 (ARQ) 媒体层 FEC 传输层 FEC NACK 重传 选择性重传 PLC 丢包隐藏 波形拼接 PLC 参数模型 PLC 深度学习 PLC 前向纠错:发送端主动添加冗余;后向纠错:接收端请求重传;PLC:接收端本地修复

嗯,这张图把整个体系串起来了。你可能会问:PLC 怎么单独拉了一条虚线?因为它既不属于前向也不属于后向——它是在接收端「猜」出丢失的数据,不依赖发送端做任何额外操作。这个后面会细讲。

4.2 前向纠错(FEC):用冗余换可靠性

前向纠错的核心思想很简单:发送端在原始数据之外,额外发送一些冗余数据。接收端即使丢了一部分包,也能靠冗余信息把原始数据恢复出来。

我在项目中遇到过最典型的场景——卫星直播。卫星链路的延迟动不动就 500ms 以上,你根本等不起重传。这时候 FEC 就是救命稻草。

4.2.1 媒体层 FEC

媒体层 FEC 直接对音频或视频的编码比特流做保护。比如 Opus 编码器内置的 in-band FEC,它会在当前包中携带上一帧的低质量副本。丢包时,接收端直接用这个副本顶上去。

关键参数:冗余度

冗余度 = 冗余数据量 / 原始数据量。冗余度越高,抗丢包能力越强,但带宽开销也越大。实际项目中,我一般建议冗余度控制在 20%~50% 之间,具体看链路质量。

4.2.2 传输层 FEC

传输层 FEC 工作在 RTP 层面,最常见的是 XOR 校验和 Reed-Solomon 码。拿 XOR 举例:每 N 个原始包生成 1 个校验包,这 N+1 个包中只要任意丢失 1 个,就能通过 XOR 恢复。

// 简单 XOR FEC 示例(N=4, 生成 1 个校验包)
原始包: P1, P2, P3, P4
校验包: P_fec = P1 ^ P2 ^ P3 ^ P4

// 接收端收到 P1, P2, P4, P_fec,丢失 P3
恢复: P3 = P1 ^ P2 ^ P4 ^ P_fec

注意:XOR FEC 只能恢复 1 个丢包。如果 N=4 的组内丢了 2 个包,XOR 就无能为力了。这时候需要 Reed-Solomon 或 LDPC 等更复杂的纠错码。

4.3 后向纠错(ARQ):按需重传

后向纠错,说白了就是「丢了再要」。接收端发现丢包后,向发送端发送 NACK(Negative ACK)请求重传。发送端收到 NACK 后,把丢失的包重新发一次。

ARQ 的优势是带宽利用率高——链路质量好的时候几乎零开销。但代价是引入了额外的往返延迟(RTT)。

我曾经在一个跨国直播项目中踩过坑:服务器在美西,观众在东南亚,RTT 接近 300ms。ARQ 重传一次就要 600ms,画面卡得没法看。后来我们改用了 FEC + ARQ 混合方案,才把问题解决。

3.3.1 NACK 重传 vs 选择性重传

特性 NACK 重传 选择性重传
触发条件 接收端检测到丢包 发送端根据反馈选择性重传
延迟 至少 1 个 RTT 至少 1 个 RTT
带宽开销 仅重传丢失的包 仅重传丢失的包
实现复杂度 低 中
适用场景 低延迟、低丢包率 高丢包率、需要优先级控制

我的建议:如果 RTT < 50ms 且丢包率 < 5%,纯 ARQ 就够用。RTT 超过 100ms 时,一定要考虑 FEC 兜底。

4.4 PLC(丢包隐藏):让耳朵「听不见」丢包

PLC 和前两种方案完全不同。它不修复数据,而是在接收端用算法「填补」丢失的音频或视频片段。对音频来说,就是根据前后波形「猜」出中间缺失的部分。

你想想看,人耳对毫秒级的音频中断其实不太敏感。PLC 就是利用这个心理声学特性,用几十毫秒的「假数据」蒙混过关。

4.4.1 三种主流 PLC 方法

  • 波形拼接 PLC:把丢包前后的波形片段复制拼接。实现简单,适合语音。
  • 参数模型 PLC:用线性预测或正弦模型生成丢失段。质量更高,但计算量大。
  • 深度学习 PLC:用神经网络生成上下文相关的填补内容。效果最好,但需要模型推理。

我记得有一次做 WebRTC 集成,默认的 PLC 在音乐场景下效果很差,拼接出来的声音像「卡带」。后来换成基于深度学习的 PLC,虽然 CPU 占用高了 5%,但音质提升非常明显。

4.5 前向纠错 vs 后向纠错:一张表说清楚

对比维度 前向纠错(FEC) 后向纠错(ARQ)
冗余策略 发送端主动添加冗余 接收端按需请求重传
延迟影响 无额外延迟(固定延迟) 增加至少 1 个 RTT
带宽开销 固定冗余(即使无丢包) 仅丢包时产生开销
抗突发丢包 强(取决于冗余度) 弱(连续丢包时重传压力大)
实现复杂度 中高(纠错码算法) 低(NACK 逻辑简单)
典型场景 卫星、广播、实时直播 低延迟互动、视频会议

核心结论:没有完美的方案。FEC 用固定带宽换低延迟,ARQ 用可变延迟换带宽效率。实际工程中,混合方案才是常态——比如用 FEC 保护关键帧,用 ARQ 保护非关键帧。

4.6 如何选择?我的实战经验

说了这么多理论,最后给点实在的。我一般按以下步骤做技术选型:

  1. 先看 RTT:RTT < 30ms,纯 ARQ 即可;RTT > 100ms,必须上 FEC。
  2. 再看丢包率:丢包率 < 1%,ARQ 足够;丢包率 > 5%,FEC 冗余度至少 30%。
  3. 最后看内容类型:语音通话优先 PLC + ARQ;音乐/视频直播优先 FEC + PLC。