跳转至

EP04:传输技术三国杀:RTMP / SRT / WHIP

在 YouTube 打开

上集回顾 EP03《内容主权:自己可控,才是终极护城河》讲完,Module 0(破局)三集结束
下集预告 EP05《Simulcast 的原理和用途》

0. 本集目标

看完这一集,观众应该能做到两件事:

  1. 说清楚 RTMP、SRT、WHIP 三种推流协议在丢包和延迟上的具体权衡机制,不是只会背"TCP 不好、UDP 好"这种粗线条结论。
  2. 理解本项目为什么让 WHIP 和 SRT 共存,而不是二选一淘汰另一个——两者解决的是不同的问题。

1. 开场钩子(逐字稿要点)

Module 0 讲完了三个困境和整体架构,从这一集开始进入 Module 1,回到最基础的东西——推流协议。EP01 已经讲过 RTMP/HTTP-FLV 在弱网下的队头阻塞问题,这一集把这个结论往下挖一层:RTMP、SRT、WHIP 具体是怎么处理"丢包"这件事的?为什么本项目同时支持 SRT 和 WHIP,而不是只留一个?


2. RTMP:被淘汰但值得理解的起点

RTMP(Real-Time Messaging Protocol)通常建立在持久 TCP 连接上,握手完成后,消息被切成 chunk 并在多个 chunk stream 上复用。AMF 主要用于命令和数据消息的对象序列化;音频、视频消息承载相应编码数据,不能笼统地说成"媒体数据用 AMF 编码"。RTMPS 则是在 TLS 上承载 RTMP,为链路提供机密性和完整性;它不消除 TCP 队头阻塞。

这套设计在它诞生的年代是合理的:TCP 的可靠传输省去了协议自己处理丢包重传的麻烦。但代价正是 EP01 讲过的队头阻塞——任何一个 TCP 分节丢失,后面已经到达的数据都必须排队等它重传完成,这个机制在设计 RTMP 的时候不是问题(当时的典型场景是稳定的有线网络推流),放到今天的移动网络、弱网场景下就成了硬伤。

今天 RTMP 在生态里的位置已经很单薄:播放侧因为 Flash 停更基本退场(EP01 讲过),仅剩的价值是"推流入口"——一些老旧的编码器/推流工具还只认 RTMP。但连这一层价值也在被取代:SRT 和 WHIP 都提供了比 RTMP 更适合当代网络环境的推流方式,这也是为什么本项目对外推流协议清单里没有 RTMP。


3. SRT:为弱网设计的现代化选择

SRT(Secure Reliable Transport)建立在 UDP 之上,面向不稳定网络中的低时延可靠传输。理解它时要把三个机制分开:

  • ARQ:接收端根据序列号发现缺包并发送 NAK,发送端在数据仍有时效时重传。它解决"怎么恢复丢包"。
  • TSBPD:依据发送时间戳和协商的 latency 安排包何时交付,吸收网络抖动并恢复发送时序。它解决"何时交付",不是 ARQ 窗口的同义词。
  • TLPKTDROP/过期包丢弃:启用并满足条件时,放弃已来不及按计划交付的数据,使发送端和接收端跳过过期包。它解决"何时停止补救",不能写成 TSBPD 自动丢包。

latency 给重传和抖动吸收提供时间预算,调大通常提高恢复机会并增加交付等待,调小则相反。但该参数不是整个 SRT 会话的严格数学时延上界:握手、网络排队、应用缓冲、配置差异、断线和重连都在它之外。本项目案例应以端到端埋点为准,不再用若干配置值相加推导总时延。

SRT 可配置基于 AES 的 payload 加密。具体模式和密钥长度取决于协议版本及实现配置;它是传输链路保护,不自动等同于跨所有中间处理节点的端到端加密。

SRT 解决的核心问题是"弱网上行还能不能把画面完整送到",用延迟换鲁棒性是它的设计初衷,不是缺陷。


4. WHIP:把 WebRTC 标准化成一套推流协议

WHIP(WebRTC-HTTP Ingestion Protocol)本质上不是一个全新的传输协议,而是给 WebRTC 补上了一套标准化的"推流签约流程"(用 HTTP 完成 SDP offer/answer 交换),媒体数据仍然走 WebRTC 原生的栈:

  • ICE 负责打通网络路径(含 NAT 穿透的地址协商)。
  • DTLS-SRTP 负责 WebRTC 对等连接上的媒体链路加密。若媒体在 SFU/Edge 终止 SRTP 后被处理或重新加密转发,它是逐段(hop-by-hop)保护,不是只有业务通信双方可解密的 E2EE;真正的 E2EE 需要额外的媒体帧级加密与密钥分发方案。
  • RTP 承载媒体,配合 NACK(选择性重传请求)和可选的前向纠错(FEC)处理丢包,拥塞控制算法(如 GCC)动态调整发送码率。

WHIP 没有 SRT 的 TSBPD。RTP 实现通常会维护按包数或字节数计的接收/重排历史,以发现乱序、生成 NACK 或保存可重传数据;例如本项目的 WebRTCInboundRTPBufferSize 是包容量。包缓存数量不等于时间窗口:相同 512 个包在不同码率、包长和帧率下覆盖的时间不同,也不能由它直接推出播放等待时延。实际等待还由 jitter buffer、NACK 策略、解码截止时间和拥塞控制共同决定。

