相关技术栈
对于移动端来说,大多是视频聊天功能都是采用的Native端的代码来实现,这种方式性能好,兼容性强但是开发成本也会高一些,那么本文就来介绍一下采用纯H5的方式来实现视频聊天功能。
- WebRTC
- Socket.io
- Node.js
项目截图:
体验地址:https://app.nihaoshijie.com.cn/webrtc/index.html
推荐使用Safari打开。
WebRTC介绍
WebRTC 主要提供了三个核心的 API:
- getUserMedia:可以获取本地的媒体流,一个流包含几个轨道,比如视频和音频轨道。
- getDisplayMedia:获取电脑屏幕的视频流,不过暂时无法获取音频媒体流,如果需要音频流,手动添加到轨道内,使之同步播放。
- RTCPeerConnection:用于建立 P2P 连接以及传输多媒体数据。
- RTCDataChannel:建立一个双向通信的数据通道,可以传递多种数据类型。
通过这几个 API,我们可以获取本地的音视频流,然后与其他浏览器建立点对点连接并将音视频流发送给对方,还可以建立一个建立一个双向的数据通道,发送文本、文件等实时数据。
本次的项目,我们主要用到的是getUserMedia
和RTCPeerConnection
相关的API。
getUserMedia音视频采集 API
可以使用浏览器提供的getUserMedia
接口,采集本地的音视频。
const localVideo = document.getElementById('local-video');
// 非安全模式(非https/localhost)下 navigator.mediaDevices 会返回 undefined
const mediaStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
localVideo.srcObject = mediaStream;
RTCPeerConnection创建点对点连接的 API
RTCPeerConnection
作为创建点对点连接的 API,是我们实现音视频实时通信的关键,主要会用到以下方法和事件:
媒体协商方法
createOffer
createAnswer
setLocalDesccription
setRemoteDesccription
重要事件onicecandidate
ontrack
对于点对点连接,就需要有发送方和接收方,对应上面的代码,分别是:
发送方:
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); // 接收方发送信令消息
添加音视频流:
// 添加音视频流
mediaStream.getTracks().forEach(track => {
pc.addTrack(track, mediaStream);
});
接收音视频流:
remotePeer.ontrack = function(evt) {
const remoteVideo = document.getElementById('remote-video');
remoteVideo.srcObject = evt.streams[0];
}
有些会采用addstream
和onaddstream
属于老版本的API,这里不再推荐使用。
通信协商流程
在 WebRTC 中,有一个专门的协议,称为Session Description Protocol(SDP),可以用于描述上述这类信息。因此参与音视频通讯的双方想要了解对方支持的媒体格式,必须要交换 SDP 信息。而交换 SDP 的过程,通常称之为媒体协商。整个媒体协商流程如下:
呼叫端创建 Offer(createOffer)并将 offer 消息(内容是呼叫端的 SDP 信息)通过信令服务器传送给接收端,同时调用 setLocalDesccription 将含有本地 SDP 信息的 Offer 保存起来。
接收端收到对端的 Offer 信息后调用 setRemoteDesccription 方法将含有对端 SDP 信息的 Offer 保存起来,并创建 Answer(createAnswer)并将 Answer 消息(内容是接收端的 SDP 信息)通过信令服务器传送给呼叫端。
呼叫端收到对端的 Answer 信息后调用 setRemoteDesccription 方法将含有对端 SDP 信息的 Answer 保存起来。
更多关于WebRTC相关的文档可以参考[官网地址]webrtc.github.io/webrtc-org/architecture/
项目代码
在这里就不整体贴大段的代码来讲解了,感兴趣的童鞋可以参考源码[GitHub]github.com/lvming6816077/liveone来理解,这里笔者简单的说明一下整体的代码逻辑。
- 对于Vue端主要实现的是视频的预览功能和一些来电或者响应相关的CSS3动画。
- 对于Node.js端主要实现的是实时的信息通信(socket.io的room相关API),包括了识别对方的信令信息和用户的一些基本头像昵称信息的通信。
- 整体的WebRTC协议的逻辑都是安装上文中所讲解的代码方式来体现。
点击查看更多内容