目录
前端实现在线视频通话主要借助WebRTC,WebRTC(Web Real-Time Communication)是一种支持网络浏览器和移动应用进行实时音视频通话的开源技术。
WebRTC使浏览器能够直接进行点对点(peer-to-peer)的实时通信,而不需要借助中介服务器,大大简化了音视频通话、数据共享等实时互动应用的开发。
二、实现流程
-
用户A和用户B打开页面进行通话
-
用户A创建WebRTC offer并发送给服务器
-
服务器将 offer 转发给用户B
-
用户B生成 answer并发送给服务器
-
服务器将 answer 转发给用户A
-
用户A和用户B通过交换ICE candidate 建立点对点连接
-
双方开始视频通话
三、代码
html内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #333;
}
.video-container {
display: flex;
flex-direction: column;
align-items: center;
}
video {
width: 600px;
border: 2px solid #fff;
margin: 10px;
background: #000;
}
</style>
</head>
<body>
<div class="video-container">
<video id="localVideo" autoplay muted></video>
<video id="remoteVideo" autoplay></video>
</div>
<script type="text/module" src="./socket.io.js"></script>
<script type="text/module" src="./index.js"></script>
</body>
</html>
index.js
const socket = io(); // 获取视频元素
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
const configuration = { // 设定STUN服务器
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
}
const peerConnection = new RTCPeerConnection(configuration); // 创建RTCPeerConnection对象
// 获取本地媒体流
navigator.mediaDevices.getUserMedia({video: true, audio: true}).then(stream => {
localVideo.srcObject = stream;
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream))
}).catch(error => {
console.error('error', error);
})
peerConnection.onicecandidate = event => { // 处理ICE候选
if(event.candidate) {
socket.emit('ice-candidate', event.candidate)
}
}
peerConnection.ontrack = event => { // 显示远程视频流
remoteVideo.srcObject = event.streams[0]
}
socket.on('offer', async offer => { // 处理信令信息
if(!peerConnection.remoteDescription) {
await peerConnection.setRemoteDescription(new RTCSessionDescription(offer))
const answer = await peerConnection.createAnswer()
await peerConnection.setLocalDescription(answer)
socket.emit('answer', answer)
}
})
socket.on('ice-candidate', async candidate => {
if(candidate) {
try {
await peerConnection.addIceCandidate(candidate)
} catch(error) {
console.error('error', error);
}
}
})
peerConnection.onnegotiationneeded = async () => { // 创建offer
const offer = await peerConnection.createOffer()
await peerConnection.setLocalDescription(offer)
socket.emit('offer', offer)
}
socket.io.js (npm install express socket.io)
const express = require('express')
const http = require('http')
const socketIo = require('socket.io')
const app = express()
const server = http.createServer(app)
const io = socketIo(server)
app.use(express.static(__dirname))
io.on('connection', socket => {
console.log('用户连上了!!!');
socket.on('offer', offer => {
socket.broadcast.emit('offer', offer)
})
socket.on('answer', answer => {
socket.broadcast.emit('answer', answer)
})
socket.on('ice-candidate', candidate => {
socket.broadcast.emit('ice-candidate', candidate)
})
socket.on('disconnect', () => {
console.log('断开连接了!!!');
})
})
server.listen(5500, () => {
console.log('5500端口连接上了----');
})