乐趣区

关于webrtc:玩转-WebRTC-通信一文读懂-SDP-协议

简介

在网络多媒体通话场景下,会议的参与者往往是用 SDP 协定来传递、协商媒体详细信息、网络地址和其余元数据。SDP 协定的全称是 session description protocol,含意是会话形容协定,它不是一种传输协定,而是由 ITEF 组织下的 MMusic 工作组设计的一种会话形容格局。

SDP 利用

SDP 最罕用于 RTC 实时通话的协商过程,在 WebRTC 中,通信单方在连贯阶段应用 SDP 来协商后续传输过程中应用的音视频编解码器 (codec)、主机候选地址、网络传输协定等。

在理论的利用过程中,通信单方能够应用 HTTP、WebSocket、DataChannel 等传输协定来互相传送 SDP 内容,这个过程称作 offer/answer 替换,也就是发起方发送 offer,接管方收到 offer 后回复一个 answer。例如在下图的服务端架构中,客户端将 offer 发送给信令服务器,信令服务器转发给媒体服务器,媒体服务器将 offer 和本身的能力进行比拟后失去 answer,信令服务器再将 answer 转发给客户端,随后客户端和媒体服务器就能够进行 RTP 通信。

SDP 格局

SDP 协定的设计能够参考 RFC4566 文档。它是一种具备非凡约定格局的纯文本形容文档,也就是它的内容都是由 UTF-8 编码的文本,有点相似于 JSON/XML。一个 SDP 会话形容包含若干行 type=value 模式的文本,其中 type 是一个辨别大小写的字母,例如 v、m 等,value 是一个结构化的文本,格局不固定。通常 value 由若干宰割符隔开的字段组成或者是一个字符串, 整个协定文本辨别大小写。”=” 两侧不容许有空格存在。

SDP 整体构造

SDP 由一个会话级形容(session level description)和多个媒体级形容(media level description)组成。会话级形容的作用域是整个会话,在 SDP 中,从 “v=” 行开始到第一个 “m=” 行之前都是属于会话级形容的内容。媒体级形容对某个媒体流的内容进行形容,例如某个音频流或者某个视频流,从某个 “m=” 行开始到下个 “m=” 行之前是属于一个媒体级形容的内容。如下图所示:

会话级形容次要形容了 SDP 的版本号、session 信息、是否启用端口复用等。每一个媒体级形容都形容了某种媒体的信息,包含所反对的 Codec、传输的时候应用的 SSRC、反对的 RTP 扩大头等。在会话级形容和媒体级形容可能会呈现雷同的内容,当这种状况呈现时,以媒体级形容的内容为准。

SDP 中字段的含意

SDP 中有的字段是必须的,有的字段是可选的,可选的字段在如下的示例中都应用 * 进行标记。SDP 中 type 呈现的程序是固定的,依照如下程序进行排列,这样能够加强解析器谬误检测的能力,另外也能够简化解析器的实现。

# 1. 会话级别的形容(及其字段)v=  (protocol version)
o=  (originator and session identifier)
s=  (session name)
i=* (session information)
u=* (URI of description)
e=* (email address)
p=* (phone number)
c=* (connection information -- not required if included in all media)
b=* (zero or more bandwidth information lines)
# 2. 一个或多个工夫形容(字段参见下文)z=* (time zone adjustments)
k=* (encryption key)
a=* (zero or more session attribute lines)
# 3. 零个或多个媒体级别的形容(字段参见下文)# 工夫形容的字段有这些
t=  (time the session is active)
r=* (zero or more repeat times)

# 媒体级别的形容字段有这些
m=  (media name and transport address)
i=* (media title)
c=* (connection information -- optional if included at session level)
b=* (zero or more bandwidth information lines)
k=* (encryption key)
a=* (zero or more media attribute lines)

能够看到 type 都是单个小写字母,它们是不可扩大的,如果 SDP 解析器不能解析某个 type 则必须疏忽,”a=” 是 SDP 的次要扩大伎俩,来针对某中特定类型的媒体或利用做扩大。

