WebRTC实现音视频通话全流程
WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC 包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。
WebRTC的应用场景
点对点视频聊天:如 微信视频 等实时视频通话应用。
多人视频会议:企业级多人视频会议系统,如飞书、钉钉、腾讯会议等。
在线教育:如腾讯课堂、网易云课堂等。
直播:游戏直播、课程直播等。
WebRTC实现音视频通话过程
- 1.server端新建socket服务(作为信令服务器),当用户进入客户端的时候将用户端与socket建立连接。
- 2.当客户端与server端建立连接后,客户端会向server端发起一个加入房间的事件,并携带房间id。
- 3.server端监听到加入房间的事件后,会将房间id添加到指定房间中,这样,所有加入同一个房间的客户端都可以接收到在该房间内发送的事件或消息。
- 4.将客户端用户分为发起方和接收方。
- 5.当客户端用户发起方发起通话时会向server端发起通话的事件。
- 6.当server端接收到这个事件后,会向在这个房间中的所有客户端广播通话事件。
- 7.当客户端用户接收方接收到这个事件,如果接收方同意了这个请求则会向server端发送同意视频的事件反之,如果挂断的话会向server端发起拒绝视频的事件。
- 8.当server端收到同意视频事件后会向客户端广播同意视频的事件。
- 9.当客户端用户发送方收到这个事件后,创建RTCPeerConnection()对象,并将音视频流加入到里面,并且将,网络信息和媒体流信息通过事件发送到server端,同时会通过onaddstream事件来获取对方的音视频流
- 10.当serve端接收到这些事件后会将这些事件已广播的形式返回,当接收方收到这些事件后会将这些信息添加到RTCPeerConnection中,同时接收方也会将这些信息通过事件发送到服务端,同时会通过onaddstream事件来获取对方的音视频流
- 11.实现视频通话。
总结:上述过程就是通过 WebRTC 提供的 API 获取各端的媒体信息 SDP 以及 网络信息 candidate ,并通过信令服务器交换,进而建立了两端的连接通道完成实时视频语音通话。
代码实现WebRTC音视频通话过程
1. 建立socket连接
sock.on('connectionSuccess', () => { console.log('连接成功'); //前端连接成功之后需要向服务器发送一个加入房间的事件 sock.emit('joinRoom', roomId) })2. 服务器接收到事件后将roomId添加到房间中
//监听加入房间的事件 sock.on('joinRoom', (roomId) => { sock.join(roomId); })3. 发起方发起视频请求,发送请求事件,同时将视频流输出到video中
// 发起方发起视频请求 const callRemote = async () => { console.log('发起视频'); //用户A向用户B发起视频请求 caller.value = true //表示当前用户是发起方,发起了视频请求 calling.value = true //表示是否呼叫中 //在发起视频的时候讲视频流输出到页面上 await getLocalStream() //通过信令服务器向用户B发起视频请求,?socket.value存在且非null或undefined的情况下,才进行方法调用, socket.value?.emit('callRemote', roomId) } //获取视频流方法 //获取本地音视频流,并进行播放 const getLocalStream = async () => { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }) localVideo.value!.srcObject = stream localVideo.value!.play() localStream.value = stream return stream }4. 服务器接收到事件,对事件进行广播
//监听发起视频通话的请求 sock.on('callRemote', (roomId) => { //广播事件 io.to(roomId).emit('callRemote'); })5. 接收方接收到广播事件,改变页面状态
// 监听服务器发来的视频请求 sock.on('callRemote', () => { //如果是发送方自己收到了这个callRemote事件,那么就直接忽略 if (!caller.value) {//不是发送方才会处理 called.value = true//接听方 calling.value = true//视频通话中 } })6. 接收方同意视频邀请
// 接收方同意视频请求 const acceptCall = () => { console.log('同意视频邀请'); //通过信令服务器通知用户A socket.value?.emit('acceptCall', roomId) }7. 服务器通知发起方用户接受了视频邀请
//通知其他用户接收了通话请求 sock.on("acceptCall", (roomId) => { io.to(roomId).emit("acceptCall"); })8. 发起方接收到了事件,将candidate信息和offer信息通过事件传递到server中 注意:如果要将此项目部署到外部进行访问则需要搭建coturn服务,此项目支持视频音频以及屏幕的音视频流,如果需要更改peer.value.addStream(localStream.value)
//监听接收了通话请求 sock.on("acceptCall", async ()