基本概念
https://www.psvmc.cn/article/2022-06-16-webrtc-start.html
交互详情
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| sequenceDiagram participant A as 用户A participant WS as WS participant B as 用户B
A->>WS: 1. 创建offer并发送 sdp type:offer WS->>B: 2. sdp type:offer B->>WS: 3. sdp type:answer WS->>A: 4. sdp type:answer A->>WS: 1. 发送candidate WS->>B: 2. 发送candidate B->>WS: 3. 发送candidate WS->>A: 4. 发送candidate B->>A: 连接
|
交互的数据
1 创建offer并发送
1
| {"type":"offer","sdp":"v=0\r\no=- 72532 0 IN IP4 127.0.0.1\r\ns=sipsorcery\r\nt=0 0\r\na=group:BUNDLE 0\r\nm=video 9 UDP/TLS/RTP/SAVP 96 100\r\nc=IN IP4 0.0.0.0\r\na=ice-ufrag:SEFW\r\na=ice-pwd:ZWIYQSXNKGKSEUCBULXIQQCQ\r\na=fingerprint:sha-256 7B:8E:55:E3:27:F2:B3:30:E9:2C:A0:87:E2:C9:1F:70:F6:A7:52:97:F6:F6:04:4B:F0:2A:04:87:FD:CA:9E:B7\r\na=setup:actpass\r\na=candidate:950637637 1 udp 2113937663 192.168.3.56 62710 typ host generation 0\r\na=ice-options:ice2,trickle\r\na=mid:0\r\na=rtpmap:96 VP8/90000\r\na=rtpmap:100 H264/90000\r\na=fmtp:100 packetization-mode=1\r\na=rtcp-mux\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=end-of-candidates\r\na=sendrecv\r\na=ssrc:1819341444 cname:6fef90ad-0e6b-4af4-9220-377c2faf01d8\r\n"}
|
2 响应
1
| {"type":"answer","sdp":"v=0\r\no=- 8100819546663100148 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=msid-semantic: WMS 0eb90fdc-f221-409a-8cc2-10015551f1d1\r\nm=video 9 UDP/TLS/RTP/SAVP 96 100\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:Kz3X\r\na=ice-pwd:ci0C3HqUXi/oTbiOqzjxdNKF\r\na=ice-options:trickle\r\na=fingerprint:sha-256 4D:2B:B6:60:B9:F2:C5:9C:D9:7C:DC:7C:DA:E4:1A:A0:B6:79:D7:9D:66:9A:99:05:09:56:A4:43:FF:B3:48:E3\r\na=setup:active\r\na=mid:0\r\na=sendrecv\r\na=msid:0eb90fdc-f221-409a-8cc2-10015551f1d1 c32f714c-b627-4313-be6d-15fbbc7d8656\r\na=rtcp-mux\r\na=rtpmap:96 VP8/90000\r\na=rtpmap:100 H264/90000\r\na=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\r\na=ssrc:2948904417 cname:ufqrpgnhfhKdMI5c\r\na=ssrc:2948904417 msid:0eb90fdc-f221-409a-8cc2-10015551f1d1 c32f714c-b627-4313-be6d-15fbbc7d8656\r\n"}
|
3 并发送candidate
1
| {"candidate":"candidate:388572998 1 udp 2113937151 bd043a02-be83-461c-84d3-6ab8d12290c5.local 62712 typ host generation 0 ufrag Z/Ju network-cost 999","sdpMid":"0","sdpMLineIndex":0,"usernameFragment":"Z/Ju"}
|
SDP数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| v=0 o=- 72532 0 IN IP4 127.0.0.1 s=sipsorcery t=0 0 a=group:BUNDLE 0 m=video 9 UDP/TLS/RTP/SAVP 96 100 c=IN IP4 0.0.0.0 a=ice-ufrag:SEFW a=ice-pwd:ZWIYQSXNKGKSEUCBULXIQQCQ a=fingerprint:sha-256 7B:8E:55:E3:27:F2:B3:30:E9:2C:A0:87:E2:C9:1F:70:F6:A7:52:97:F6:F6:04:4B:F0:2A:04:87:FD:CA:9E:B7 a=setup:actpass a=candidate:950637637 1 udp 2113937663 192.168.3.56 62710 typ host generation 0 a=ice-options:ice2,trickle a=mid:0 a=rtpmap:96 VP8/90000 a=rtpmap:100 H264/90000 a=fmtp:100 packetization-mode=1 a=rtcp-mux a=rtcp:9 IN IP4 0.0.0.0 a=end-of-candidates a=sendrecv a=ssrc:1819341444 cname:6fef90ad-0e6b-4af4-9220-377c2faf01d8
|
可以看出
在SDP阶段,双方交换了各种支持的编码和IP
回发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| v=0 o=- 8100819546663100148 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE 0 a=msid-semantic: WMS 0eb90fdc-f221-409a-8cc2-10015551f1d1 m=video 9 UDP/TLS/RTP/SAVP 96 100 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:Kz3X a=ice-pwd:ci0C3HqUXi/oTbiOqzjxdNKF a=ice-options:trickle a=fingerprint:sha-256 4D:2B:B6:60:B9:F2:C5:9C:D9:7C:DC:7C:DA:E4:1A:A0:B6:79:D7:9D:66:9A:99:05:09:56:A4:43:FF:B3:48:E3 a=setup:active a=mid:0 a=sendrecv a=msid:0eb90fdc-f221-409a-8cc2-10015551f1d1 c32f714c-b627-4313-be6d-15fbbc7d8656 a=rtcp-mux a=rtpmap:96 VP8/90000 a=rtpmap:100 H264/90000 a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f a=ssrc:2948904417 cname:ufqrpgnhfhKdMI5c a=ssrc:2948904417 msid:0eb90fdc-f221-409a-8cc2-10015551f1d1 c32f714c-b627-4313-be6d-15fbbc7d8656
|
概念
在WebRTC(Web Real-Time Communication)中,SDP是“Session Description Protocol”的缩写。
SDP是一种描述多媒体会话的协议,主要用于定义和协商音视频会话的参数。
在WebRTC中,SDP用于交换会话的元数据,例如媒体格式、编解码器、传输协议和网络地址等。
具体来说,SDP用于:
- 描述会话:SDP包含了会话的所有必要信息,如视频和音频流的编解码器、分辨率、比特率等。
- 协商参数:通过SDP交换,WebRTC客户端可以协商使用哪些媒体格式和传输方式,以确保双方都能理解和处理对方发送的媒体流。
- 建立连接:SDP还用于建立和维护WebRTC连接,包括处理ICE(Interactive Connectivity Establishment)候选者和网络地址信息。
在实际应用中,SDP通常是在建立WebRTC连接时,通过信令服务器进行交换的。
信令服务器的作用是帮助客户端交换SDP信息,协商会话参数,从而成功建立P2P连接。
WebRTC中的candidate是一个包含网络地址信息的实体,它至少包括地址(IP)、端口(Port)、协议(Protocol)三元组,还可能包括Candidate类型、用户名(ufrag)、网络ID(network_id)、网络成本(network_cost)等其他信息。
Web端WebRTC示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <!DOCTYPE html> <head> <title>WebRTC</title> </head> <body> <video controls autoplay="autoplay" id="videoCtl" width="640" height="480"></video> <div> <label for="websockurl">WS:</label><input type="text" id="websockurl" size="40" /> <button type="button" class="btn btn-success" onclick="start();">Start</button> <button type="button" class="btn btn-success" onclick="closePeer();">Close</button> </div> </body>
<script type="text/javascript"> const WEBSOCKET_URL = "ws://127.0.0.1:8081/ws" document.querySelector('#websockurl').value = WEBSOCKET_URL; let pc, ws;
async function start () { var ws_url = document.querySelector('#websockurl').value; pc = new RTCPeerConnection(); let stream = await navigator .mediaDevices .getUserMedia({ video: true }) stream.getTracks().forEach(track => pc.addTrack(track, stream)) pc.ontrack = evt => document.querySelector('#videoCtl').srcObject = evt.streams[0]; pc.onicecandidate = evt => evt.candidate && ws.send(JSON.stringify(evt.candidate)); ws = new WebSocket(ws_url, []); ws.onmessage = async function (evt) { const obj = JSON.parse(evt.data); if (obj?.sdp) { await pc.setRemoteDescription(new RTCSessionDescription(obj)); if (pc.signalingState === 'have-remote-offer') { let answer = await pc.createAnswer(); await pc.setLocalDescription(answer); ws.send(JSON.stringify(pc.localDescription)) } } else if (obj?.candidate) { await pc.addIceCandidate(obj); } }; ws.onopen = async () => { const offer = await pc.createOffer(); await pc.setLocalDescription(offer); ws.send(JSON.stringify(offer)) }; }
async function closePeer () { await pc?.close(); await ws?.close(); }
start(); </script>
|