有一个很好的网站:https://webrtchacks.com/sdp-a… 可用于学习 SDP,这个网站外面鼠标挪动到 SDP 某一行时,就会显示这一行 SDP 的具体含意。在这里简略介绍一下 SDP 协定中罕用的 type 以及对应的含意。

  1. v: protocol version

    v=0

    v 的含意是 SDP 协定的版本号,目前 v 都是 0。

  2. o: originator and session identifier

    o=<username> <session-id> <session-version> <nettype> <addrtype> <unicast-address>

    会话所有者无关的参数,包含用户名、session 信息,地址信息等。
    (Owner/creator and session identifier)。

  • username: 会话发起者的名称。如果不提供则用 ”-“ 示意,用户名不能蕴含空格;
  • session-id: 主叫方的会话标识符;
  • session-version: 会话版本号,个别为 0;
  • nettype: 网络类型,目前仅应用 IN 来示意 Internet 网络类型;
  • addrtype: 地址类型,能够是 IPV4 和 IPV6 两种地址类型;
  • unicast-address:会话发起者的 IP 地址。
  1. s: session name

    s=<session name>

    本次会话的题目或会话的名称(Session name)。

  2. t: time the session is active

    t=<start-time> <stop-time>

    会话的起始工夫和完结工夫(Time session starts and stops),如果没有规定这两个工夫的话,都写为 0 即可。

  3. m: media name

    m=<media> <port>/<number of ports> <proto> <fmt> ...

    媒体行,形容了发送方所反对的媒体类型等信息(Media information)。

  • media:媒体类型,能够为 “audio”、”video”、”text”、”application”、”message”,示意音频类型、视频类型、文本类型、利用类型、音讯类型等,当前也可能扩大其余类型;
  • port/number of ports:流传输端口号。示意在对应的本地端口上发送流;
  • proto:流传输协定。举例说明:

    • RTP/SAVPF 示意用 UDP 传输 RTP 包;
    • TCP/RTP/SAVPF 示意用 TCP 传输 RTP 包;
    • UDP/TLS/RTP/SAVPF 示意用 UDP 来传输 RTP 包,并且应用 TLS 加密;
    • 最初的 SAVPF 还有其余几种值:AVP, SAVP, AVPF, SAVPF。

      • AVP 意为 AV profile
      • S 意为 secure
      • F 意为 feedback
    • fmt 示意媒体格式形容,它可能是一串数字,代表多个媒体,这个字段的含意与 proto 字段的类型相干。在前面,能够应用 ”a=rtpmap:”、”a=fmtp:”、”a=rtcp-fb” 等扩大字段来对 fmt 进行阐明。
  1. c: connection data

    c=<nettype> <addrtype> <connection-address>

    一个会话形容必须在每个媒体层都蕴含“c=”字段或者在会话层蕴含一个“c=”字段。如果这两个层都呈现的话,则媒体层呈现的“c=”会笼罩会话层呈现的“c=”字段的值。

  • nettype: 是一个文本字符串,目前只定义了“IN”,示意“Internet”,将来会定义其余值。
  • addrtype: 目前只定义了 IP4 和 IP6。
  • connection-address: 标记连贯的地址。取决于 addrtype 字段的不同,在 connection-address 之后可能也会追随其余的字段。
  1. b: bandwidth
b=<bwtype>:<bandwidth>

这个字段的意思是本会话或者媒体所需占用的带宽。bwtype 能够为 “CT” 或者 “AS”,给出了 bandwidth(单位 kbps)数字所代表的含意:

CT:示意会话所占的所有的带宽的大小。当用于 RTP 会话时,示意所有的 RTP 会话所占用的带宽。

AS:这个带宽类型是针对特定利用的。通常,这示意某利用所占用的最大带宽。当用于 RTP 会话时,示意繁多 RTP 会话所占用的带宽.

