WebRTC 的核心:RTCPeerConnection

07-11 1019阅读

WebRTC 的核心:RTCPeerConnection

  • WebRTC 的核心:RTCPeerConnection
    • 创建 RTCPeerConnection 对象
    • RTCPeerConnection 与本地音视频数据绑定
    • 媒体协商
    • ICE
      • 什么是 Candidate?
      • 收集 Candidate
      • 交换 Candidate
      • 尝试连接
      • SDP 与 Candidate 消息的互换
      • 远端音视频渲染
      • 参考

        WebRTC 的核心:RTCPeerConnection

        RTCPeerConnection 是 WebRTC API 中的一个对象,它提供了两个浏览器之间的实时通信。它使用音频、视频和数据流来进行点对点通讯,没有中介服务器的参与。这是一个极其有用的特性,使得实时通信变得更加高效和私密。

        RTCPeerConnection的作用是在两个浏览器之间建立WebRTC通信通道。它使用ICE(Interactive Connectivity Establishment)协议决定浏览器之间的最佳路径来传输音频、视频和数据流。它让浏览器之间的网络连接变得简单、快捷和高效。

        RTCPeerConnection API可以用于:

        1. 视频会议
        2. 实时游戏
        3. 文件共享
        4. 流媒体
        5. 实时语音聊天

        创建 RTCPeerConnection 对象

        语法:

        new RTCPeerConnection()
        new RTCPeerConnection(configuration)
        

        参数 configuration 是一个 JSON 对象,用于提供配置新连接的选项。

        WebRTC 的核心:RTCPeerConnection

        1. iceServers:一个由 RTCIceServer 对象组成的数组,每个对象描述一个可能被 ICE 代理使用的服务器。这些通常是 STUN 或 TURN 服务器。如果未指定,则将在没有可用的 STUN 或 TURN 服务器的情况下进行连接尝试,这将连接限制为本地对等点。
        2. iceTransportPolicy:当前的 ICE 传输策略。如果未指定策略,则默认使用 all 策略,允许考虑所有的候选。可能的值有:
          • “all”:所有的 ICE 候选都会被考虑。
          • “public”:只有拥有公共 IP 地址的 ICE 候选才会被考虑,已被移除。
          • “relay”:只有 IP 地址被中继的 ICE 候选,例如那些通过 STUN 或 TURN 服务器传递的,才会被考虑。
          • bundlePolicy:指定当远程对等点与 SDP BUNDLE 标准不兼容时,应如何处理候选的协商。如果远程端点可以感知 BUNDLE,则在协商完成时,所有媒体轨道和数据通道都将捆绑到单个传输上,而不管使用何种策略,并且最初创建的任何多余传输都将在此时关闭。用技术术语来说,BUNDLE 允许两个对等点之间的所有媒体流流经单个 5 元组;也就是说,使用相同的传输协议从一个对等点的单个 IP 和端口到另一个对等点的单个 IP 和端口。如果假定为不平衡(balanced),这必须是以下字符串值之一:
            • “balanced”:ICE 代理最初为每一种内容类型(音频、视频、数据通道)创建一个 RTCDtlsTransport。如果远程端点无法感知 BUNDLE,那么每一个 DTLS 传输用于处理一种数据类型的通信。
            • “max-compat”:ICE 代理最初为每个媒体轨道创建一个 RTCDtlsTransport,对数据通道则创建一个单独的传输。如果远程端点无法感知 BUNDLE,那么对于所有的内容都会协商一个单独的 DTLS 传输。
            • “max-bundle”:ICE 代理最初仅创建一个 RTCDtlsTransport 来承载所有的 RTCPeerConnection 的数据。如果远程端点无法感知 BUNDLE,那么仅会协商一个轨道而忽略其余的轨道。
            • rtcpMuxPolicy:收集 ICE 候选时使用的 RTCP mux 策略,以支持非复用的 RTCP。可能的值有:
              • “require”:告诉 ICE 代理仅收集 RTP 的 ICE 候选,并在它们之上多路复用 RTCP。如果远程对等点不支持 RTCP 多路复用,则会话协商失败。这是默认值。
              • “negotiate”:指示 ICE 代理收集 RTP 和 RTCP 候选。如果远程对等点支持 RTCP 复用,那么 RTCP 候选将在相应的 RTP 候选之上多路复用。否则,分别返回 RTP 和 RTCP 候选。
              • peerIdentity:一个字符串,用于指定 RTCPeerConnection 目标对等点的标识。如果设置了该值(其默认为 null),则在成功验证远程对等点的身份为给定的名称之前,RTCPeerConnection 不会与其建立连接。
              • certificates:一个由 RTCCertificate 对象组成的数组,用于连接的身份验证。如果未指定该属性,则会为每一个 RTCPeerConnection 实例自动创建一组证书。尽管一个给定的连接只使用一个证书,但提供多个证书可以支持多种算法,从而提高某些情况下的连接成功的机率。此配置选项在首次指定后便不能更改;一旦设置了证书,此属性将在之后调用 RTCPeerConnection.setConfiguration() 时被忽略。
              • iceCandidatePoolSize:一个无符号 16 位整数,其指定了预获取的 ICE 候选池的大小。其默认值为 0(表示不会发生候选的预获取)。如果这个值发生变化了,那么会重新收集候选者。

        RTCPeerConnection 与本地音视频数据绑定

        RTCPeerConnection 提供2种方法进行数据绑定:addTrack() 和 addStream()。

        其中 addStream() 已经被 WebRTC 标记为过时,因此建议使用 addTrack() 方法。

        当客户端从服务端接收到 joined 消息后,它会创建 RTCPeerConnection 对象,然后调用 bindTrack() 函数将其与之前通过 getUserMedia() 采集到的音视频数据绑定:

        function bindTrack() {
        	...
        	ls.getTracks().foreach((track) => {
        		pc.addTrack(track, ls);
        		...
        	})
        	...
        }
        

        其中,ls 是一个全局变量,当通过 getUserMedia() 采集到 MediaStream 后,需要将其交由 ls 管理;pc 是 RTCPeerConnection 的缩写,也是一个全局变量,当 RTCPeerConnection 创建好后,交由 pc 管理。

        媒体协商

        当 RTCPeerConnection 对象与音视频数据绑定后,紧接着需要进行媒体协商。看双方都支持那些编码方式,支持哪些分辨率等。协商的方法是通过信令服务器交换媒体能力信息,交换的内容是 SDP 格式的。

        在 WebRTC 中,媒体协商是有严格的协商顺序的,如下图所示:

        WebRTC 的核心:RTCPeerConnection

        整个过程分为 8 步:

        1. Amy 调用 createOffer 方法创建 offer 消息。offer 消息中的内容是 Amy 的 SDP 信息。
        2. Amy 调用 setLocalDescription 方法,将本端的 SDP 信息保存起来。
        3. Amy 将 offer 消息通过信令服务器传给 Bob。
        4. Bob 收到 offer 消息后,调用 setRemoteDescription 方法将其存储起来。
        5. Bob 调用 createAnswer 方法创建 answer 消息, 同样,answer 消息中的内容是 Bob 的 SDP 信息。
        6. Bob 调用 setLocalDescription 方法,将本端的 SDP 信息保存起来。
        7. Bob 将 anwser 消息通过信令服务器传给 Amy。
        8. Amy 收到 anwser 消息后,调用 setRemoteDescription 方法,将其保存起来。

        通过以上步骤就完成了通信双方媒体能力的交换。

        ICE

        当媒体协商完成后,WebRTC 就开始建立网络连接了,其过程叫 ICE(Interactive Connectivity Establishment,交互式连接建立)。更确切地说,ICE 是在各端调用 setRemoteDescription 方法后就开始了。其操作过程如下:

        1. 收集 Candidate
        2. 交换 Candidate
        3. 按优先级尝试连接

        什么是 Candidate?

        Candidate 是 WebRTC API 的接口之一,表示用于建立 RTCPeerConnection 的候选交互连接建立(ICE)的配置信息。它是至少包含 {address, port, protocol} 三元组的一个信息集。

        RTCIceCandidate 实例属性:

        1. candidate:表示用于连接检查的候选者的传输地址的字符串。

          格式为:a=candidate:{foundation} {component} {protocol} {priority} {ip} {port} typ {type} generation {generation} ufrag {username} network_id {id} network_cost {cost}。

          以如下 candidate 为例说明其代表的含义:a=candidate:1221703924 1 udp 2122260223 192.168.0.105 51417 typ host generation 0 ufrag Q8Wv network-id 1 network-cost 10。

          typ host 表示本地候选者,使用的 IP 是 192.168.0.105,端口为 51417,使用 UDP 协议,其优先级为 2122260223,generation 表示代数,初始值为 0,用户名为 Q8Wv,如果更新 candidate 则 generation 值会递增,替换老的 candidate。

        2. sdpMid:表示候选者的媒体流标识标签的字符串,该标签在候选者关联的组件中唯一标识媒体流,如果不存在这样的关联,则为 null。
        3. sdpMLineIndex:如果值不为 null,sdpMLineIndex 表示 SDP 中候选者关联的从零开始的媒体描述索引编号。

        其他更多属性见于:RTCIceCandidate

        WebRTC 还将 Candidate 分为了四种类型:host、srflx、prflx、relay,它们的优先级依次递减。假如 WebRTC 收集到两个 Candidate,一个是 host 类型,另一个是 relay 类型,那么 WebRTC 会先尝试与 host 类型的 Candidate 建立连接,如果不成功,才会使用 relay 类型的 Candidate。

        收集 Candidate

        WebRTC 收集 Candidate 时有几种途径:

        1. host 类型的 Candidate 由主机的网卡个数决定。一般一个网卡对于一个 IP 地址,每个 IP 地址随机分配一个端口从而生成一个 host 类型的 Candidate;
        2. srflx 类型的 Candidate 由 STUN 服务器获得的 IP 地址和端口生成;
        3. relay 类型的 Candidate 由 TRUN 服务器获得的 IP 地址和端口生成。

        收集到 Candidate 后,为了通知上层,WebRTC 还在 RTCPeerConnection 对象中提供了 onicecandidate 事件。为了将收集到的 Candidate 交换给对端,需要为 onicecandidate 事件设置一个回调函数:

        pc.onicecandidate = (e) => {
        	if (e.candidate) {
        		...
        	}
        }
        

        通过该回调函数就可以获得 WebRTC 底层收集到的所有 Candidate 了。同时,还可以在函数内实现发送给对端的操作。

        交换 Candidate

        WebRTC 收集 Candidate 后,会通过信令系统将它们发送给对端。对端接收后,会与本地的 Candidate 形成 CandidatePair(连接候选者对)。

        有了 CandidatePair,WebRTC 就可以开始尝试建立连接了。

        注意,Candidate 的交换不是等所有 Candidate 收集好了再进行的,而是边收集边交换。

        尝试连接

        当 WebRTC 形成 CandidatePair 后,便开始尝试进行连接。一旦发现一个可以连通的 CandidatePair 时,就不再进行其他的连接尝试了,但发现新的 Candidate 时仍然可以继续交换。

        SDP 与 Candidate 消息的互换

        媒体协商和 ICE 都需要通信双方做信息的交换,如交换 SDP 和 Candidate。这种信息交换使用的也是信令系统,只不过需要为这种需求专门设置一个新的信令,即 message。

        信息交换的过程:

        1. 发起方向信令服务器发送 message;
        2. 服务器收到 message 后不做任何处理,直接转发给目标用户;
        3. 目标用户接收 message。

        客户端发送消息:

        function sendMsg(roomid, data) {
        	...
        	socket.emit('message', roomid, data);
        }
        

        服务器转发:

        socket.on('message', (room, data) => {
        	socket.to(room).emit('message', room, data);
        });
        

        客户端接收:

        socket.on('message', (room, data) => {
        	...
        	if (data.hasOwnProperty('type') && data.type === 'offer') {
        		...
        	} else if (data.hasOwnProperty('type') && data.type === 'answer') {
        		...
        	} else if (data.hasOwnProperty('type') && data.type === 'candidate') {
        		...
        	} else {
        		...
        	}
        });
        

        远端音视频渲染

        当各端将收集到的 Candidate 通过信令系统交换给对方后,WebRTC 内部就开始就开始尝试建立连接了。连接一旦建成,音视频数据就开始源源不断地由发送端发送给接收端。

        每当有远端的音视频数据传过来时,RTCPeerConnection 对象的 ontrack() 事件就会被触发。因此只需要给 ontrack() 事件设置一个回调函数,就可以拿到远端的 MediaStream 了。再将远端音视频流赋值给本地 标签的 srcObject 属性,就可以播放音视频数据了。

        具体代码如下所示:

        function getRemoteStream(mediaStream) {
        	...
        	// 将远端音视频流赋值给本地  标签的 srcObject 属性
        	videoElement.srcObject = mediaStream;
        }
        let pc = new RTCPeerConnection(...);
        ...
        pc.ontrack = getRemoteStream;
        ...
        

        参考

        1. https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection
        2. https://www.cnblogs.com/ssyfj/p/14811253.html
        3. https://webrtc.org.cn/webrtc-tutorial-2-signaling-stun-turn/
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]