10、RTP头扩展与SSRC:SSRC的作用与冲突处理、RTP头扩展协商(abs-send-time、twcc等)

各位同学,今天我们聊一个在WebRTC开发中绕不开的话题——RTP头扩展和SSRC。说实话,这两个东西在刚入行时很容易被忽略,但真正做线上问题排查时,它们往往是关键线索。我自己就吃过不少亏,今天把这些经验分享给大家。

10.1 SSRC:媒体流的“身份证”

SSRC全称是Synchronization Source,同步源标识符。你可以把它理解成每个RTP流的唯一ID。为什么需要它?因为一个WebRTC连接里可能同时跑着音频、视频、甚至屏幕共享流,接收端得知道哪个包属于哪条流。

SSRC是一个32位的随机数,在会话开始时生成。我习惯把它比作“临时身份证”——只在当前会话中有效,但必须保证唯一。

SSRC的核心作用:

  • 流标识:区分同一连接中的不同媒体流
  • 同步参考:用于计算RTP时间戳和序列号的基准
  • 冲突检测:当两个端点意外使用了相同SSRC时,需要处理
  • 统计关联:RTCP的Sender Report和Receiver Report都通过SSRC关联到具体流

嗯,这里要注意:SSRC不是固定的。每次重新协商或者ICE重启时,都可能生成新的SSRC。我在项目中遇到过一个问题——客户端缓存了旧的SSRC,导致接收端一直收不到视频,排查了半天才发现是SSRC对不上。

10.2 SSRC冲突处理:当“撞车”发生时

SSRC是随机生成的,理论上存在冲突可能。虽然概率很低(32位空间嘛),但WebRTC规范还是设计了冲突处理机制。

冲突检测的流程是这样的:

  1. 接收端收到RTP包,检查SSRC是否与已有流重复
  2. 如果发现冲突,通过RTCP的BYE包通知发送端
  3. 发送端收到BYE后,重新生成一个新的SSRC
  4. 发送端用新SSRC继续发送数据

我曾经踩过的坑:有一次做多路视频会议,服务端转发的SSRC没有做去重处理,导致两个参与者的视频流SSRC冲突。结果就是画面疯狂闪烁,因为解码器在两条流之间来回切换。后来我们加了一层SSRC映射,才彻底解决。

实际开发中,我建议你在应用层也做一层SSRC唯一性校验。虽然协议层有冲突处理,但那个过程会有短暂的丢包或花屏。提前规避总比事后补救好。

10.3 RTP头扩展:给数据包“加料”

RTP标准头只有12字节,能携带的信息有限。但实际场景中,我们需要传递更多元数据——比如发送时间、传输拥塞信息、视频旋转角度等。这时候就需要RTP头扩展。

RTP头扩展的格式在RFC 5285中定义。它位于RTP固定头和负载之间,通过一个profile-specific标识符来区分不同的扩展类型。

常见的RTP头扩展类型:

扩展类型 ID 用途 我常用的场景
abs-send-time 通常为3 发送端绝对时间戳 带宽估计、延迟计算
transport-wide-cc (twcc) 通常为5 传输级拥塞控制 丢包率、抖动计算
video-orientation 通常为1 视频旋转角度 移动端横竖屏切换
playout-delay 通常为6 播放延迟控制 直播场景的延迟调节

10.4 abs-send-time:发送端时间戳

abs-send-time,顾名思义,就是发送端在发送RTP包时的绝对时间。它用24位表示,精度是毫秒级别。为什么需要这个?因为接收端可以通过它计算单向延迟。

计算公式很简单:

单向延迟 = 接收端收到时间 - abs-send-time

但要注意,接收端和发送端的时钟可能不同步。所以实际应用中,我们通常用相对值而不是绝对值。我个人习惯用abs-send-time来做延迟趋势分析,而不是精确测量。

小技巧:在Chrome的webrtc-internals中,你可以看到每个RTP包的abs-send-time值。如果发现这个值异常(比如比当前时间还大),说明发送端时钟有问题,赶紧检查NTP同步。

10.5 TWCC:传输级拥塞控制

TWCC(Transport-Wide Congestion Control)是WebRTC中非常重要的一个扩展。它给每个RTP包分配一个传输序列号,接收端通过RTCP反馈这些序列号的到达情况,发送端就能精确知道哪些包丢了、延迟多大。

TWCC的工作流程:

  1. 发送端给每个RTP包打上传输序列号(在头扩展中)
  2. 接收端收到包后,记录序列号和到达时间
  3. 接收端定期发送RTCP反馈包,包含所有序列号的到达状态
  4. 发送端根据反馈计算丢包率、抖动、延迟
  5. 发送端调整发送码率

说实话,TWCC比传统的RTCP RR(Receiver Report)精确得多。RR只能报告整体丢包率,而TWCC能精确到每个包。我在做弱网优化时,TWCC帮了大忙——能快速发现是哪一段网络出了问题。

10.6 头扩展的SDP协商

RTP头扩展不是想用就能用的,需要在SDP中协商。协商过程通过extmap属性完成。

SDP中的extmap格式:

a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01

这里的数字(3、5)是本地ID,可以任意分配,只要双方对应上就行。URI则标识了扩展类型。

协商规则:

  • 发送方列出所有支持的扩展
  • 接收方回复自己支持的扩展
  • 双方取交集,确定最终使用的扩展列表
  • 如果某个扩展协商失败,发送方就不应该使用它

我曾经犯过的错:有一次我写死了extmap ID为3,但对方用的是5。结果abs-send-time完全没生效,带宽估计一直不准。后来才意识到,extmap ID是本地分配的,不能硬编码。正确的做法是解析SDP后动态映射。

10.7 知识体系总览

下面这张图总结了本章的核心知识点,方便你快速回顾:

RTP头扩展与SSRC知识体系 SSRC(同步源标识符) 流标识与同步参考 冲突检测与处理 RTCP统计关联 RTP头扩展(RFC 5285) abs-send-time transport-wide-cc video-orientation playout-delay SDP协商(extmap属性) SSRC是流的身份证,RTP头扩展是包的附加信息,SDP协商决定用哪些扩展

从图中可以看出,SSRC和RTP头扩展是WebRTC媒体协商中两个紧密相关的部分。SSRC负责流的标识和同步,头扩展负责携带额外的元数据。而SDP协商则是它们能正常工作的前提。

好了,这一章的内容就到这里。SSRC的冲突处理、abs-send-time和TWCC的用法,都是实际开发中经常碰到的。下次遇到视频卡顿或者带宽估计不准,不妨先检查一下这些基础设置。


公众号:蓝海资料掘金营,微信deep3321