能够了解为 CT 代表的是整个通话过程的带宽,AS 代表的是某个流的带宽。

  1. Encryption Keys (“k=”)
k=<method>

k=<method>:<encryption key>

如果在一个平安的信道上传输 SDP 音讯,那么 SDP 之中也能够携带密钥,携带的形式就是采纳字段 “k=”。当然这种形式目前曾经不举荐了。

字段 “k=” 能够是全局的,也能够是放在某个 “m=” 中的,别离代表利用于所有的媒体流,或者独自利用于某条媒体流。定义格局有如下几种:

  • k=clear:<encryption key>

在这种办法中,密钥是没有通过任何转换的。除非传输通道是相对平安的,否则不该当应用这种办法。

  • k=base64:<encoded encryption key>

在这种办法中,密钥通过 base64 的编码。除非保障传输通道相对平安,否则不该当应用这种办法。

  • k=uri:<URI to obtain key>

在这种办法中,给出一个 URI。通过这个 URI,能够取得密钥,拜访 URI 的过程中可能还须要认证。

  • k=prompt

在这种办法中,没有给出密钥。然而加上这个字段后,当用户退出会话时会提醒其输出密钥。这种形式目前也不举荐。

  1. a: attributes
      a=<attribute>

      a=<attribute>:<value>

a 示意的是属性。a 字段是扩大 SDP 的次要形式,有会话层属性和媒体层属性。会话层的属性利用于所有的媒体流,媒体层的属性只利用于以后的媒体流。

属性有两种形式:

  • 个性属性,a=<flag> 示意,例如:”a=recvonly”
  • 值属性,以 a =<attribute>:<value> 示意,例如 ”a=ice-ufrag:khLS”

罕用的属性列表如下:

表列 A 表列 B 表列 C
a=rtpmap: RTP/AVP(Audio Video Profile) list m=audio 54278 RTP/SAVPF 111 103 104 0 8 106 105 13 126
a=rtpmap:111 opus/48000/2
a=fmtp: Format transport a=fmtp:111 minptime=10
a=rtcp: Explicit RTCP port (and address) a=rtcp:54278 IN IP4 180.6.6.6
a=mid: Media identification grouping a=mid:audio
a=ssrc: “ssrc” indicates a property (known as a”source-level attribute”) of a media source (RTP stream) within an RTP session a=ssrc:189858836 msid:GUKF430Khp9jEQiPrdYe0LbTAALiNAKAIfl2 ea392930-e126-4573-bea3-bfba519b4d59
a=ssrc-group: Ssrc identification grouping a=ssrc-group:SIMULCAST 32040 32142
a=ssrc:32040 imageattr:96 [x=1280,y=720]
a=ssrc:32142 imageattr:96 [x=640,y=480]
a=ice-ufrag: a=ice-pwd: The “ice-ufrag” and “ice-pwd” attributes convey the username fragment and password used by ICE for message integrity a=ice-ufrag:kwlYyWNjhC9JBe/V
a=ice-pwd:AU/SQPupllyS0SDG/eRWDCfA
a=ice-pwd:
a=fingerprint: A certificate fingerprint is a secure one-way hash of the DER (distinguished encoding rules) form of the certificate. a=fingerprint:sha-256 D1:2C:BE:AD:C4:F6:64:5C:25:16:11:9C:AF:E7:0F:73:79:36:4E:9C:1E:15:54:39:0C:06:8B:ED:96:86:00:39
a=candidate: It contains a transport address for a candidate that can be used for connectivity checks. a=candidate:4022866446 1 udp 2113937151 192.168.0.197 36768 typ host generation 0
a=ptime: Length of time in milliseconds for each packet a=ptime:20
a=recvonly Receive only mode a=recvonly
a=sendrecv Send and receive mode a=sendrecv
a=sendonly Send only mode a=sendonly
a=type: Type of conference
a=sdplang: Language for the session description
a=framerate: Maximum video frame rate in frames per second a=framerate:15
a=inactive Inactive mode a=inactive

