《webrtc入门系列(一)easy_webrtc_server 入门环境搭建》
《webrtc入门系列(二)easy_webrtc_server 入门example测试》
《webrtc入门系列(三)云服务器coturn环境搭建》
《webrtc入门系列(四) zlmediakit webrtc sdp交互详细解读》
学习webrtc,一开始就绕不过sdp,所以开搞。
网上搜的资料不是很全面,又不好意思一直去问别人,实际上现在webrtc还没问过谁问题,好在,现在有ChatGPT。
小趴菜都可以入门,什么都能问,越简单答的越好,虽然很多时候智障混淆信息,慢慢调教,缩小颗粒度问的话,还是一个很好的老师。
8
鉴于easy_web_rtc的http通信过程过于简单,不利于学习,所以选用了zlmedia的webrtc视频进行抓包,说句题外话,我工作十余年,也使用过蛮多开源项目,想zl这样的专心维护的高质量代码和文档的作者,真的仅此一位。可惜自己只熟悉C语言。
以下是一个PC端通过浏览器,使用http作为信令交换webrtc sdp过程的详细解释。
//# sourceMappingURL=RTCClient.js.map
POST /index/api/webrtc?app=live&stream=video0&type=play HTTP/1.1
Host: 192.168.1.248
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=utf-8
Content-Length: 2452
Origin: http://192.168.1.248
Connection: keep-alive
Referer: http://192.168.1.248/xxx.html
v=0
o=mozilla...THIS_IS_SDPARTA-99.0 3224167891387244748 0 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 F3:7B:70:7B:67:E6:9A:A4:11:83:AB:09:F0:A6:CF:74:89:17:D8:A9:05:82:CF:E5:CC:69:DB:4D:B8:7E:FB:9C
a=group:BUNDLE 0 1
a=ice-options:trickle
a=msid-semantic:WMS *
m=video 9 UDP/TLS/RTP/SAVPF 120 124 121 125 126 127 97 98
c=IN IP4 0.0.0.0
a=recvonly
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
a=extmap:6/recvonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
a=fmtp:120 max-fs=12288;max-fr=60
a=fmtp:124 apt=120
a=fmtp:121 max-fs=12288;max-fr=60
a=fmtp:125 apt=121
a=fmtp:127 apt=126
a=fmtp:98 apt=97
a=ice-pwd:c8da3d5e526162f3514da1da02b5a44a
a=ice-ufrag:9691ba55
a=mid:0
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:120 goog-remb
a=rtcp-fb:120 transport-cc
a=rtcp-fb:121 nack
a=rtcp-fb:121 nack pli
a=rtcp-fb:121 ccm fir
a=rtcp-fb:121 goog-remb
a=rtcp-fb:121 transport-cc
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:126 goog-remb
a=rtcp-fb:126 transport-cc
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=rtcp-fb:97 goog-remb
a=rtcp-fb:97 transport-cc
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:120 VP8/90000
a=rtpmap:124 rtx/90000
a=rtpmap:121 VP9/90000
a=rtpmap:125 rtx/90000
a=rtpmap:126 H264/90000
a=rtpmap:127 rtx/90000
a=rtpmap:97 H264/90000
a=rtpmap:98 rtx/90000
a=setup:actpass
a=ssrc:2791796143 cname:{b5aaf774-54b0-47ec-8b26-f4957e9925d3}
m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101
c=IN IP4 0.0.0.0
a=recvonly
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2/recvonly urn:ietf:params:rtp-hdrext:csrc-audio-level
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
a=fmtp:101 0-15
a=ice-pwd:c8da3d5e526162f3514da1da02b5a44a
a=ice-ufrag:9691ba55
a=mid:1
a=rtcp-mux
a=rtpmap:109 opus/48000/2
a=rtpmap:9 G722/8000/1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000/1
a=setup:actpass
a=ssrc:2059420909 cname:{b5aaf774-54b0-47ec-8b26-f4957e9925d3}
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 2581
Content-Type: application/json
Date: Wed, Apr 12 2023 13:08:35 GMT
Keep-Alive: timeout=15, max=100
Server: ZLMediaKit(git hash:91efab2/2023-02-28T23:00:59+08:00,branch:master,build time:2023-03-02T17:32:14)
{"sdp":"v=0\r\no=mozilla...THIS_IS_SDPARTA-99.0 3224167891387244748 0 IN IP4 192.168.1.248\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS *\r\nm=video 8000 UDP/TLS/RTP/SAVPF 126 127\r\nc=IN IP4 192.168.1.248\r\na=rtcp:8000 IN IP4 192.168.1.248\r\na=ice-ufrag:zlm_1\r\na=ice-pwd:bUUwxizAeY9My3sjPhzLmlXH\r\na=fingerprint:sha-256 C4:5B:86:11:27:38:16:04:9B:1F:9B:D9:E5:77:EC:82:60:82:2C:0C:29:61:EF:BC:B0:D8:42:5D:99:7E:D0:0E\r\na=setup:passive\r\na=mid:0\r\na=ice-lite\r\na=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:5 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:6/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=sendonly\r\na=rtcp-mux\r\na=rtpmap:126 H264/90000\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126 nack pli\r\na=rtcp-fb:126 transport-cc\r\na=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=rtpmap:127 rtx/90000\r\na=fmtp:127 apt=126\r\na=msid:zlmediakit-mslabel zlmediakit-label\r\na=ssrc:1 cname:zlmediakit-rtp\r\na=ssrc:1 msid:zlmediakit-mslabel zlmediakit-label\r\na=ssrc:1 mslabel:zlmediakit-mslabel\r\na=ssrc:1 label:zlmediakit-label\r\na=ssrc:3 cname:zlmediakit-rtp\r\na=ssrc:3 msid:zlmediakit-mslabel zlmediakit-label\r\na=ssrc:3 mslabel:zlmediakit-mslabel\r\na=ssrc:3 label:zlmediakit-label\r\na=ssrc-group:FID 1 3\r\na=candidate:udpcandidate 1 udp 120 192.168.1.248 8000 typ host\r\na=candidate:tcpcandidate 1 tcp 115 192.168.1.248 8000 typ host tcptype passive\r\nm=audio 8000 UDP/TLS/RTP/SAVPF 109\r\nc=IN IP4 192.168.1.248\r\na=rtcp:8000 IN IP4 192.168.1.248\r\na=ice-ufrag:zlm_1\r\na=ice-pwd:bUUwxizAeY9My3sjPhzLmlXH\r\na=fingerprint:sha-256 C4:5B:86:11:27:38:16:04:9B:1F:9B:D9:E5:77:EC:82:60:82:2C:0C:29:61:EF:BC:B0:D8:42:5D:99:7E:D0:0E\r\na=setup:passive\r\na=mid:1\r\na=ice-lite\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2/sendonly urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=inactive\r\na=rtcp-mux\r\na=rtpmap:109 opus/48000/2\r\na=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1\r\na=msid:zlmediakit-mslabel zlmediakit-label\r\na=ssrc:2 cname:zlmediakit-rtp\r\na=ssrc:2 msid:zlmediakit-mslabel zlmediakit-label\r\na=ssrc:2 mslabel:zlmediakit-mslabel\r\na=ssrc:2 label:zlmediakit-label\r\na=candidate:udpcandidate 1 udp 120 192.168.1.248 8000 typ host\r\na=candidate:tcpcandidate 1 tcp 115 192.168.1.248 8000 typ host tcptype passive\r\n","type":"answer","code":0}
SDP详细解释
这是一个Session Description Protocol(SDP)的示例,它描述了一个实时媒体会话的参数。以下是对该SDP的详细解释:
v=0:表示这是SDP的版本号,为0。
o=mozilla...THIS_IS_SDPARTA-99.0 3224167891387244748 0 IN IP4 0.0.0.0:这是会话的原始创建者和会话ID的标识符,其中mozilla是创建者的用户名,THIS_IS_SDPARTA-99.0是会话名称,3224167891387244748是会话ID,0表示会话版本,IN表示网络类型为Internet,IP4表示IPv4,0.0.0.0表示源IP地址。
s=-:表示会话名称为空。
t=0 0:表示媒体流的有效时间为0,即无限期。
a=fingerprint:sha-256 F3:7B:70:7B:67:E6:9A:A4:11:83:AB:09:F0:A6:CF:74:89:17:D8:A9:05:82:CF:E5:CC:69:DB:4D:B8:7E:FB:9C:这是会话的指纹,用于验证媒体流的完整性和安全性。
a=group:BUNDLE 0 1:指定了将要使用的媒体流的标识符,此处标识符0和1表示将要使用的音频和视频流。
a=ice-options:trickle:表示使用trickle ICE协议,这是一种实时通信中常用的网络协议,用于实现ICE。
a=msid-semantic:WMS *:指定了媒体流的标识符。
m=video 9 UDP/TLS/RTP/SAVPF 120 124 121 125 126 127 97 98:这是视频流的媒体描述,其中video表示媒体类型为视频,9表示媒体流的传输端口,UDP/TLS/RTP/SAVPF表示使用UDP传输,使用TLS进行安全传输,使用RTP协议传输,使用SAVPF(Secure Audio Video Profile Framework)进行流媒体传输,120、124、121、125、126、127、97和98是视频编码的标识符。
c=IN IP4 0.0.0.0:表示媒体流的连接信息,其中IN表示网络类型为Internet,IP4表示IPv4,0.0.0.0表示目标IP地址。
a=recvonly:表示该媒体流为接收流。
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid:指定了扩展头的标识符和使用的标准。
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time:指定了扩展头的标识符和使用的标准。
a=extmap:5 urn:ietf:params:rtp-hdrext:toffset:指定了扩展头的标识符和使用的标准。
a=extmap:6/recvonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
该行表示会话中使用 RTP 扩展标识符 6,表示接收方只接收该扩展标识符的数据包。该扩展标识符的名称为 playout-delay。
a=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
该行表示会话中使用 RTP 扩展标识符 7,其名称为 transport-wide-cc-extensions-01。
a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
该行表示媒体流 126 使用 H.264 编码,并且配置了 H.264 编码器的一些参数,如 profile-level-id、level-asymmetry-allowed、packetization-mode。
a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
该行表示媒体流 97 使用 H.264 编码,并且配置了 H.264 编码器的一些参数,如 profile-level-id、level-asymmetry-allowed。
a=fmtp:120 max-fs=12288;max-fr=60
该行表示媒体流 120 使用 VP8 编码,并且设置了 VP8 编码器的最大帧大小和最大帧率。
a=fmtp:124 apt=120
该行表示媒体流 124 使用的是与媒体流 120 相关联的 RTX 流。
a=fmtp:121 max-fs=12288;max-fr=60
该行表示媒体流 121 使用 VP9 编码,并且设置了 VP9 编码器的最大帧大小和最大帧率。
a=fmtp:125 apt=121
该行表示媒体流 125 使用的是与媒体流 121 相关联的 RTX 流。
a=fmtp:127 apt=126
该行表示媒体流 127 使用的是与媒体流 126 相关联的 RTX 流。
a=fmtp:98 apt=97
该行表示媒体流 98 使用的是与媒体流 97 相关联的 RTX 流。
a=ice-pwd:c8da3d5e526162f3514da1da02b5a44a
a=ice-ufrag:9691ba55
这两行表示使用 ICE(Interactive Connectivity Establishment)协议进行 NAT 穿透。ice-pwd 表示 ICE 密码,ice-ufrag 表示 ICE 用户名。
a=mid:0
该行表示媒体流的标识符为 0。
m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97
"m=video" 指示此媒体流是视频
"9" 是传输此流的端口号
"UDP/TLS/RTP/SAVPF" 表示使用UDP、TLS、RTP和SAVPF协议传输视频
"120 121 126 97" 是视频使用的编码格式,分别是VP8、VP9、H264和H264
a=rtcp-fb:120 nack
"a=rtcp-fb" 表示媒体流使用RTCP反馈
"120" 是编码格式VP8所使用的参数
"nack" 是一种RTCP反馈机制,用于请求缺失的数据包
a=rtpmap:120 VP8/90000
"a=rtpmap" 指定了编码格式到数字映射
"120" 是VP8编码格式所使用的数字
"VP8/90000" 表示该编码格式是VP8,并且它的时钟速率为90000Hz
a=setup:actpass
"a=setup" 指示了SDP会话的网络配置参数
"actpass" 表示在传输开始前,等待对端发送控制信息来决定此端是作为主动方还是被动方
m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101
"m=audio" 指示此媒体流是音频
"9" 是传输此流的端口号
"UDP/TLS/RTP/SAVPF" 表示使用UDP、TLS、RTP和SAVPF协议传输音频
"109 9 0 8 101" 是音频使用的编码格式,分别是opus、G722、PCMU、PCMA和telephone-event
a=rtpmap:109 opus/48000/2
"a=rtpmap" 指定了编码格式到数字映射
"109" 是opus编码格式所使用的数字
"opus/48000/2" 表示该编码格式是opus,并且它的时钟速率为48000Hz,通道数为2
a=setup:actpass
"a=setup" 指示了SDP会话的网络配置参数
"actpass" 表示在传输开始前,等待对端发送控制信息来决定此端是作为主动方还是被动方
a=setup:actpass:表示本地端点愿意接受和发送媒体,但希望由远端点来选择角色。这个字段是用来协商双方之间的角色,决定哪一方负责发起和接受连接。
a=ssrc:2791796143 cname:{b5aaf774-54b0-47ec-8b26-f4957e9925d3}:表示同步信源标识符(SSRC)是2791796143,CNAME是{b5aaf774-54b0-47ec-8b26-f4957e9925d3}。SSRC是一个唯一标识符,用于识别媒体流的不同源。CNAME是同步上下文的名称,用于在同步多个媒体流时标识流的来源。
m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101:表示媒体类型是音频,使用UDP/TLS/RTP传输协议,使用SAVPF(安全音频可扩展预定义格式)的媒体格式。109,9,0,8和101是支持的媒体格式(payload type)。这里的payload type是用来标识传输的媒体格式。
c=IN IP4 0.0.0.0:表示连接的网络类型是IPv4,地址是0.0.0.0,即本地地址。这个字段是用来指定连接的网络类型和地址。
a=recvonly:表示本地端点只会接收数据,而不会发送数据。这个字段是用来协商媒体的流向,确定哪一方负责发送数据和接收数据。
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level:表示使用扩展头部(extmap)1来传输音频信号级别信息(ssrc-audio-level)。扩展头部可以用来传输一些不属于标准RTP协议的信息。
a=extmap:2/recvonly urn:ietf:params:rtp-hdrext:csrc-audio-level:表示使用扩展头部2来传输音频信号级别信息(csrc-audio-level)。这里的"/recvonly"表示本地端点只会接收数据,不会发送数据。
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid:表示使用扩展头部3来传输SDES(Session Description Protocol Security Descriptions)中的mid(媒体流ID)字段。SDES是用来为会话中的媒体流提供安全信息的协议。
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1:表示使用媒体格式109时,最大回放率为48000,支持立体声
a=setup:actpass - 表示要求对方在协商连接时扮演"主动"或"被动"角色。这里是被动,也就是等待对方发起连接。
a=ssrc:2791796143 cname:{b5aaf774-54b0-47ec-8b26-f4957e9925d3} - 表示同步信源,用于区分多个流的不同数据源,这里的ssrc为2791796143,cname为一个标识符。
m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101 - 表示媒体类型为音频(audio),端口为9,传输层协议为UDP/TLS/RTP/SAVPF,表示要使用SRTP进行安全传输,支持的编码格式为109、9、0、8、101。
c=IN IP4 0.0.0.0 - 表示连接信息,包括传输协议和IP地址。这里的0.0.0.0表示地址是动态分配的,等待对方建立连接后再确定IP地址。
a=recvonly - 表示这个端点只接收流,不发送流。
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level - 表示使用RTP头扩展,扩展id为1,urn为urn:ietf:params:rtp-hdrext:ssrc-audio-level。
a=extmap:2/recvonly urn:ietf:params:rtp-hdrext:csrc-audio-level - 表示使用RTP头扩展,扩展id为2,urn为urn:ietf:params:rtp-hdrext:csrc-audio-level,只接收这个扩展,不发送。
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid - 表示使用RTP头扩展,扩展id为3,urn为urn:ietf:params:rtp-hdrext:sdes:mid。
a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1 - 表示对109编码器的特殊参数,最大回放速率为48000,支持立体声,使用带宽内FEC。
a=fmtp:101 0-15 - 表示对101编码器的特殊参数,表示支持0到15个DSCP值(Differentiated Services Code Point)。
a=ice-pwd:c8da3d5e526162f3514da1da02b5a44a - 表示用于ICE(Interactive Connectivity Establishment)的密码。
a=ice-ufrag:9691ba55 - 表示用于ICE的用户名。
a=mid:1 - 表示媒体流的唯一标识符。
a=rtcp-mux:表示使用单个 UDP 端口进行 RTCP 传输(复用 RTCP 和 RTP)。
a=rtpmap:109 opus/48000/2:定义 RTP 负载类型编号为 109 的媒体格式为 Opus,采样率为 48000 Hz,通道数为 2。
a=rtpmap:9 G722/8000/1:定义 RTP 负载类型编号为 9 的媒体格式为 G722,采样率为 8000 Hz,通道数为 1。
a=rtpmap:0 PCMU/8000:定义 RTP 负载类型编号为 0 的媒体格式为 μ-law PCM,采样率为 8000 Hz,通道数为 1。
a=rtpmap:8 PCMA/8000:定义 RTP 负载类型编号为 8 的媒体格式为 A-law PCM,采样率为 8000 Hz,通道数为 1。
a=rtpmap:101 telephone-event/8000/1:定义 RTP 负载类型编号为 101 的媒体格式为电话事件,采样率为 8000 Hz,通道数为 1。
a=setup:actpass:表示端点希望对等端控制传输的设置,但不知道自己是主动方还是被动方,需要对等端指定。
a=ssrc:2059420909 cname:{b5aaf774-54b0-47ec-8b26-f4957e9925d3}:标识音频流的同步源(SSRC) ID 和源的 CNAME。
天色已晚,明日继续