一、相关API简介
在前面的章节中,已经对WebRTC相关的重要知识点进行了介绍,包括涉及的网络协议、会话描述协议、如何进行网络穿透等,剩下的就是WebRTC的API了。
WebRTC通信相关的API非常多,主要完成了如下功能:
- 信令交换
- 通信候选地址交换
- 音视频采集
- 音视频发送、接收
相关API太多,为避免篇幅过长,文中部分采用了伪代码进行讲解。详细代码参考文章末尾,也可以在笔者的Github上找到,欢迎留言交流。
二、信令交换
信令交换是WebRTC通信中的关键环节,交换的信息包括编解码器、网络协议、候选地址等。对于如何进行信令交换,WebRTC并没有明确说明,而是交给应用自己来决定,比如可以采用WebSocket。
发送方伪代码如下:
const pc = new RTCPeerConnection(iceConfig);
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
sendToPeerViaSignalingServer(SIGNALING_OFFER, offer); // 发送方发送信令消息
接收方伪代码如下:
const pc = new RTCPeerConnection(iceConfig);
await pc.setRemoteDescription(offer);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
sendToPeerViaSignalingServer(SIGNALING_ANSWER, answer); // 接收方发送信令消息
三、候选地址交换服务
当本地设置了会话描述信息,并添加了媒体流的情况下,ICE框架就会开始收集候选地址。两边收集到候选地址后,需要交换候选地址,并从中知道合适的候选地址对。
候选地址的交换,同样采用前面提到的信令服务,伪代码如下:
// 设置本地会话描述信息
const localPeer = new RTCPeerConnection(iceConfig);
const offer = await pc.createOffer();
await localPeer.setLocalDescription(offer);
// 本地采集音视频
const localVideo = document.getElementById('local-video');
const mediaStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
localVideo.srcObject = mediaStream;
// 添加音视频流
mediaStream.getTracks().forEach(track => {
localPeer.addTrack(track, mediaStream);
});
// 交换候选地址
localPeer.onicecandidate = function(evt) {
if (evt.candidate) {
sendToPeerViaSignalingServer(SIGNALING_CANDIDATE, evt.candidate);
}
}
四、音视频采集
可以使用浏览器提供的getUserMedia
接口,采集本地的音视频。
const localVideo = document.getElementById('local-video');
const mediaStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
localVideo.srcObject = mediaStream;
五、音视频发送、接收
将采集到的音视频轨道,通过addTrack
进行添加,发送给远端。
mediaStream.getTracks().forEach(track => {
localPeer.addTrack(track, mediaStream);
});
远端可以通过监听ontrack
来监听音视频的到达,并进行播放。
remotePeer.ontrack = function(evt) {
const remoteVideo = document.getElementById('remote-video');
remoteVideo.srcObject = evt.streams[0];
}
六、完整代码
包含两部分:客户端代码 和 服务端代码。
1、客户端代码:
const socket = io.connect('http://localhost:3000');
const CLIENT_RTC_EVENT = 'CLIENT_RTC_EVENT';
const SERVER_RTC_EVENT = 'SERVER_RTC_E