# Transport-CC 反馈 · 通往拥塞控制的桥

> 现代 WebRTC 拥塞控制的信号源，是 Transport-CC 反馈：发送端给每个包打一个全局序号，接收端如实报回每个包的到达时间，发送端据此算出延迟变化。这一章讲清这套反馈怎么运转、为什么把带宽估计放在发送端，以及它如何连接第 4 与第 5 部分。

- 作者：David（道雾轩）
- 专栏：音视频与 WebRTC 详解（https://daiw.org/manual/webrtc.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/webrtc/transport-cc
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# Transport-CC 反馈 · 通往拥塞控制的桥

WebRTC 到底该**发多快**？发太快网络就堵、丢包飙升；发太慢又浪费带宽、画质打折。要动态找到这个「刚刚好」的速率，得先有精确的**信号**——知道网络当前的拥塞状况。现代 WebRTC 的信号源，就是 **Transport-CC（Transport-wide Congestion Control）反馈**。它是第 4 部分（RTP/RTCP）通往[第 5 部分（拥塞控制）](https://daiw.org/manual/webrtc/source-map)的桥。

## 机制：打全局序号，报到达时间

Transport-CC 的运转，是发送端和接收端一场精心配合：

<Callout type="info">
  **① 发送端给每一个发出的包（跨所有流）打一个连续的全局序号——[transport-wide-cc 序号头扩展](https://daiw.org/manual/webrtc/rtp-header-extensions)。② 接收端记下每个序号的包的**精确到达时间**。③ 接收端周期性地把「哪些序号、分别何时到达」通过 [RTCP 的 `TransportFeedback` 报文](https://daiw.org/manual/webrtc/rtcp-feedback)报回发送端。④ 发送端于是同时握有「每个包我何时发的」和「它何时到的」，算出**单向延迟怎么变化**。**

  这个「延迟变化」是拥塞的**先兆信号**：如果包的传输延迟在**逐渐变大**，说明网络的缓冲区正在**排队堆积**——拥塞即将发生，该[降速](https://daiw.org/manual/webrtc/source-map)了；如果延迟平稳，说明还有余量，可以[试着提速](https://daiw.org/manual/webrtc/payload-types)。**在丢包真正发生之前，延迟的变化就预警了拥塞**——这让 WebRTC 能「未堵先让」，比「丢了才反应」快得多。这正是 [GCC 延迟based 带宽估计](https://daiw.org/manual/webrtc/source-map)的核心输入（[第 5 部分](https://daiw.org/manual/webrtc/source-map)详解）。
</Callout>

对应的类是 [`TransportFeedback`](https://daiw.org/manual/webrtc/rtcp-feedback)（`modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h`，继承 [`Rtpfb`](https://daiw.org/manual/webrtc/rtcp-feedback)）——它高效地编码「一串序号 + 各自的到达时间差」，一个 RTCP 包就能报回几十上百个包的到达情况。

## 为什么把估计放在发送端

[上一章](https://daiw.org/manual/webrtc/rtcp-feedback)提过 Transport-CC 相对老的 REMB 的关键转变——**把带宽估计从接收端搬到发送端**。这里再点透其深意：

<Callout type="info">
  **只有发送端同时知道「发送时间」和「到达时间」，才能算出真正的延迟变化。** 接收端只知道包**何时到**，不知道它**何时被发出**，所以它**算不出单向延迟的绝对变化**——REMB 时代接收端只能用较粗的方式估。而 Transport-CC 让接收端**只当忠实的记录员**（报原始到达时间，不做判断），把估计的活儿交给**信息最全的发送端**。发送端有完整数据，能跑[更精细的算法](https://daiw.org/manual/webrtc/source-map)（trendline 等），估得更准、反应更快。

  这是分布式系统一个反复出现的智慧：**决策放在信息最完整的地方，其他节点只提供原始观测。** Transport-CC 把它用在了拥塞控制上，效果是 WebRTC 拥塞控制的一次代际提升。代价是每个包多带几字节的[序号头扩展](https://daiw.org/manual/webrtc/rtp-header-extensions)、以及周期性的反馈包——但相比它带来的精度，非常划算。
</Callout>

## 一张反馈闭环图

```mermaid
sequenceDiagram
    participant S as 发送端
    participant R as 接收端
    S->>R: RTP 包(带 transport-cc 全局序号 1,2,3…)
    Note over R: 记录每个序号的到达时间
    R->>S: RTCP TransportFeedback(序号 1@t1, 2@t2, 3@t3…)
    Note over S: 有了发送时间 + 到达时间<br/>→ 算单向延迟变化 → 估带宽(第 5 部分)
    S->>R: 按新估的码率继续发(该快则快,该慢则慢)
```

这是一个**持续运转的闭环**：发包 → 报到达 → 估带宽 → 调速率 → 再发包……每隔几十毫秒转一圈，让发送速率**始终贴着网络的实时容量**。

## 小结与第 4 部分回顾

**Transport-CC** 是现代拥塞控制的信号源：发送端给[每个包打全局序号](https://daiw.org/manual/webrtc/rtp-header-extensions)，接收端**如实报回每个包的到达时间**（[`TransportFeedback`](https://daiw.org/manual/webrtc/rtcp-feedback) RTCP），发送端据此算**延迟变化**——在丢包前就预警拥塞。把估计**放在信息最全的发送端**，是它相对 [REMB](https://daiw.org/manual/webrtc/rtcp-feedback) 的代际提升。它是一个持续的**反馈闭环**，让发送速率贴着网络容量。

**第 4 部分「RTP/RTCP」到此完整**：[RTP 包](https://daiw.org/manual/webrtc/rtp-packet) → [头扩展](https://daiw.org/manual/webrtc/rtp-header-extensions) → [PT 分配](https://daiw.org/manual/webrtc/payload-types) → [模块中枢](https://daiw.org/manual/webrtc/rtp-rtcp-module) → [发送路径](https://daiw.org/manual/webrtc/rtp-sender) → [RTCP 报告](https://daiw.org/manual/webrtc/rtcp-reports) → [反馈](https://daiw.org/manual/webrtc/rtcp-feedback) → [NACK/RTX](https://daiw.org/manual/webrtc/nack-rtx) → [FEC](https://daiw.org/manual/webrtc/fec) → Transport-CC。还差接收侧的分流和帧变换钩子——下一章补上，再进入拥塞控制。👉 [RtpDemuxer 与帧变换](https://daiw.org/manual/webrtc/rtp-demuxer)。

## 参考资料

- [1] libwebrtc 源码.`modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h`、`rtp_header_extensions.h`（transport-cc 序号）。
- [2] IETF「RTP Extensions for Transport-wide Congestion Control」草案。
- [3] 关联[第 5 部分拥塞控制](https://daiw.org/manual/webrtc/source-map)——本反馈的消费者。