WHIP 已正式发布为 RFC 9725(2025),不再是 IETF 草案。它标准化 WebRTC 摄取的 HTTP 信令与资源生命周期;媒体安全、拥塞控制和丢包恢复仍来自 WebRTC/RTP 体系。


5. 三者横向对比

维度 RTMP SRT WHIP
传输层 TCP UDP + ARQ UDP + RTP(NACK / FEC / 拥塞控制)
丢包处理 TCP 必须重传并按序交付,可能队头阻塞 ARQ 恢复;TSBPD 定时交付;配置过期包丢弃时可跳过迟到数据 NACK/FEC 依协商与实现使用;jitter buffer 和解码截止策略决定是否等待
延迟边界 无严格数学上界 latency 是工程预算,不是无条件端到端上界 动态缓冲与拥塞控制,无无条件数学上界
加密 RTMP 本身无加密;RTMPS 使用 TLS 可配置 AES payload 加密 强制 DTLS-SRTP 链路加密;不自动等于 E2EE
浏览器原生支持 已不支持(依赖已停更的 Flash) 不支持 原生支持(标准 WebRTC API)
典型定位 历史遗留,正在退出 弱网上行的现代选择 主流实时推流/播放协议
本项目是否支持 不支持 支持(入库) 支持(入库 + 播放统一走 WHEP)

6. 本项目怎么选:统一信号,差异化处理

WHIP 和 SRT 在本项目里不是"谁取代谁"的关系,而是同时提供,服务不同的推流场景:网络干净、追求最低延迟时优先 WHIP;上行不稳定、需要更强鲁棒性时用 SRT 换一点延迟。

两者的接收机制并不等价:SRT 的 TSBPD 是按时间戳调度交付,RTP 包缓存通常按包数/字节数保存历史。本项目可以把两侧统计归一化为不可恢复丢包率(Unrecoverable Loss Rate, ULR)用于产品策略,但这不是 SRT 与 WebRTC 共同定义的标准指标。计算时还必须统一采样区间、分母、重传去重和计数器重置语义,不能只因字段名字相似就直接比较。这套统一信号已经是本项目 WHIP/SRT 共用的同一套降级状态机(设计见 docs/design/publish-degrade-protocol.zh-CN.md):触发阈值 degradeRaisePct 默认 0.8%、恢复阈值 degradeLowerPct 默认 0.3%,采样周期 degradeSampleSec 默认 6 秒、每次状态转移后冷却 degradeObservationSec 默认 60 秒——这些是配置默认值,不是全网保证的 SLA,正式生产阈值仍需按链路实测校准。

降级动作分两步,代价从低到高:

  1. 先降编码码率:实时生效,不中断推流。
  2. 码率降到底仍不达标,才降分辨率(砍同播层数):需要重启推流,约 1 秒中断。

这个顺序背后的逻辑很直接:调码率零代价,可以频繁触发;调层数有中断代价,只有在"压到底都不够"时才动用。"约 1 秒中断"目前主要是 SRT 侧的生产观察(mmx 侧有专门的日志埋点 SRT publish resumed on path X after <gap> of ingest interruption 用来度量真实重连耗时),不是跨网络环境的承诺值;WHIP 侧目前重启代价还缺同等粒度的生产测量。


7. 框图

7.1 三种协议的丢包处理机制对比

【RTMP / RTMPS(TCP)】
丢包 → TCP 必须重传 → 按序交付 → 后续字节排队等待 → 等待可持续增长

【SRT(UDP)】
ARQ:发现缺包 → NAK → 在仍有时效时重传
TSBPD:按时间戳 + latency 安排交付时间
TLPKTDROP:启用且包已过期时,跳过来不及交付的数据

【WHIP(WebRTC/RTP,典型 UDP 路径)】
序列号与 RTCP 反馈:发现丢包 → 可用 NACK/FEC 尝试恢复
jitter buffer:按动态目标处理抖动和播放时序
解码截止策略:恢复已无价值时可丢帧继续播放
注意:按包计的 RTP 缓存容量不是毫秒窗口

7.2 统一决策语义,不直接统一原始计数器

SRT 原生统计                         RTP/WebRTC 原生统计
loss / retrans / drop / too-late     sequence gap / late / RTX / FEC
         │                                      │
         └──────────────┬───────────────────────┘
                        ▼
 接收端按统计窗口、原包身份、恢复结果和播放 deadline 派生产品指标
                        │
          ┌─────────────┴─────────────┐
          ▼                           ▼
 指标持续恶化 → 降码率/降档      指标稳定恢复 → 谨慎升档

两边可以统一"何时降级、何时恢复"的产品决策语义,但不能把不同协议的累计计数器直接套进同一个公式。正式阈值还需要按协议、方向、编码档位和真实网络样本分别校准。


8. 结尾与下集预告(逐字稿要点)

这一集把 EP01 提过的"队头阻塞"往下挖了一层:RTMP/RTMPS 继承 TCP 的可靠有序字节流语义;SRT 用 ARQ、TSBPD 和可选的过期包丢弃配合;WHIP 则复用 WebRTC/RTP 的反馈、拥塞控制和动态缓冲。它们都没有脱离实现与网络条件的数学延迟上界。本项目让 WHIP 和 SRT 共存,并把各自统计归一化后用于同一套产品降级策略。

下一集,我们讲 Simulcast——同一路推流怎么一次性编出多档画质,服务端不用转码的原理是什么。