1. 首页
  2. IT资讯

50行代码完成视频通话 (WebRTC + WebSocket)

前言

“它(WebRTC)允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输”

这是 MDN 上对 WebRTC 的描述,初次接触时无法理解 WebRTC 为什么要和 WebSocket 搭配,明明说的很清楚 不借助中间媒介 ,那 WebSocket 充当的是什么角色?整个 WebRTC 通话建立的流程又是怎样的?

开始

先看一下最终效果

50行代码完成视频通话 (WebRTC + WebSocket)

1.相关技术

本示例主要使用了 WebRTCWebSocket

  • WebRTC(Web Real-Time Communication)即网页即时通信,是一个支持网页浏览器进行实时语音对话或视频对话的API。
  • WebSocket是一种在单个TCP连接上进行全双工通信的协议。在 WebSocket 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

2.通话建立流程

简单说一下流程,如浏览器 A 想和浏览器 B 进行音视频通话:

  1. A、B 都连接信令服务器(ws);
  2. A 创建本地视频,并获取会话描述对象(offer sdp)信息;
  3. A 将 offer sdp 通过 ws 发送给 B;
  4. B 收到信令后,B 创建本地视频,并获取会话描述对象(answer sdp)信息;
  5. B 将 answer sdp 通过 ws 发送给 A;
  6. A 和 B 开始打洞,收集并通过 ws 交换 ice 信息;
  7. 完成打洞后,A 和 B 开始为安全的媒体通信协商秘钥;
  8. 至此, A 和 B 可以进行音视频通话。

引用网上的有关WebRTC建立的时序图,可能更加直观:

50行代码完成视频通话 (WebRTC + WebSocket)

从上述流程,可以发现通信双方在建立连接前需要交换信息,这也就是开头提到的 WebSocket 充当的角色:信令服务器,用于转发信息。而 WebRTC 不借助中间媒介 的意思是,在建立对等连接后,不需要借助第三方服务器中转,而是直接在两个实体(浏览器)间进行传输。

3.代码

第一步

获取视频标签,连接信令服务器,创建 RTCPeerConnection 对象。其中 RTCPeerConnection 的作用是在两个对等端之间建立连接,其构造函数支持传一个配置对象,包含ICE“打洞”(由于本示例在本机进行测试,故不需要)。

const localVideo = document.querySelector('#local-video'); const remoteVideo = document.querySelector('#remote-video'); const socket = new WebSocket('ws://localhost:8080'); const peer = new RTCPeerConnection();  socket.onmessage = () => { // todo } peer.ontrack = () => { // todo } peer.onicecandidate = () => { // todo }

第二步

获取本地摄像头/麦克风(需要允许使用权限),拿到本地媒体流(MediaStream)后,需要将其中所有媒体轨道(MediaStreamTrack)添加到轨道集,这些轨道将被发送到另一对等方。

navigator.mediaDevices.getUserMedia({ video: true, audio: true })     .then(stream => {         localVideo.srcObject = stream;         stream.getTracks().forEach(track => {             peer.addTrack(track, stream);         });     });

第三步

创建发起方会话描述对象(createOffer),设置本地SDP(setLocalDescription),并通过信令服务器发送到对等端,以启动与远程对等端的新WebRTC连接。

peer.createOffer().then(offer => {     peer.setLocalDescription(offer);     socket.send(JSON.stringify(offer)); });

当调用 setLocalDescription 方法,PeerConnection 开始收集候选人(ice信息),并发送offer_ice到对等方。这边补充第一步中的peer.onicecandidatesocket.onmessage

对等方收到ice信息后,通过调用 addIceCandidate 将接收的候选者信息传递给浏览器的ICE代理。

peer.onicecandidate = e => {     if (e.candidate) {         socket.send(JSON.stringify({             type: 'offer_ice',             iceCandidate: e.candidate         }));     }  };  socket.onmessage = e => {     const { type, sdp, iceCandidate } = JSON.parse(e.data);     if (type === 'offer_ice') {         peer.addIceCandidate(iceCandidate);     } }

第四步

接收方收到了offer信令后,开始获取摄像头/麦克风,与发起方操作一致。同时将收到offer SDP指定为连接的远程对等方属性(setRemoteDescription),并创建应答SDP(createAnswer),发送到对等端。这边补充第一步中的socket.onmessage

socket.onmessage = e => {     const { type, sdp, iceCandidate } = JSON.parse(e.data);     if (type === 'offer') {         navigator.mediaDevices.getUserMedia();        // 与发起方一致,省略         const offerSdp = new RTCSessionDescription({ type, sdp });         peer.setRemoteDescription(offerSdp).then(() => {             peer.createAnswer(answer => {                 socket.send(JSON.stringify(answer));                 peer.setLocalDescription(answer)             });         });     } }

注意:当 setLocalDescription 方法调用后,开始收集候选人信息,并发送 answer_ice 到对等方。与发送方同理,不赘述。

第五步

通过不断收集ICE信息(onicecandidate),发起方和应答方最终将建立一条最优的连接方式,此时会触发 ontrack 回调,即可获取到对等方的媒体流。

peer.ontrack = e => {     if (e && e.streams) {         remoteVideo.srcObject = e.streams[0];     } };

4.最后

整合发起方和应答方的代码,差不多50行,不算标题党!哈哈哈哈哈哈…

50行代码完成视频通话 (WebRTC + WebSocket)

完整示例相关代码已上传 github.com/shushushv/webrtc-p2p ,⭐🦆~

原作者姓名:shushushu
原出处:segmentfault
原文链接:50行代码完成视频通话 (WebRTC + WebSocket)

原文始发于:50行代码完成视频通话 (WebRTC + WebSocket)

主题测试文章,只做测试使用。发布者:玩家L-,转转请注明出处:http://www.cxybcw.com/22567.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code