SDP 协商过程

SDP 协商过程对应的 RFC 文档是 RFC3264。在 WebRTC 通信过程中,连贯的两端通过 offer/answer 替换过程来相互进行 SDP 协商,发起方发送 offer 给接管方,其中蕴含了发起方的媒体能力和其余信息(包含 ICE、DTLS fingerprint,SSRC 等),接管方收到 offer 后和本人反对的能力进行比拟取出交加,回复 answer 给发起方,其中蕴含了协商之后的媒体能力和其余信息(ICE、DTLS fingerprint,SSRC 等),要留神这个过程中只有媒体能力是协商的,也就是发起方和接管方独特反对的媒体能力,例如反对的编解码格局,以及是否反对 RTX、FEC、TCC 等 QoS 性能,而 ICE、DTLS、SSRC 的信息是间接给出告诉对方,是连贯单方各自的信息。在 offer/answer 替换实现之后,单方就能够应用这些独特反对的媒体能力进行通信。

协商的过程如下图所示:

A 向服务器发送 offer 携带本人的 SDP 信息,包含:

  1. 地址信息是 UDP 10.124.17.11:32132,A 通过这个地址来和服务端进行媒体通信;
  2. ICE 信息,服务器通过 ICE 信息来验证客户端 A 的身份;
  3. 在接下来的媒体通信过程,客户端 A 只发不收 RTP;
  4. A 音频反对 48kHz 的双声道 Opus 编解码,应用 SSRC=1111 来发送;
  5. A 视频反对 VP8 或者 VP9 或者 H264 或者 H265 编解码,应用 SSRC=2222 来发送;

服务器在收到 A 的 offer 后,回复给 A 一个 answer,这是单方协商进去的媒体能力:

  1. 地址信息是 UDP 10.108.27.64:8888,服务器通过这个地址来和 A 进行媒体通信;
  2. ICE 信息,A 通过 ICE 信息来验证服务器的身份;
  3. 在接下来的媒体通信过程,服务器对于 A 来说只收不发 RTP;
  4. 协商进去的音频能力是 48kHz 的双声道 Opus 编解码;
  5. 协商进去的视频能力是 H264 编解码。

B 向服务器发送 offer 携带本人的 SDP 信息,包含:

  1. 地址信息是 UDP 192.168.1.1:32222,B 通过这个地址来和服务端进行媒体通信;
  2. ICE 信息,服务器通过 ICE 信息来验证客户端 B 的身份;
  3. 在接下来的媒体通信过程,客户端 A 须要收发 RTP;
  4. B 音频反对 48kHz 的双声道 Opus 编解码或者 G711 编解码,应用 SSRC=1234 来进行发送;
  5. A 视频反对 H264,应用 SSRC=4567 来进行发送;

服务器在收到 B 的 offer 后,回复给 B 一个 answer,这是单方协商进去的媒体能力:

  1. 地址信息是 UDP 10.108.27.64:8888,服务器通过这个地址来和 B 进行媒体通信;
  2. ICE 信息,B 通过 ICE 信息来验证服务器的身份;
  3. 在接下来的媒体通信过程,服务器对于 B 来说能够收发 RTP;
  4. 协商进去的音频能力是 Opus 编解码、48KHz,双声道,应用 SSRC=1122 进行发送;
  5. 协商进去的视频能力是 H264 编解码,应用 SSRC=3344 能够发送。
    从以上两个 offer/answer 替换过程中能够看出,上图中的媒体服务器音频反对 Opus 编解码,但不反对 G711 编解码;视频反对 H264 编解码,但不反对 VP8、VP9、H265 编解码。

SDP 样例

在介绍完 SDP 的文本构造和 SDP 的协商过程中后,这里咱们举一个理论传输的 SDP 内容来帮忙了解。理论工程中,客户端和服务端都会反对好几种音视频媒体编解码,并且可能反对好几种能力,例如 FEC、NACK、TCC 等等,所以理论工程中的 SDP 都会十分长。为了不便浏览,下文将间接在 SDP 中每一行上方的正文中解释其含意。这个 SDP 中包含了 audio 和 video 两种流,video 的内容有局部也在 audio 中呈现过,因而不再反复解释。

