天天看点

WebRTC 之通信—PeerConnections 连接

作者:音视频开发老舅

PeerConnections 用于 WebRTC 用户之间的连接,通过 PeerConnections 连接的用户之间可以发送音视频实进行时通信。new RTCPeerConnection 即可创建一个 PeerConnection 连接,这个 PeerConnection 可以与其他 PeerConnection 进行连接,连接成功即可发送音视频数据。

SDP

PeerConnection 连接需要进行 SDP 交换,因为想要互相进行音视频发送,需要了解对端对于音视频协议格式等相关功能的支持情况,想要顺利发送数据需要双端取交集,保证达成一致才能正常发送,SDP 就描述了这些信息,因此连接时需要互相给对端发送 SDP 信息。

【免费】FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发-学习视频教程-腾讯课堂

C++音视频开发学习资料:点击莬费领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)

RTCPeerConnection 实例上有 createOffer 和 createAnswer 两个方法可以创建 SDP, WebRTC 中要求一端发 offer 另一端回复 answer 来确保连接正确,这里看一个双端 RTCPeerConnection SDP 的连接流程:

  1. A createOffer offerA
  2. A setLocalDescription offerA
  3. A 发送 offerA 给 B
  4. B setRemoteDescription offerA
  5. B createAnswer AnswerB
  6. B setLocalDescription AnswerB
  7. B 发送 AnswerB 给 A
  8. A setRemoteDescription AnswerB

至此双端都接收了对面的 SDP 信息,示例代码:

let PC1, PC2;
PC1 = new RTCPeerConnection({});
PC2 = new RTCPeerConnection({});

const offer = await PC1.createOffer({ offerToReceiveAudio: 1, offerToReceiveVideo: 1 });
await PC1.setLocalDescription(offer);
await PC2.setRemoteDescription(offer);
const answer = await PC2.createAnswer();
await PC2.setLocalDescription(answer);
await PC1.setRemoteDescription(answer);           

ICE

除了交换 SDP,这里还需要进行 ICE 信息传递。SDP 协商了媒体传输格式,而ICE 是用来与对端协商连接方式的。在 RTCPeerConnection 对象上提供了 icecandidate 事件和 addIceCandidate 方法,当一端执行 setLocalDescription 是,表示 SDP 完成,准备连接了,这时会在当前对象上触发 icecandidate 事件,其中带有 ICE 传输的 candidate 信息,我们需要把这个信息发到对端,通过 addIceCandidate 添加给对端,完成 ICE 连接:

let PC1, PC2;
PC1 = new RTCPeerConnection({});
PC2 = new RTCPeerConnection({});

PC1.addEventListener('icecandidate', e => {
    PC2.addIceCandidate(e.candidate);
});
PC2.addEventListener('icecandidate', e => {
    PC1.addIceCandidate(e.candidate);
});           

之后就可以进行发送了,我们可以使用 RTCPeerConnection 对象上的 addTrack 方法来添加发送的音视频轨道数据,通过上一篇我们知道 track 可以通过 getUserMedia 获取:

C++音视频开发学习资料:点击莬费领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)

const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach(track => PC1.addTrack(track, stream));           

而在另一端可以通过监听 RTCPeerConnection 上的 track 事件来接收,可以使用 video 标签查看收到的数据:

remotePC.addEventListener('track', e => {
	if (video.srcObject !== e.streams[0]) {
    video.srcObject = e.streams[0];
  }
});           

至此,整个 PeerConnection 创建连接发送音视频的过程就完成了,但是目前我们的 PC1 和 PC2 是在一起的,在实际应用中他们肯定是两个用户,这时 SDP 和 ICE 交换将不再是本地行为,我们需要一个服务器来转发对端的信息,在 RTC 应用中这个服务器成为信令服务器。本文是 RTC 系列第二篇,在下一篇会使用 PeerConnection + 信令服务器实现真正意义上的 RTC 应用。

继续阅读