3、RTP负载类型与编解码映射:动态PT与静态PT

聊到RTP,有个东西绕不开——负载类型(Payload Type,简称PT)。说白了,PT就是告诉接收端:“嘿,这包数据是啥编码格式?” 如果PT对不上,解码器就罢工,画面直接花掉或黑屏。

我刚开始接触WebRTC时,就被PT值搞晕过。为什么有的编码用96,有的用100?为什么不能统一?后来踩了坑才明白,这里头有历史包袱,也有设计智慧。

3.1 静态PT vs 动态PT:谁说了算?

RTP协议最初设计时,给一些老牌编解码器分配了固定编号,这就是静态PT。比如PCMU用0,PCMA用8,GSM用3。这些编号在RFC 3551里写死了,所有设备都得认。

但后来编解码器越来越多,VP8、VP9、H264、Opus……RFC那点编号根本不够分。于是IETF想了个办法:动态PT。范围是96到127,具体用哪个,由应用层通过SDP协商决定。

类型 PT范围 分配方式 典型例子
静态PT 0–95 RFC 3551固定分配 PCMU(0), PCMA(8), GSM(3)
动态PT 96–127 SDP协商决定 VP8(96), Opus(111)

核心区别:静态PT是“出厂设定”,动态PT是“现场配对”。WebRTC几乎只用动态PT,因为它的编解码器组合太灵活了。

3.2 WebRTC中常用的编解码器PT分配

WebRTC的PT分配,其实没有绝对标准。不同浏览器、不同版本可能不一样。但业界有个约定俗成的分配方案,我列出来供你参考。

编解码器 常用PT值 类型 备注
VP8 96 视频 WebRTC默认视频编码,兼容性最好
VP9 98 视频 压缩率更高,但解码开销大
H264 100 或 102 视频 硬件编码支持好,Safari/Chrome都认
Opus 111 音频 WebRTC默认音频编码,48kHz采样
G722 9 音频 静态PT,16kHz宽带音频
PCMU 0 音频 静态PT,8kHz窄带

个人习惯:我一般把VP8固定为96,H264固定为100,Opus固定为111。这样在抓包分析时,一眼就能认出编码类型。但记住,这只是惯例,不是标准。

3.3 SDP中的PT协商:到底怎么配对的?

PT值不是写死在代码里的。它通过SDP的m=行和a=rtpmap属性来声明。举个例子:

m=video 9 UDP/TLS/RTP/SAVPF 96 98 100
a=rtpmap:96 VP8/90000
a=rtpmap:98 VP9/90000
a=rtpmap:100 H264/90000

这段SDP的意思是:“我这路视频流支持三种编码,VP8用PT96,VP9用PT98,H264用PT100。时钟频率都是90000Hz。”

接收端收到后,会根据自己的能力选一个。比如Safari可能选H264,Chrome可能选VP8。选完后,后续的RTP包就带着对应的PT值发过来。

我曾经踩过的坑:有一次我写死PT=96是VP8,但对方SDP里把96分配给了H264。结果解码全乱套,画面全是马赛克。后来我学乖了——永远不要硬编码PT值,必须从SDP里动态解析。

3.4 动态PT的冲突风险

动态PT范围只有32个(96–127)。如果同时协商太多编解码器,或者有冗余的RTP扩展头,PT可能不够用。我见过一个极端案例:一个会议同时支持VP8、VP9、H264、H265、AV1,再加上3种FEC格式,PT直接爆了。

解决办法?精简编解码器列表。只保留真正需要的,别贪多。另外,有些实现会用PT值来区分不同的RTP流(比如 simulcast 的每层流),这更要注意别重复。

3.5 知识体系图:PT与编解码映射全流程

下面这张图,把PT的整个生命周期串起来了。从SDP协商,到RTP发包,再到接收端解码,每一步都离不开PT。

RTP负载类型与编解码映射流程 1. SDP Offer/Answer 2. 动态PT分配 3. RTP包封装 4. 网络传输 5. 接收端解析PT 6. 选择解码器播放 关键点: • PT值在SDP协商阶段动态分配,不写死在代码里 • 接收端根据PT值查找对应的编解码器,而不是靠猜测 • 动态PT范围有限(96-127),避免同时协商过多编码格式 避坑指南: • 不要硬编码PT值,必须从SDP中动态解析 • 同一会话中,不同RTP流的PT值不能重复

3.6 实战建议:如何安全地处理PT

说了这么多,总结几条我实际项目中的经验:

  • 永远从SDP解析PT:别信“默认值”,对方可能用不同的分配方案。
  • PT值要唯一:同一路RTP流里,一个PT只能对应一种编码。如果发现重复,优先用SDP里最后出现的那个。
  • 预留扩展空间:动态PT范围有限,别把所有鸡蛋放一个篮子里。如果支持太多编码,考虑用a=rtcp-fb等扩展来分担。
  • 日志里打上PT:调试时,把每个RTP包的PT值打出来。我习惯在日志里加一句 PT=96, codec=VP8,排查问题快很多。

一句话总结:PT是RTP包的“身份证”,动态PT是WebRTC的“灵活用工”。理解它,你就能在编解码切换、SDP协商、抓包分析时游刃有余。