发布者 Offer

// SDP 版本信息

v=0

// session 信息

// o=<username> <session-id> <session-version> <nettype> <addrtype> <unicast-address>

o=- 1873022542326151139 2 IN IP4 127.0.0.1

// s=<session name>

s=-

// t=<start-time> <stop-time>,如果不规定开始和完结工夫,两个都填 0 即可

t=0 0

// 应用 "a=" 来扩大的 bundle 属性,其含意是 audio 和 video 应用同一个端口发送 / 接管,具体能够参考下方的 RFC 文档:// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54

a=group:BUNDLE audio video

// 指明了 media stream ID 为 34b34ced3c5623ea4213vx3

// 参考 RFC 文档: https://tools.ietf.org/html/draft-ietf-mmusic-msid-17

a=msid-semantic: WMS 34b34ced3c5623ea4213vx3

// m=<media> <port> <proto> <fmt> ...

// port=10 无理论含意,真正通信应用的端口由 ICE Candidate 指定

// proto=UDP/TLS/RTP/SAVP 示意用 UDP 来传输 RTP 包,并应用 DTLS 加密

// 前面的一串数字是 fmt,示意所有 codec 的 payloadtype

m=audio 10 UDP/TLS/RTP/SAVPF 111 114 115 116 123 124 125

// c=<nettype> <addrtype> <connection-address>

c=IN IP4 0.0.0.0

// a=rtcp:<port> [nettype addrtype connection-address]

a=rtcp:9 IN IP4 0.0.0.0

// ICE 信息,参考 RFC 文档: https://tools.ietf.org/html/rfc5245#section-15.4

a=ice-ufrag:aZ/b

a=ice-pwd:3tFwvgPAA2PK3pPWoJjVz4FJ

a=ice-options:trickle renomination

// DTLS 信息,参考 RFC 文档: https://tools.ietf.org/html/rfc4572#section-5

a=fingerprint:sha-256 5F:78:37:05:D7:83:46:05:F7:3F:17:35:2A:7E:81:D3:2D:26:71:87:8B:9F:57:02:53:30:E3:3E:B6:3E:49:D5

// a=setup:<role>

// role 可选 active/passive/actpass/holdconn,// 别离示意端点将发动一个传出连贯、端点将承受传入连贯、// 端点违心承受传入连贯或启动传出连贯、端点临时不想建设连贯

// 参考 rfc: https://tools.ietf.org/html/rfc4145#section-4

a=setup:actpass

// a=mid:<token>

// 这个 token 在 a=group 那一行中也有呈现,// 也就是说这里形容的媒体正是须要被 bundle 的

// 参考 rfc: https://tools.ietf.org/html/rfc5888#section-6

a=mid:audio

// 以下是这个媒体反对的所有 RTP 扩大头,// 参考 rfc: https://tools.ietf.org/html/rfc8285

// a=extmap:<value>["/"<direction>] <URI> <extensionattributes>

// value=ID

// direction 可选 sendonly/recvonly/sendrecv/inactive,默认值 sendrecv

// URI 就是这个扩大头的 URI,通信单方能够通过 URI 表明扩大头的含意让单方都能了解

// ID=1 的扩大头是 audio level 扩大头,示意 RTP 包中会携带音频包音量大小

// 参考 https://tools.ietf.org/html/rfc6464#section-4

a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level

// rtp stream 信息,参考 rfc: https://tools.ietf.org/html/draft-ietf-avtext-rid-09

a=extmap:13 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id

// 流的方向,sendrecv 示意能够收也能够发

// 参考 rfc:https://tools.ietf.org/html/rfc3264

a=sendrecv

// 这一行示意 rtcp 和 rtp 复用一个端口,// 参考 rfc:https://tools.ietf.org/html/rfc5761 

