NACK 与 RTX 重传 · 丢包了就重发

UDP 会丢包,WebRTC 用 NACK+重传补救:接收端发现序号缺失就发 NACK,发送端从历史重发。这一章讲清 NackTracker 怎么决定请求哪些包、RTX 为什么用独立的流承载重传,以及重传的适用边界——RTT 太大时重传就来不及了。

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

NACK 与 RTX 重传 · 丢包了就重发

UDP 会丢包,而视频对丢包尤其敏感(丢一个包可能让好几帧解不出)。WebRTC 对抗丢包的第一招,是最直接的:发现丢了就重发。这套机制叫 NACK + 重传,重传常走一条叫 RTX 的独立流。这一章拆开它。

NACK:接收端喊「重发」

序号让接收端能发现丢包——收到序号 100、102,那 101 就是丢了。接收端于是发一个 NACK(Negative ACKnowledgement,否定确认)告诉发送端「101 我没收到,重发」。发送端从 RtpPacketHistory 历史里取出 101 号包,重发。

决定「请求重传哪些包」的,是接收端的 NackTracker(modules/rtp_rtcp/source/nack_tracker.cc 一类):

NackTracker 不是「一发现缺号就立刻狂发 NACK」,它有策略。 要点:

  • 判断是丢包还是乱序:序号 101 没到,可能是真丢了,也可能只是乱序(101 比 102 晚到)。NackTracker 会稍等——给乱序一点到达时间,别把「晚到」误当「丢失」而无谓重传。
  • 控制重传请求的节奏:同一个包别反复请求太频繁(重传本身也占带宽),也别请求太久(过了播放时刻再来就没用了)。
  • 考虑 RTT:重传一来一回要一个 RTT,得判断「重传回来还赶不赶得上播放」。

这些策略,是「重传有用」和「重传别添乱」之间的精细平衡——重传不是免费的,发多了反而加重拥塞。

RTX:重传走独立的流

重传的包怎么发?最朴素的办法是原样重发(同序号同 SSRC)。但 WebRTC 更常用 RTX(RTP Retransmission,RFC 4588)——让重传走一条独立的 RTP 流:

RTX 给重传包配了独立的 SSRC、payload type 和序号空间——重传不再冒充原包,而是「另开一路」。 一个原始流(SSRC=A),配一个 RTX 流(SSRC=B)专发它的重传。重传 101 号包时,在 RTX 流里它有自己的新序号(比如 RTX 序号 5),包体里再带上「我其实是原始流的 101 号」。为什么这么绕?

  • 不打乱原始流的序号连续性:原始流的序号保持严格 +1,丢包检测、抖动计算才不被重传包干扰。
  • 重传流可独立统计:能清楚知道「重传占了多少带宽」,给拥塞控制参考。
  • 兼做带宽探测:g3doc/rtp.md 说的 RTX 探测就复用这条流——重发个旧包既探带宽、又万一有用。

代价是要多协商一个 payload type 和 SSRC。这是实时传输里「多一层间接、换取干净与灵活」的又一例。RTX 是否启用由 SDP 协商(a=rtpmap 里的 rtx)。

重传的边界:RTT 太大就来不及

重传不是万能的,它有个硬边界:

重传要一来一回一个 RTT,如果 RTT 大于「这段媒体还能等多久」,重传回来时媒体早该播了,纯属浪费。 举例:视频缓冲区只能容忍 100ms 延迟,而 RTT 是 300ms——你发 NACK、对端重传、包回来,已经 300ms 过去,这帧的播放时刻早过了,重传的包只能丢弃。所以重传适合低 RTT 场景(同城、好网络);高 RTT(跨国、卫星)下,重传越来越不划算,得靠不需要往返的 FEC 前向纠错来补。

这引出实时传输一个核心权衡:重传(NACK/RTX)省带宽但要往返、FEC 免往返但费带宽。WebRTC 常两者结合——低 RTT 主要靠重传,高 RTT / 高丢包补以 FEC。下一章就讲 FEC。

小结与下一章

NACK + 重传是对抗丢包的第一招:接收端靠序号发现缺包、发 NACK,发送端从历史重发。NackTracker 有策略(区分丢包 / 乱序、控节奏、看 RTT)。重传常走 RTX 独立流(独立 SSRC/PT/序号),不打乱原始流、可独立统计、兼做探测。重传的硬边界是 RTT——太大就来不及,得靠 FEC。

那个「不需要往返」的补丁,就是前向纠错 FEC。下一章看它怎么用冗余包在丢包发生的当下就恢复。👉 FEC 前向纠错。

参考资料

  • [1] libwebrtc 源码.modules/rtp_rtcp/source/nack_tracker.h、rtp_rtcp/source/rtp_packet_history.h(重传取包)。
  • [2] libwebrtc 源码.g3doc/rtp.md(RTX 流与探测)。
  • [3] IETF RFC 4585「NACK」、RFC 4588「RTP Retransmission (RTX)」。

本页目录