在浏览器上实现一对一实时音视频通信是WebRTC最主要的应用场景。由于主流的浏览器都已支持了WebRTC,因此在浏览器中实现一对一通信很容易,只要几行代码就可以实现。
目前像Chrome、Safari、Firefox等世界上主流的浏览器都已支持WebRTC。
检测设备
进行一对一通信之前,需要对设备进行检测,看看主机上都支持哪些设备,检测设备使用mediaDevices.enumerateDevices()即可,该方法返回一个可用设备的列表。
获得设备列表主要是为了得到设备的信息来获取对应设备采集到的数据,例如,video能得到视频数据,audio能够得到音频数据。
采集数据
通过enumerateDevices()接口获得音视频设备后,就可以选择其中的设备进行数据采集了,采集数据使用mediaDevices.getUserMedia(),该方法接收采集数据的配置对象,这个对象的目的是告诉浏览器需要采集什么设备的数据,例如,要采集video的数据,就需要配置{video:true},如果对视频的宽高有限制,可以使用{video:{width:100,height:100}}限制。
显示数据
采集到的数据之后就需要把数据显示,如果是视频数据使用video元素显示,通过id得到video元素后,设置srcObject就能在video元素中显示摄像头拍到的画面。
发送信令消息
当采集到数据之后,就需要连接服务器,向服务器发送消息,让服务器把消息转发给对应的客户端。
在发送消息之前需要实现信令系统,让客户端与信令服务器可以互通。
其原理为:每次发送/接收一个信令后,客户端都根据状态机当前的状态做相应的逻辑处理。比如当客户端刚启动时,其处于Init状态,在此状态下,用户只能向服务端发送join消息,待服务端返回joined消息后,客户端的状态机发生了变化,变成了joined状态后,才能开展后续工作。
let pc = new RTCPeerConnection(configuration);
在创建RTCPeerConnection对象时,需要给它传输一个参数。这个参数是一个JSON格式的数据,通过该参数可以对WebRTC中数据传输方式做一些策略选择.
mediaDevices.getUserMedia({video:true}).then(res => {
res.getTracks().forEach((track)=>{
pc.addTrack(track , ls);
});
});
在建立网络连接前需要收集candidate,而Candidate正是WebRTC用来描述它可以连接的远端的基本信息,因此它是至少包括{address,port,protocol}三元组的一个信息集。
pc.onicecandidate = (e) => {
if(e.candidate){}
}
当通信双方需要交换信息时,发起方首先向信令服务器发送message消息,服务端收到message消息后不做任何处理,直接将该消息转发给目标用户。
// 客户端向服务器发送数据
socket.emit('message ', 'hello');
// 客户端接受服务器发送的消息
socket.on('message ', (roomid , data) => {
if(data.hasOwnProperty('type') && data.type === 'offer ') {
//……
}else if(data.hasOwnProperty('type') && data.type === 'answer '){
//……
}else if (data.hasOwnProperty('type')}else{
// ……
}
});
当各端将收集到的Candidate通过信令系统交换给对方后,WebRTC内部就开始尝试建立连接了。连接一旦建成,音视频数据就开始源源不断地由发送端发送给接收端。
在播放音视频数据之前,我们需要将远端传来的音视频数据流与本地标签绑定才行。具体的做法是将收到的音视频数据流(MediaStream)赋值给标签的srcObject属性 。
pc.ontrack = (e) => {
videoEl.srcObject = e.mediaStream;
}