// 和 rfc:https://tools.ietf.org/html/rfc8035

a=rtcp-mux

// a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]

// opus codec 的 payload,

// 表明 fmt=111 就是用来传输 opus 数据的

// 参考 rfc: https://datatracker.ietf.org/doc/html/rfc7587

a=rtpmap:111 opus/48000/2

// a=rtcp-fb:<payload type> [...]

// 示意反对的 rtcp 反馈报文类型

// 这个反馈报文是 tcc 带宽探测用的

// 参考 https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01

a=rtcp-fb:111 transport-cc

// nack,示意 fmt=111 反对 nack 重传包

a=rtcp-fb:111 nack

// a=fmtp 用来形容 codec 的一些个性,例如这里示意冀望的 opus 最小打包工夫是 10ms,并且应用 inbandfec

a=fmtp:111 minptime=10;useinbandfec=1

// 指明了音频 RTX 包的 payloadtype

// 参考 rfc:https://tools.ietf.org/html/rfc4588#section-8.6

a=rtpmap:114 rtx/48000/2

// apt 示意 fmt=114 的 RTX 包是用来重传 fmt=111 音频的

a=fmtp:114 apt=111

// 指明了 rsfec 包的 payloadtype

a=rtpmap:123 rsfec/48000/2

// 指明了 red 包的 payloadtype

// 参考 https://tools.ietf.org/html/rfc2198

a=rtpmap:124 red/48000/2

// 指明了音频 RTX 包的 payloadtype

a=rtpmap:125 rtx/48000/2

// apt 示意 fmt=125 的 RTX 包是用来重传 fmt=124 的 red 包的

a=fmtp:125 apt=124

// ssrc-group 指明了一组 ssrc 之间的关系,FID 表明后一个 ssrc 是前一个 ssrc 的 rtx

// https://tools.ietf.org/html/rfc5576#section-4.2

a=ssrc-group:FID 2952055605 1713037948

// cname 的内容是一个 16 位 Base64 字符串,含意是传输级的标识符,同一个 PeerConnection 的值雷同

// 参考 https://datatracker.ietf.org/doc/html/rfc8834#section-4.9

a=ssrc:2952055605 cname:vqdagKn92E0lhuXn

// 前一个 49b56cad1c6074ef96622fa0 是 media stream id,后一个是 sender track id

// media stream 次要用于音视频同步,每个 track 以 media stream id 作为 sync label 进行同步

// 参考 https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-msid

a=ssrc:2952055605 msid:49b56cad1c6074ef96622fa0 49b56cad1c6074ef96622fa0a0

// media stream id

a=ssrc:2952055605 mslabel:49b56cad1c6074ef96622fa0

// sender track id

a=ssrc:2952055605 label:49b56cad1c6074ef96622fa0a0

// video media

m=video 9 UDP/TLS/RTP/SAVPF 96 97 101 102 103

c=IN IP4 0.0.0.0

a=rtcp:9 IN IP4 0.0.0.0

a=ice-ufrag:aZ/b

a=ice-pwd:3tFwvgPAA2PK3pPWoJjVz4FJ

a=ice-options:trickle renomination

a=fingerprint:sha-256 5F:78:37:05:D7:83:46:05:F7:3F:17:35:2A:7E:81:D3:2D:26:71:87:8B:9F:57:02:53:30:E3:3E:B6:3E:49:D5

a=setup:actpass

a=mid:video

// 传输工夫偏移扩大头

// 参考 https://datatracker.ietf.org/doc/html/rfc5450

a=extmap:2 urn:ietf:params:rtp-hdrext:toffset

// abs-send-time 扩大头,gcc 带宽探测用的

a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time

// 视频朝向扩大头

// 参考 https://datatracker.ietf.org/doc/html/rfc6184

a=extmap:4 urn:3gpp:video-orientation

// transport-cc 扩大头,tcc 带宽探测用的

a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01

