SDP详解

经上面的介绍后,相信你已经对WebRTC中的SDP有了一定的了解,但WebRTC的SDP中还有很多小细节,这些小细节对于我们理解WebRTC同样重要。代码7.11对WebRTC的SDP进行了完整的注释,以便读者可以随时查阅参考。

代码7.11 SDP完整信息
// ===============================================
// SDP 会话描述
// ===============================================
// 版本信息
v=0
// 会话的创建者
o=- 8567802084787497323 2 IN IP4 127.0.0.1
// 会话名
s=-
// 会话时长
t=0 0
// 音视频传输采用多路复用方式,通过同一个通道传输
// 这样可以减少对 ICE 资源的消耗
a=group:BUNDLE 0 1
// WMS(WebRTC Media Stream)
// 因为上面的 BUNDLE 使得音视频可以复用传输通道
// 所以 WebRTC 定义一个媒体流来对音视频进行统一描述
// 媒体流中可以包含多路轨(音频轨、视频轨……)
// 每个轨对应一个 SSRC
a=msid-semantic: WMS 3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt
// ===============================================
// 音视频媒体描述
// ===============================================
// 音频媒体描述
// 端口 9 忽略,端口设置为 0 表示不传输音频
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
// 网络描述, 忽略!WebRTC 不使用该属性
c=IN IP4 0.0.0.0
// 忽略!WebRTC 不使用该属性
a=rtcp:9 IN IP4 0.0.0.0
// 用于 ICE 有效用户的验证
// ufrag 表示用户名(随机值)
a=ice-ufrag:r8+X
// 密码
a=ice-pwd:MdLpm2pegfysJ/VMCCGtZRpF
// 收信 candidate 方式
a=ice-options:trickle
// 证书指纹,用于验证 DTLS 证书有效性
a=fingerprint:sha-256 53:08:1A:66:24:C7:45:31:0A:EA:9E:59:97:A9:15:3A:EC:60:1F:85:85:5B:B8:EC:D4:77:78:9A:46:09:03:2A
// 用于指定 DTLS 用户角色
a=setup:actpass
// BUNDLE 使用,0 表示音频
a=mid:0
// 音频传输时 RTP 支持的扩展头
// 发送端是否音频 level 扩展,可参考 RFC6464
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
// NTP 时间扩展头
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
// transport-CC 的扩展头
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
// 与 RTCP 中的 SDES(Source Description) 相关的扩展头
// 通过 RTCP 的 SDES 传输 mid
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
// 通过 RTCP 的 SDES 传输 rtp-stream-id
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
// 通过 RTCP 的 SDES 传输重传时的 rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
// 音频数据传输方向
// sendrecv 既可以接收音频,又可以发送音频
a=sendrecv
// 记录音频与媒体流的关系
a=msid:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt 67eb8a85-f7c0-4cad-bd62-41cae9517041
// RTCP 与 RTP 复用传输通道
a=rtcp-mux
// PT=111 代表音频编码器 opus/采样率 48000/双通道
a=rtpmap:111 opus/48000/2
// 使用 Opus 时,支持 RTCP 中的 Transport-CC 反馈报文
a=rtcp-fb:111 transport-cc
// 使用 Opus 时,每个视频帧的最小间隔为 10ms, 使用带内频率
a=fmtp:111 minptime=10;useinbandfec=1
// PT=103 代表音频编码器 ISAC/采样率 16000
a=rtpmap:103 ISAC/16000
// PT=104 代表音频编码器 ISAC/采样率 32000
a=rtpmap:104 ISAC/32000
// PT=9 代表音频编码器 G722/采样率 8000
a=rtpmap:9 G722/8000
// PT=0 未压缩音频数据 PCMU/采样率 8000
a=rtpmap:0 PCMU/8000
// PT=8 未压缩音频数据 PCMA/采样率 8000
a=rtpmap:8 PCMA/8000
// PT=106 舒适噪声(Comfort Noise, CN)/采样率 32000
a=rtpmap:106 CN/32000
// PT=106 舒适噪声/采样率 16000
a=rtpmap:105 CN/16000
// PT=106 舒适噪声/采样率 8000
a=rtpmap:13 CN/8000
// PT=110 SIP DTMF 电话按键/采样率 48000
a=rtpmap:110 telephone-event/48000
// PT=112 SIP DTMF 电话按键/采样率 32000
a=rtpmap:112 telephone-event/32000
// PT=113 SIP DTMF 电话按键/采样率 16000
a=rtpmap:113 telephone-event/16000
// PT=116 SIP DTMF 电话按键/采样率 8000
a=rtpmap:126 telephone-event/8000
// 源 933825788 的别名
a=ssrc:933825788 cname:Tf3LnJwwJc0lgnxC
// 记录源 SSRC 与音频轨和媒体流的关系
a=ssrc:933825788 msid:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt 67eb8a85-f7c0-4cad-bd62-41cae9517041
// 记录源 SSRC:933825788 属于哪个媒体流
a=ssrc:933825788 mslabel:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt
// 记录源 SSRC:933825788 属于哪个音频轨
a=ssrc:933825788 label:67eb8a85-f7c0-4cad-bd62-41cae9517041
// ===============================================
// 视频媒体描述
// ===============================================
// 视频媒体描述
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 121 127 120 125 107 108 109 124 119 123
// 网络描述, 忽略!WebRTC 不使用该属性
c=IN IP4 0.0.0.0
// 忽略!WebRTC 不使用该属性
a=rtcp:9 IN IP4 0.0.0.0
// 与音频一样,用于验证用户的有效性
// 如果音视频复用传输通道,只用其中一个即可
a=ice-ufrag:r8+X
a=ice-pwd:MdLpm2pegfysJ/VMCCGtZRpF
// 与音频一样,设置收集 Candidate 的方式
a=ice-options:trickle
// 证书指纹,用于验证 DTLS 证书有效性
a=fingerprint:sha-256 53:08:1A:66:24:C7:45:31:0A:EA:9E:59:97:A9:15:3A:EC:60:1F:85:85:5B:B8:EC:D4:77:78:9A:46:09:03:2A
// 用于指定 DTLS 用户角色
a=setup:actpass
// media id 1
a=mid:1
// 视频传输时 RTP 支持的扩展头
// toffset(TransportTime Offset)
// RTP 包中的 timestamp 与实际发送时的偏差
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
// 视频旋转角度的扩展头
a=extmap:13 urn:3gpp:video-orientation
// Transport-CC 扩展头
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
// 发送端控制接收端渲染视频的延时时间
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
// 指定视频的内容,它有两种值:未指定和屏幕共享
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
// 该扩展仅在每个视频帧最后一个包中出现
// 其存放 6 个时间戳,分别为:
// 1. 编码开始时间
// 2. 编码完成时间
// 3. 打包完成时间
// 4. 离开 pacer 的最后一个包的时间
// 5. 预留时间 1
// 6. 预留时间 2
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
// 携带 mid 的扩展头
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
// 携带 rtp-stream-id 的扩展头
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
// 重传时携带的 rtp-stream-id 的扩展头
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
// 视频数据传输方向
// sendrecv,既可以发送,又可以接收视频数据
a=sendrecv
// media stream id
a=msid:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt f5d231d9-f0f7-4cd2-b2bc-424f37dfd003
// RTCP 与 RTP 复用端口
a=rtcp-mux
// 减少 RTCP 尺寸
a=rtcp-rsize
// PT=96 代表音频编码器 VP8/采样率为 90000
a=rtpmap:96 VP8/90000
// PT=96 支持 RTCP 协议中的 Goog-REMB 反馈
a=rtcp-fb:96 goog-remb
// PT=96 支持 RTCP 协议中的 Transport-CC 反馈
a=rtcp-fb:96 transport-cc
// PT=96 支持 RTCP 协议中的 fir 反馈
a=rtcp-fb:96 ccm fir
// PT=96 支持 RTCP 中的 nack 反馈
a=rtcp-fb:96 nack
// PT=96 支持 RTCP 中的 pli 反馈
a=rtcp-fb:96 nack pli
// PT=97 代表重传数据/采样率为 90000
a=rtpmap:97 rtx/90000
// PT=97 与 96 是绑定关系,说明 97 是 96 的重传数据
a=fmtp:97 apt=96
// PT=98 代表音频编码器 VP9/采样率为 90000
a=rtpmap:98 VP9/90000
// PT=98 支持 RTCP 中的 Goog-REMB 反馈
a=rtcp-fb:98 goog-remb
// PT=98 支持 RTCP 中的 Transport-CC 反馈
a=rtcp-fb:98 transport-cc
// PT=98 支持 RTCP 中的 fir 反馈
a=rtcp-fb:98 ccm fir
// PT=98 支持 RTCP 中的 nack 反馈
a=rtcp-fb:98 nack
// PT=98 支持 RTCP 中的 pli 反馈
a=rtcp-fb:98 nack pli
// 使用 VP9 时,视频帧的 profile id 为 0
// VP9 一共有 4 种 profile 1,2,3,4
// 0 表示支持 8bit 位深
// 和 YUV4:2:0 格式
a=fmtp:98 profile-id=0
// PT=99 代表重传数据/采样率 90000
a=rtpmap:99 rtx/90000
// PT=99 与 98 是绑定关系,因此 99 是 98 的重传数据
a=fmtp:99 apt=98
// PT=100 代表音频编码器 VP9/采样率 90000
a=rtpmap:100 VP9/90000
// PT=100 支持 RTCP 中的 Goog-REMB 反馈
a=rtcp-fb:100 goog-remb
// PT=100 支持 RTCP 中的 Transport-CC 反馈
a=rtcp-fb:100 transport-cc
// PT=100 支持 RTCP 中的 fir 反馈
a=rtcp-fb:100 ccm fir
// PT=100 支持 RTCP 中的 nack 反馈
a=rtcp-fb:100 nack
// PT=100 支持 RTCP 中的 pli 反馈
a=rtcp-fb:100 nack pli
// 使用 VP9 时,视频帧的 profile id 为 2
// VP9 一共有 4 种 profile 1,2,3,4
// 2 表示支持 10bit、12bit 位深
// 和 YUV4:2:0 格式
a=fmtp:100 profile-id=2
// PT=101 代表重传数据/采样率为 90000
a=rtpmap:101 rtx/90000
// PT=101 与 100 是绑定关系,因此 101 是 100 的重传数据
a=fmtp:101 apt=100
// PT=102 代表音频编码器 H264/采样率为 90000
a=rtpmap:102 H264/90000
// PT=102 支持 RTCP 中的 Goog-REMB 反馈
a=rtcp-fb:102 goog-remb
// PT=102 支持 RTCP 中的 Transport-CC 反馈
a=rtcp-fb:102 transport-cc
// PT=102 支持 RTCP 中的 fir 反馈
a=rtcp-fb:102 ccm fir
// PT=102 支持 RTCP 中的 nack 反馈
a=rtcp-fb:102 nack
// PT=102 支持 RTCP 中的 pli 反馈
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
// PT=121 代表重传数据/采样率为 90000
a=rtpmap:121 rtx/90000
// PT=121 与 102 是绑定关系,因此 121 是 102 的重传数据
a=fmtp:121 apt=102
// PT=127 代表音频编码器 H264/采样率为 90000
a=rtpmap:127 H264/90000
// PT=127 支持 RTCP 中的 Goog-REMB 反馈
a=rtcp-fb:127 goog-remb
// PT=127 支持 RTCP 中的 Transport-CC 反馈
a=rtcp-fb:127 transport-cc
// PT=127 支持 RTCP 中的 fir 反馈
a=rtcp-fb:127 ccm fir
// PT=127 支持 RTCP 中的 nack 反馈
a=rtcp-fb:127 nack
// PT=127 支持 RTCP 中的 pli 反馈
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
// PT=120 代表重传数据/采样率为 90000
a=rtpmap:120 rtx/90000
// PT=127 与 120 是绑定关系,因此 127 是 120 的重传数据
a=fmtp:120 apt=127
// PT=125 代表音频编码器 H264/采样率为 90000
a=rtpmap:125 H264/90000
// PT=125 支持 RTCP 中的 Goog-REMB 反馈
a=rtcp-fb:125 goog-remb
// PT=125 支持 RTCP 中的 Transport-CC 反馈
a=rtcp-fb:125 transport-cc
// PT=127 支持 RTCP 中的 fir 反馈
a=rtcp-fb:125 ccm fir
// PT=127 支持 RTCP 中的 nack 反馈
a=rtcp-fb:125 nack
// PT=127 支持 RTCP 中的 pli 反馈
a=rtcp-fb:125 nack pli
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
// PT=107 代表重传数据/采样率为 90000
a=rtpmap:107 rtx/90000
// PT=107 与 125 是绑定关系,因此 177 是 125 的重传数据
a=fmtp:107 apt=125
// PT=108 代表音频编码器 H264/采样率为 90000
a=rtpmap:108 H264/90000
// PT=108 支持 RTCP 中的 Goog-REMB 反馈
a=rtcp-fb:108 goog-remb
// PT=108 支持 RTCP 中的 Transport-CC 反馈
a=rtcp-fb:108 transport-cc
// PT=108 支持 RTCP 中的 fir 反馈
a=rtcp-fb:108 ccm fir
// PT=108 支持 RTCP 中的 nack 反馈
a=rtcp-fb:108 nack
// PT=108 支持 RTCP 中的 pli 反馈
a=rtcp-fb:108 nack pli
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
// PT=109 代表重传数据/采样率为 90000
a=rtpmap:109 rtx/90000
// PT=109 与 108 是绑定关系,因此 109 是 108 的重传数据
a=fmtp:109 apt=108
// PT=124 代表视频使用 red fec 技术/采样率为 90000
a=rtpmap:124 red/90000
// PT=119 代表重传数据/采样率为 90000
a=rtpmap:119 rtx/90000
// PT=1119 与 124 是绑定关系,因此 119 是 124 的重传数据
a=fmtp:119 apt=124
// PT=123 代表视频使用 ulp fec 技术/采样率为 90000
a=rtpmap:123 ulpfec/90000
// ssrc-group 表示几个源之间的关系
// 其格式为 a=ssrc-group:<semantics> <ssrc-id> …
// 参考 RFC5576
// FID(Flow ID), 表示这几个源都是数据流
// 其中,1101026881 是正常的视频流
// 而后面的 ssrc=35931176 是前面的 ssrc 的重传流
a=ssrc-group:FID 1101026881 35931176
// 源 1101026881 的别名为 Tf3LnJwwJc0lgnxC
a=ssrc:1101026881 cname:Tf3LnJwwJc0lgnxC
// 下面的描述行指明了源 1101026881 与媒体流 ID(Media Stream ID) 和轨的关系
// 在一个媒体流中可以有多路轨(track), 每个轨对应一个 ssrc
a=ssrc:1101026881 msid:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt f5d231d9-f0f7-4cd2-b2bc-424f37dfd003
// 下面描述行指明了源 1101026881 所属的媒体流的 label(Media Stream label)
a=ssrc:1101026881 mslabel:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt
// 下面描述行指明了源 1101026881 对应的媒体轨,同时它也是视频设备的 label
a=ssrc:1101026881 label:f5d231d9-f0f7-4cd2-b2bc-424f37dfd003
// 源 35931176 的别名为 Tf3LnJwwJc0lgnxC
a=ssrc:35931176 cname:Tf3LnJwwJc0lgnxC
// 下面的信息与源 1101026881 的信息相同,不做解释
a=ssrc:35931176 msid:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt f5d231d9-f0f7-4cd2-b2bc-424f37dfd003
a=ssrc:35931176 mslabel:3eofXQZ24BqbQPRkcL49QddC5s84gauyOuUt
a=ssrc:35931176 label:f5d231d9-f0f7-4cd2-b2bc-424f37dfd003