美文网首页
WebRTC学习笔记五 SDP(Session Descript

WebRTC学习笔记五 SDP(Session Descript

作者: 合肥黑 | 来源:发表于2021-04-09 16:28 被阅读0次

    参考
    Webrtc SDP格式解读
    WebRTC:会话描述协议SDP
    WebRTC会话描述协议(SDP)详解
    SDP字段全解析
    详细的文档
    更详细的官方文档
    https://webrtcforthecurious.com/zh/docs/02-signaling/

    SDP里面内容虽然很多,但是条理很清楚。SDP值为字符串,通过换行符生成一行一行的SDP报文,所有行可分为三类:全局行、音频行、视频行

    • v - Version,版本,版本,应等于0
    • o - Origin,源,包含一个唯一ID,用于重新协商
    • s - Session Name,会话名称,应等于-
    • t - Timing,时间,应等于0 0
    • m - Media Description,媒体描述,下面有详细说明
    • a - Attribute,属性,一个自由文本字段,这是WebRTC中最常见的行
    • c - Connection Data,连接数据,应等于IN IP4 0.0.0.0
    一、全局行

    v=0

    sdp版本号,一直为0,rfc4566规定

    o=- 7017624586836067756 2 IN IP4 127.0.0.1

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

    各字段含义如下:

    • username:发起者的用户名,不允许存在空格,如果应用不支持用户名,则为-。
    • sess-id:会话id,由应用自行定义,规范的建议是NTP(Network Time Protocol)时间戳。
    • sess-version:会话版本,用途由应用自行定义,只要会话数据发生变化时(比如编码),sess-version随着递增就行。同样的,规范的建议是NTP时间戳。
    • nettype:网络类型,比如IN表示Internet。
    • addrtype:地址类型,比如IP4、IV6
    • unicast-address:域名,或者IP地址。

    s=<session name>

    会话名,没有的话使用 - 代替

    t=0 0

    它给出了开始和结束时间。 当它们被设置为0时,意味着会话不受特定时间限制,换句话说,它在任何时候都是永久有效的。

    a=group:BUNDLE audio video

    BUNDLE分组建立了SDP中包含的几个媒体线之间的关系,通常是音频和视频。在WebRTC中,它用于在相同的RTP会话中复用多个媒体流。 在这种情况下,浏览器提供多路复用音频和视频,但另一方也必须支持和接受。 如果没有这一行,音视频,数据就会分别单独用一个udp端口来发送

    a=msid-semantic: WMS h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C

    WMS是WebRTC Media Stream简称,这一行定义了本客户端支持同时传输多个流,一个流可以包括多个track, 一般定义了这个,后面a=ssrc这一行就会有msid,mslabel等属性

    二、视频行
    2.1 媒体描述

    m=video 60372 UDP/TLS/RTP/SAVPF 100 101 116 117 96

    m=video说明本会话包含音频,60372代表视频使用端口60372来传输,但是在webrtc中一现在一般不使用,如果设置为0,代表不传输音频, UDP/TLS/RTP/SAVPF是表示用户来传输视频支持的协议,udp,tls,rtp代表使用udp来传输rtp包,并使用tls加密SAVPF代表使用srtcp的反馈机制来控制通信过程, 后台100 101 116 117 96表示本会话视频支持的编码。

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

    其中:

    • media:媒体类型。包括 video、audio、text、application、message等。
    • port:传输媒体流的端口,具体含义取决于使用的网络类型(在c=中声明)和使用的协议(proto,在m=中声明)。
    • proto:传输协议,具体含义取决于c=中定义的地址类型,比如c=是IP4,那么这里的传输协议运行在IP4之上。比如:
      • UDP:传输层协议是UDP。
      • RTP/AVP:针对视频、音频的RTP协议,跑在UDP之上。
      • RTP/SAVP:针对视频、音频的SRTP协议,跑在UDP之上。
    • fmt:媒体格式的描述,可能有多个。根据 proto 的不同,fmt 的含义也不同。比如 proto 为 RTP/SAVP 时,fmt 表示 RTP payload 的类型。如果有多个,表示在这次会话中,多种payload类型可能会用到,且第一个为默认的payload类型。
      举例,下面表示媒体类型是视频,采用SRTP传输流媒体数据,且RTP包的类型可能是122、102...119,默认是122。
    m=video 9 UDP/TLS/RTP/SAVPF 122 102 100 101 124 120 123 119
    
    

    对于 RTP/SAVP,需要注意的是,payload type 又分两种类型:

    举例,下面的SDP中:

    • 对于audio,111 是动态类型,表示opus/48000/2
    • 对于video,122 是动态类型,表示H264/90000
    m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 126
    a=rtpmap:111 opus/48000/2
    m=video 9 UDP/TLS/RTP/SAVPF 122 102 100 101 124 120 123 119
    a=rtpmap:122 H264/90000
    
    2.2 连接数据(c=)

    c=IN IP4 217.130.243.155

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

    每个SDP至少需要包含一个会话级别的c=字段,或者在每个媒体描述后面各包含一个c=字段。(媒体描述后的c=会覆盖会话级别的c=)

    • nettype:网络类型,比如IN,表示 Internet。
    • addrtype:地址类型,比如IP4、IP6。
    • connection-address:如果是广播,则为广播地址组;如果是单播,则为单播地址;

    举例01:

    c=IN IP4 224.2.36.42/127
    

    举例02:

    c=IN IP4 host.anywhere.com
    
    2.3 属性(a=)

    a=rtcp:64891 IN IP4 217.130.243.155

    a=<attribute> | <attribute>:<value>
    

    属性(attribute)是扩展SDP的主要手段,分为会话级属性和媒体级属性:

    (a)会话级属性:添加在第一个媒体描述之前,传达的信息适用于整个会议而不是单个媒体。

    • a=group:BUNDLE audio video 通过mid标识符把多个媒体属性连接起来;
    • a=msid-semantic: WMS ma 表示是webrtc媒体流(Webrtc Media Streams);

    (b)媒体级属性:媒体描述中添加有关媒体流的信息。

    • a=mid:audio 上述BUNDLE中用到的媒体标识;
    • a=msid:ma ta 连接不同的媒体描述,使用相同的MediaStreams;
    • a=sendonly 表示媒体发送端,其他类型:recvonly,sendrecv,inactive;
    • a=rtcp:9 IN IP4 0.0.0.0 用来传输rtcp地地址和端口;
    • a=rtcp-mux 表示rtp,rtcp包使用同一个端口来传输;
    • a=ice-xxx:xxx ice协商过程中的安全验证信息;
    • a=fingerprint:xxx 表示dtls协商过程中需要的认证信息;
    • a=setup:actpass 表示本客户端在dtls协商过程中,可以做客户端也可以做服务端;
    • a=rtpmap:111 opus/48000/2 负载类型111,编码格式opus,48000是时钟,2是通道数;
    • a=rtcp-fb:111 nack 支持丢包重传;
    • a=rtcp-fb:111 nack pli 支持关键帧丢包重传;
    • a=rtcp-fb:111 transport-cc 表示opus编码支持使用rtcp来控制拥塞;
    • a=fmtp:111 minptime=10;useinbandfec=1;maxplaybackrate=16000 对opus编码可选的补充说明,minptime代表最小打包时长是10ms,useinbandfec=1代表使用opus编码内置fec特性;
    • a=ssrc:1370113029 cname:NMediaAudio cname用来标识一个数据源,ssrc当发生冲突时可能会发生变化,但是cname不会发生变化,也会出现在rtcp包中SDEC中,用于音视频同步;
    • a=candidate:1 1 udp 2013266431 x.x.x.x 43342 typ host generation 0 表示候选人的传输地址,查看详情。
    2.1 ICE候选者

    a=candidate:1467250027 1 udp 2122260223 192.168.0.196 56143 typ host generation 0

    2.2 ICE参数

    a=ice-ufrag:Oyef7uvBlwafI3hT
    a=ice-pwd:T0teqPLNQQOf+5W+ls+P2p16

    2.3 DTLS参数

    a=fingerprint:sha-256 49:66:12:17:0D:1C:91:AE:57:4C:C6:36:DD:D5:97:D2:7D:62:C9:9A:7F:B9:A3:F4:70:03:E7:43:91:73:23:5E
    a=setup:actpass

    2.4 Codec参数

    a=rtpmap:100 VP8/90000

    这条线表示VP8与有效载荷类型100对齐。这意味着此会话中包含VP8视频帧的RTP数据包的有效载荷类型字段的值将为100. 现在VP8是视频的MTI编解码器,未来可能会发生变化。

    a=rtcp-fb:100 ccm fir

    指明使用全内帧请求(Full Intraframe Request, FIR)

    a=rtcp-fb:100 nack

    此行请求使用RFC 4585中指示的否定ACK(nack)。这允许另一端知道数据包丢失。

    a=rtcp-fb:100 nack pli

    此行表明支持PLI NACK RTCP消息。 这允许在视频包丢失时向另一端点请求新的VP8关键帧。

    a=rtcp-fb:100 goog-remb

    它定义了RTCP消息对Receiver Estimated Maximum Bitrate的使用。前缀goog-意味着仍然只能由Google和非标准实现。

    a=rtpmap:101 VP9/90000

    Chrome支持版本48的VP9。您可以在Web M项目站点了解此视频编解码器的功能。 默认情况下,它在VP8之后显示为SDP中的第二个选项。

    a=rtcp-fb:101 ccm fir
    a=rtcp-fb:101 nack
    a=rtcp-fb:101 nack pli
    a=rtcp-fb:101 goog-remb
    a=rtpmap:116 red/90000

    该行请求使用RFC2198,其定义有效载荷格式以编码冗余媒体数据。在WebRTC中,这用于封装有效载荷VP8(视频有效载荷本身)和FEC(Forward Error Correction)。

    a=rtpmap:117 ulpfec/90000

    此行请求使用ULP FEC(在RFC5109中定义)。 FEC(前向纠错)允许通过基于原始分组发送冗余信息来纠正数据传输中的某种错误。 当丢包(在RTCP-RR数据包中报告)时使用FEC。

    a=rtpmap:96 rtx/90000

    参数rtx和apt在RFC4588中定义。 该RFC定义了RTP有效载荷格式,仅用于执行另一方尚未接收的分组的重传。 无法使用原始有效负载重新发送数据包,因为它会破坏RTP和RTCP机制,因此它们会在具有不同有效负载的重新传输流中重新传输。 90000指的是重传流的时钟速率,其与原始VP8流相同,原始VP8流与其他视频协议90000相同。

    a=fmtp:96 apt=100

    该行表示具有有效载荷96的RTP分组将传输那些已经在该SDP(VP8)中对有效载荷100进行了编码的编解码器的rtx消息。

    2.5 SSRC参数

    a=ssrc-group:FID 2231627014 632943048

    此行声明SSRC 632943048是RFC5576中指定的2231627014的rtx修复流程

    a=ssrc:2231627014 cname:4TOk42mSjXCkVIa6
    a=ssrc:2231627014 msid:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS daed9400-d0dd-4db3-b949-422499e96e2d
    a=ssrc:2231627014 mslabel:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS
    a=ssrc:2231627014 label:daed9400-d0dd-4db3-b949-422499e96e2d

    ** 注:未特别说明,则与audio一致

    三、音频行

    m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126

    m=audio说明本会话包含音频,9代表音频使用端口9来传输,但是在webrtc中一现在一般不使用,如果设置为0,代表不传输音频, UDP/TLS/RTP/SAVPF是表示用户来传输音频支持的协议,udp,tls,rtp代表使用udp来传输rtp包,并使用tls加密SAVPF代表使用srtcp的反馈机制来控制通信过程, 后台111 103 104 9 0 8 106 105 13 126表示本会话音频支持的编码。

    c=IN IP4 0.0.0.0

    这一行表示你要用来接收或者发送音频使用的IP地址,webrtc使用ice传输,不使用这个地址

    a=rtcp:9 IN IP4 0.0.0.0

    明确指定传输RTCP的IP和端口,而不是从基础媒体端口派生的。请注意,与SRTP的端口相同,因为支持RTCP Multiplex。webrtc中不使用。

    a=mid:audio

    在前面BUNDLE这一行中用到的媒体标识。如果我们有不同的媒体,我们每个都应该有不同的标识符。

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

    此行定义将在RTP标头中使用的扩展,以便接收器可以正确解码并提取元数据。

    a=sendrecv

    上一行指出我是双向通信,另外几种类型是recvonly,sendonly,inactive。

    a=rtcp-mux

    指出rtp,rtcp包使用同一个端口来传输

    3.1 ICE候选者

    a=candidate:1467250027 1 udp 2122260223 192.168.0.196 46243 typ host generation 0

    a=candidate:1467250027 2 udp 2122260222 192.168.0.196 56280 typ host generation 0

    UDP上RTP的主机候选者 - 在此ICE行中,我们的浏览器为其主机候选者 - 浏览器正在计算机上监听的接口或接口的IP。 浏览器可以在该IP上接收/发送SRTP和SRTCP,以防远程对等端的候选者具有IP可见性。例如,如果另一台计算机位于同一LAN上,则将使用主机候选项。 协议(udp) - 2122260223之后的数字是候选者的优先级。请注意,宿主候选者的优先级高于其他候选者, 因为使用宿主候选者在资源使用方面更有效。第一行(component = 1)用于RTP,第二行(component = 2)用于RTCP。 请注意,浏览器不知道另一端是否支持rtcp-mux,因此它必须在要约中包含RTCP端口。

    a=candidate:435653019 1 tcp 1845501695 192.168.0.196 0 typ host tcptype active generation 0

    a=candidate:435653019 2 tcp 1845501695 192.168.0.196 0 typ host tcptype active generation 0

    TCP上RTP的主机候选者 - 这些线路与之前的两条ICE线路相同,但是对于TCP流量。 请注意,优先级较低 - 即1845501695较大 - 因为TCP不是实时媒体传输的最佳选择。

    a=candidate:1853887674 1 udp 1518280447 47.61.61.61 36768 typ srflx raddr 192.168.0.196 rport 36768 generation 0

    a=candidate:1853887674 2 udp 1518280447 47.61.61.61 36768 typ srflx raddr 192.168.0.196 rport 36768 generation 0

    UDP上RTP的自反性候选者(reflexive candidates) - 这里我们有服务器反身候选人。 请注意,它们的优先级低于主机候选者。 这些候选人是由STUN服务器发现的。

    a=candidate:750991856 2 udp 25108222 237.30.30.30 51472 typ relay raddr 47.61.61.61 rport 54763 generation 0

    a=candidate:750991856 1 udp 25108223 237.30.30.30 58779 typ relay raddr 47.61.61.61 rport 54761 generation 0

    UDP上RTP的中继候选者(Relay candidates) - 接下来我们有中继候选。这些候选者是从TURN服务器获得的,必须在创建对等连接时进行配置。 请注意,此处的优先级低于主机和反射候选者(25108222更高),因此仅当主机和反射候选者之间没有IP连接时才使用中继。

    3.2 ICE参数

    a=ice-ufrag:khLS

    a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ

    以上两行是ice协商过程中的安全验证信息

    3.3 DTLS参数

    a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17

    此指纹是DTLS-SRTP协商中使用的证书的哈希函数的结果。 此行在信令(应该是可信的)和DTLS中使用的证书之间创建绑定,如果指纹不匹配,则应拒绝会话。

    a=setup:actpass

    代表本客户端在dtls协商过程中,可以做客户端也可以做服务端

    3.4 Codec参数

    a=rtpmap:111 opus/48000/2

    Opus是WebRTC的MTI音频编解码器之一。 它具有可变比特率(6kbps-510kbps),并且不受任何版税限制,因此可以在任何浏览器中自由实现。 Opus支持开始变得普遍,它已成为大多数WebRTC应用程序的关键。

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

    此行包括Chrome支持的音频Opus编解码器的可选有效载荷格式特定参数。 minipitime = 10指定分组化时间的最低值(ptime:由单个分组传输的音频的毫秒数)。 useinbandfec = 1指定解码器能够利用Opus带内FEC(前向错误连接)。

    a=rtpmap:103 ISAC/16000

    ISAC(互联网语音音频编解码器)是用于高质量会议的宽带语音编解码器。 16000表示ISAC将以16kbps的速度使用。

    a=rtpmap:104 ISAC/32000

    32000表示ISAC将以32kbps的速度使用。

    a=rtpmap:9 G722/8000

    G722是一款工作频率为48,56和64 kbit/s的宽带音频编解码器,与G.711等窄带语音编码器相比,由于50-7000 Hz的语音带宽更宽,因此可提供更高的语音质量。

    a=rtpmap:0 PCMU/8000

    a=rtpmap:8 PCMA/8000

    这是使用不同压扩法则的经典电信64kbps脉冲编码调制(PCM)编解码器。 0和8分别是PCMU和PCMA的静态有效载荷类型。从技术上讲,这些线路不存在,因为这些信息可以通过媒体线中的编解码器列表 - PCMU或PCMA来推断。

    a=rtpmap:106 CN/32000

    a=rtpmap:105 CN/16000

    a=rtpmap:13 CN/8000

    上面的动态RTP有效载荷类型(除了有效载荷类型13,它是静态的)表示舒适噪声(Comfort Noise, CN)将用于速率为48000,32000,16000和8000kbits/s的编解码器。

    a=rtpmap:126 telephone-event/8000

    此行表示浏览器支持RFC4733,允许它在RTP内发送DTMF,而不是通常的数字化正弦波,而是作为特殊有效载荷(在这种情况下,RTP数据包中有效载荷126)。 该DTMF机制确保DTMF将独立于音频编解码器和信令协议进行传输。

    a=maxptime:60

    maxptime指定可以封装在每个数据包中的最大媒体数量,以毫秒为单位表示。数据包的大小可能会对音频和BW的质量产生副作用。可以在SDP中修改此值。

    3.5 SSRC参数

    a=ssrc:3570614608 cname:4TOk42mSjXCkVIa6

    cname源属性将媒体源与其Canonical端点标识符相关联,即使在发现冲突时ssrc标识符发生更改,该标准端点标识符也将保持RTP媒体流的常量。 这是媒体发送方将在其RTCP SDES数据包中放置的值。

    a=ssrc:3570614608 msid:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS 35429d94-5637-4686-9ecd-7d0622261ce8

    该线用于使用SDP信令通知SSRC的RTP概念与“媒体流”/“媒体流轨道”的WebRTC概念之间的关联。 第一个参数对应于媒体流(media stream)的id,第二个参数对应于媒体流轨道的if。这些ID在WebRTC API中处理。 第一个数字是SSRC标识符,它将包含在RTP数据包的SSRC字段中。

    a=ssrc:3570614608 mslabel:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS

    label属性指的是Media Stream对象的id。不推荐使用该参数,并将msid替换为该参数。标签是为了向后兼容而保留。

    a=ssrc:3570614608 label:35429d94-5637-4686-9ecd-7d0622261ce8

    label属性也被msid弃用,并在使用SDP的任意网络应用程序的上下文中携带指向RTP媒体流的指针。 此标签与WebRTC API中的Media Stream Track ID相对应,该ID包含在msid行中。

    四、WebRTC实例

    下面例子来自腾讯云WebRTC服务的远端offer。

    // sdp版本号为0
    v=0
    // o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
    // 用户名为空,会话id是8100750360520823155,会话版本是2
    //(后面如果有类似改变编码的操作,sess-version加1),
    // 地址类型为IP4,地址为127.0.0.1(这里可以忽略)
    o=- 7595655801978680453 2 IN IP4 112.90.139.105
    // 会话名为空
    s=-
    // 会话的起始时间,都为0表示没有限制
    t=0 0
    a=ice-lite
    // 音频、视频的传输的传输采取多路复用,通过同一个RTP通道传输音频、视频,
    // 可以参考 https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54
    a=group:BUNDLE 0 1
    // WMS是WebRTC Media Stram的缩写,这里给Media Stream定义了一个唯一的标识符。
    // 一个Media Stream可以有多个track(video track、audio track),
    //这些track就是通过这个唯一标识符关联起来的,具体见下面的媒体行(m=)以及它对应的附加属性(a=ssrc:)
    // 可以参考这里 http://tools.ietf.org/html/draft-ietf-mmusic-msid
    a=msid-semantic: WMS 5Y2wZK8nANNAoVw6dSAHVjNxrD1ObBM2kBPV
    // m=<media> <port> <proto> <fmt> ...
    // 本次会话有音频,端口为9(可忽略,端口9为Discard Protocol专用),
    // 采用UDP传输加密的RTP包,并使用基于SRTCP的音视频反馈机制来提升传输质量
    //,111、103、104等是audio可能采用的编码(参见前面m=的说明)
    m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 126
    // 音频发送者的IP4地址,WebRTC采用ICE,这里的 0.0.0.0 可直接忽略
    c=IN IP4 0.0.0.0
    // RTCP采用的端口、IP地址(可忽略)
    a=rtcp:9 IN IP4 0.0.0.0
    // ice-ufrag、ice-pwd 分别为ICE协商用到的认证信息
    a=ice-ufrag:58142170598604946
    a=ice-pwd:71696ad0528c4adb02bb40e1
    // DTLS协商过程的指纹信息
    a=fingerprint:sha-256 7F:98:08:AC:17:6A:34:DB:CF:3B:EC:93:ED:57:3F:5A:9E:1F:4A:F3:DB:D5:BF:66:EE:17:58:E0:57:EC:1B:19
    // 当前客户端在DTLS协商过程中,既可以作为客户端,也可以作为服务端,具体可参考 RFC4572
    a=setup:actpass
    // 当前媒体行的标识符(在a=group:BUNDLE 0 1 这行里面用到,这里0表示audio)
    a=mid:0
    // RTP允许扩展首部,这里表示采用了RFC6464定义的针对audio的扩展首部,
    // 用来调节音量,比如在大型会议中,有多个音频流,就可以用这个来调整音频混流的策略
    // 这里没有vad=1,表示不启用这个音量控制
    a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
    // 表示既可以发送音频,也可以接收音频
    a=sendrecv
    // 表示启用多路复用,RTP、RTCP共用同个通道
    a=rtcp-mux
    // 下面几行都是对audio媒体行的补充说明(针对111),包括rtpmap、rtcp-fb、fmtp
    // rtpmap:编解码器为opus,采样率是48000,2声道
    a=rtpmap:111 opus/48000/2
    // rtcp-fb:基于RTCP的反馈控制机制,可以参考 https://tools.ietf.org/html/rfc5124、
    //https://webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02/
    a=rtcp-fb:111 transport-cc
    a=rtcp-fb:111 nack
    // 最小的音频打包时间
    a=fmtp:111 minptime=20
    // 跟前面的rtpmap类似
    a=rtpmap:126 telephone-event/8000
    // ssrc用来对媒体进行描述,格式为a=ssrc:<ssrc-id> <attribute>:<value>,具体可参考 RFC5576
    // cname用来唯一标识媒体的数据源
    a=ssrc:16864608 cname:YZcxBwerFFm6GH69
    // msid后面带两个id,第一个是MediaStream的id,第二个是audio track的id(跟后面的mslabel、label对应)
    a=ssrc:16864608 msid:5Y2wZK8nANNAoVw6dSAHVjNxrD1ObBM2kBPV 128f4fa0-81dd-4c3a-bbcd-22e71e29d178
    a=ssrc:16864608 mslabel:5Y2wZK8nANNAoVw6dSAHVjNxrD1ObBM2kBPV
    a=ssrc:16864608 label:128f4fa0-81dd-4c3a-bbcd-22e71e29d178
    // 跟audio类似,不赘述
    m=video 9 UDP/TLS/RTP/SAVPF 122 102 125 107 124 120 123 119
    c=IN IP4 0.0.0.0
    a=rtcp:9 IN IP4 0.0.0.0
    a=ice-ufrag:58142170598604946
    a=ice-pwd:71696ad0528c4adb02bb40e1
    a=fingerprint:sha-256 7F:98:08:AC:17:6A:34:DB:CF:3B:EC:93:ED:57:3F:5A:9E:1F:4A:F3:DB:D5:BF:66:EE:17:58:E0:57:EC:1B:19
    a=setup:actpass
    a=mid:1
    a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
    a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
    a=extmap:4 urn:3gpp:video-orientation
    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=sendrecv
    a=rtcp-mux
    a=rtcp-rsize
    a=rtpmap:122 H264/90000
    a=rtcp-fb:122 ccm fir
    a=rtcp-fb:122 nack
    a=rtcp-fb:122 nack pli
    a=rtcp-fb:122 goog-remb
    a=rtcp-fb:122 transport-cc
    a=fmtp:122 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
    a=rtpmap:102 rtx/90000
    a=fmtp:102 apt=122
    a=rtpmap:125 H264/90000
    a=rtcp-fb:125 ccm fir
    a=rtcp-fb:125 nack
    a=rtcp-fb:125 nack pli
    a=rtcp-fb:125 goog-remb
    a=rtcp-fb:125 transport-cc
    a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
    a=rtpmap:107 rtx/90000
    a=fmtp:107 apt=125
    a=rtpmap:124 H264/90000
    a=rtcp-fb:124 ccm fir
    a=rtcp-fb:124 nack
    a=rtcp-fb:124 nack pli
    a=rtcp-fb:124 goog-remb
    a=rtcp-fb:124 transport-cc
    a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d0032
    a=rtpmap:120 rtx/90000
    a=fmtp:120 apt=124
    a=rtpmap:123 H264/90000
    a=rtcp-fb:123 ccm fir
    a=rtcp-fb:123 nack
    a=rtcp-fb:123 nack pli
    a=rtcp-fb:123 goog-remb
    a=rtcp-fb:123 transport-cc
    a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
    a=rtpmap:119 rtx/90000
    a=fmtp:119 apt=123
    a=ssrc-group:FID 33718809 50483271
    a=ssrc:33718809 cname:ovaCctnHP9Asci9c
    a=ssrc:33718809 msid:5Y2wZK8nANNAoVw6dSAHVjNxrD1ObBM2kBPV 1d7fc300-9889-4f94-9f35-c0bcc77a260d
    a=ssrc:33718809 mslabel:5Y2wZK8nANNAoVw6dSAHVjNxrD1ObBM2kBPV
    a=ssrc:33718809 label:1d7fc300-9889-4f94-9f35-c0bcc77a260d
    a=ssrc:50483271 cname:ovaCctnHP9Asci9c
    a=ssrc:50483271 msid:5Y2wZK8nANNAoVw6dSAHVjNxrD1ObBM2kBPV 1d7fc300-9889-4f94-9f35-c0bcc77a260d
    a=ssrc:50483271 mslabel:5Y2wZK8nANNAoVw6dSAHVjNxrD1ObBM2kBPV
    a=ssrc:50483271 label:1d7fc300-9889-4f94-9f35-c0bcc77a260d
    
    五、Uncaught (in promise) DOMException: Answer tried to set recv when offer did not set send
    chrome 中可以播放,firefox报错

    搜索一下,参考https://stackoverflow.com/questions/35166456

    RFC 3264: " If a media stream is listed as recvonly in the offer, the answer MUST be marked as sendonly or inactive in the answer. "

    这里可以参考SDP模型介绍,获取更详细的知识

    1.情态动词术语解释
    • MUST必须、一定要;
    • MUST NOT禁止;
    • REQUIRED需要;
    • SHALL、SHOULD应该;
    • SHALL NOT、SHOULD NOT不应该;
    • RECOMMENDED推荐;
    • MAY可以

    以上情态动词术语可参考RFC2119[3],这些动词要求我们在产品实现时,需要遵守或灵活变更约束。

    2.初始协商的Offer请求

    实体A <-> 实体B,实体首先发起Offer请求,内容如2节所示,对于作何一个媒体流/媒体通道,这时实体A必须:

    • 如果媒体流方向标为recvonly/sendrecv,即a=recvonly或a=sendrecv,则A必须(MUST)准备好在这个IP和端口上接收实体B发来的媒体流;
    • 如果媒体流方向标为sendonly/inactive,即a=recvonly或a=sendrecv,则A不需要进行准备。
    3.Answer响应

    实体B收到A的请求offer后,根据自身支持的媒体类型和编码策略,回复响应。

    • 如果实体B回复的响应中的媒体流数量和顺序必须(MUST)和请求offer一致,以便实体A进行甄别和决策。即m行的数量和顺序必须一致,B不能(MUST NOT)擅自增加或删除媒体流。如果B不支持某个媒体流,可以在对应的端口置0,但不能不带这个m行描述。
    • 对于某种媒体,实体B必须(MUST)从请求offer中选出A支持且自己也支持的该媒体的编码标识集,并且可以(MAY)附带自己支持的其它类型编码。
    • 对于响应消息中各个媒体的方向:
      如果请求某媒体流的方向为sendonly,那么响应中对应媒体的方向必须为recvonly;
      如果请求某媒体流的方向为recvonly,那么响应中对应媒体的方向必须为sendonly;
      如果请求某媒体流的方向为sendrecv,那么响应中对应媒体的方向可以为sendrecv/sendonly/recvonly/inactive中的一种;
      如果请求某媒体流的方向为inactive,那么响应中对应媒体的方向必须为inactive;
    • 响应answer里提供IP和端口,指示Offerer本端期望用于接收媒体流的IP和端口,一旦响应发出之后,Offerer必须(MUST)准备好在这个IP和端口上接收实体A发来的媒体流。
    • 如果请求offer中带了ptime(媒体流打包间隔)的a行或带宽的a行,则响应answer也应该(SHOULD)相应的携带。
    • 实体B Offerer应该(SHOULD)使用实体A比较期望的编码生成媒体流发送。一般来说对于m行,如m=video 0 RTP/AVP 31 34,排充越靠前的编码表示该实体越希望以这个编码作为载体,这里示例31(H261),34(H263)中H261为A更期望使用的编码类型。同理,当实体A收到响应answer后也是这样理解的。
    4.实体收到响应后的处理

    当实体A收到B回复的响应后,可以(MAY)开始发送媒体流,如果媒体流方向为sendonly/sendrecv,

    • 必须(MUST)使用answer列举的媒体类型/编码生成媒体发送;
    • 应该(SHOULD)使用answer中的ptime和bandwidth来打包发送媒体流;
    • 可以(MAY)立即停止监听端口,该端口为offer支持answer不支持的媒体所使用的端口。
    5.修改媒体流(会话)

    修改媒体流的offer-answer操作必须基于之前协商的媒体形式(音频、视频等),不能(MUST NOT)对已有媒体流进行删减。

    (a)删除媒体流
    如果实体认定新的会话不支持之前媒商的某个媒体,新的offer只须对这种媒体所在m行的端口置0,但不能不描述这种媒体,即不带对应m行。当answerer收到响应之后,处理同初始协商一样。

    (b)增加媒体流
    如果实体打算新增媒体流,在offer里只须加上描述即可或者占用之前端口被置0的媒体流,即用新的媒体描述m行替换旧的。当answerer收到offer请求后,发现有新增媒体描述,或者过于端口被置0的媒体行被新的媒体描述替换,即知道当前为新增媒体流,处理同初始协商。

    (c)修改媒体流
    修改媒体注主要是针对初始协商结果,如果有变更即进入修改流程处理,可能的变更包括IP地址、端口,媒体格式(编码),媒体类型(音、视频),媒体属性(ptime,bandwidth,媒体流方向变更等)。

    6.解决问题:

    查看请求offer发送的Sdp,发现在没有设置的情况下,全是默认的recvonly。

    m=audio ...
    ...
    a=recvonly
    ...
    m=video ...
    a=recvonly
    

    而服务器返回的

    m=audio ...
    ...
    a=recvonly
    ...
    m=video ...
    a=sendrecv
    

    参照上述要求,可以将请求offer设置成sendrecv即可解决firefox中的报错

            this.pc.addTransceiver("video", {
                'direction': 'sendrecv'
            });
            this.pc.addTransceiver("audio", {
                'direction': 'sendrecv'
            });
    
    7.Transceivers

    Transceivers are for sending and receiving

    Transceivers is a WebRTC specific concept that you will see in the API. What it is doing is exposing the ‘Media Description’ to the JavaScript API. Each Media Description becomes a Transceiver. Every time you create a Transceiver a new Media Description is added to the local Session Description.

    Each Media Description in WebRTC will have a direction attribute. This allows a WebRTC Agent to declare ‘I am going to send you this codec, but I am not willing to accept anything back’. There are four valid values:

    • send
    • recv
    • sendrecv
    • inactive

    相关文章

      网友评论

          本文标题:WebRTC学习笔记五 SDP(Session Descript

          本文链接:https://www.haomeiwen.com/subject/hfxthltx.html