// 扩大头的内容是对播放提早限度的值

a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay

// 视频内容类型扩大头

a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type

// 这个扩大头用于传输每帧的工夫信息

a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing

// 视频的色域空间扩大头

a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/color-space

// 传输视频 SDES 信息的扩大头

// 参考:https://datatracker.ietf.org/doc/html/draft-ietf-avtext-rid-06

a=extmap:13 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id

a=sendrecv

a=rtcp-mux

a=rtcp-rsize

// 指明 fmt=96 就是用来传输 H264 编码的视频的

a=rtpmap:96 H264/90000

// remb 反馈报文,gcc 带宽探测用的

a=rtcp-fb:96 goog-remb

a=rtcp-fb:96 transport-cc

// FIR(残缺帧内申请)反馈报文

// 参考 https://datatracker.ietf.org/doc/html/rfc5104

a=rtcp-fb:96 ccm fir

a=rtcp-fb:96 nack

// PLI NACK 反馈报文

// 参考 https://datatracker.ietf.org/doc/html/rfc5104

a=rtcp-fb:96 nack pli

// 前面的是一些 H264 的参数

a=fmtp:96 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f

a=rtpmap:97 rtx/90000

a=fmtp:97 apt=96;packetization-mode=1

a=rtpmap:101 red/90000

a=fmtp:101 packetization-mode=1

a=rtpmap:102 rtx/90000

a=fmtp:102 apt=101;packetization-mode=1

a=rtpmap:103 rsfec/90000

a=fmtp:103 packetization-mode=1

// ssrc-group:SIM 示意前面的这些 ssrc 是同一个流的 simulcast

a=ssrc-group:SIM 2955842370 1032318052

a=ssrc-group:FID 2955842370 521905126

a=ssrc-group:FID 1032318052 1492521545

a=ssrc:2955842370 cname:vqdagKn92E0lhuXn

a=ssrc:2955842370 msid:49b56cad1c6074ef96622fa0 49b56cad1c6074ef96622fa0v0

a=ssrc:2955842370 mslabel:49b56cad1c6074ef96622fa0

a=ssrc:2955842370 label:49b56cad1c6074ef96622fa0v0

a=ssrc:1032318052 cname:vqdagKn92E0lhuXn

a=ssrc:1032318052 msid:49b56cad1c6074ef96622fa0 49b56cad1c6074ef96622fa0v0

a=ssrc:1032318052 mslabel:49b56cad1c6074ef96622fa0

a=ssrc:1032318052 label:49b56cad1c6074ef96622fa0v0

a=ssrc:521905126 cname:vqdagKn92E0lhuXn

a=ssrc:521905126 msid:49b56cad1c6074ef96622fa0 49b56cad1c6074ef96622fa0v0

a=ssrc:521905126 mslabel:49b56cad1c6074ef96622fa0

a=ssrc:521905126 label:49b56cad1c6074ef96622fa0v0

a=ssrc:1492521545 cname:vqdagKn92E0lhuXn

a=ssrc:1492521545 msid:49b56cad1c6074ef96622fa0 49b56cad1c6074ef96622fa0v0

a=ssrc:1492521545 mslabel:49b56cad1c6074ef96622fa0

a=ssrc:1492521545 label:49b56cad1c6074ef96622fa0v0

// 应用的 rsfec 的版本

a=rsfec-version:1

总结

SDP 协定是 WebRTC 通信的重要组成部分,它使得不同版本的 WebRTC 服务端、客户端之间可能兼容。能够从文中列出的理论的 SDP 样例中发现 SDP 还是很简单的,而且波及到了各种音视频传输中的概念,弄懂 SDP 对深刻学习 WebRTC 很有帮忙。


参考文档

  1. SDP 格局规定,RFC4566:https://datatracker.ietf.org/…
  2. offer/answer 替换过程,RFC3264:https://datatracker.ietf.org/…
  3. SDP 各字段解释示例:https://webrtchacks.com/sdp-a…
退出移动版