一 、安装 ws
库来创建 WebSocket 服务器
npm install ws
server.js:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
// 广播消息到所有连接的客户端
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
console.log('信令服务器已启动,监听端口 8080');
二、客户端 HTML 和 JavaScript
index.html:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebRTC 视频通话</title>
</head>
<body>
<h1>WebRTC 视频通话</h1>
<video id="localVideo" autoplay muted></video>
<video id="remoteVideo" autoplay></video>
<button id="startButton">开始通话</button>
<script>
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
const startButton = document.getElementById('startButton');
const ws = new WebSocket('ws://localhost:8080');
let localStream;
let peerConnection;
const configuration = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' } // STUN 服务器
]
};
// 获取用户媒体流
async function startCall() {
localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
localVideo.srcObject = localStream;
peerConnection = new RTCPeerConnection(configuration);
localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));
peerConnection.onicecandidate = event => {
if (event.candidate) {
ws.send(JSON.stringify({ type: 'ice-candidate', candidate: event.candidate }));
}
};
peerConnection.ontrack = event => {
remoteVideo.srcObject = event.streams[0];
};
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
ws.send(JSON.stringify({ type: 'offer', offer: offer }));
}
ws.onmessage = async (message) => {
const data = JSON.parse(message.data);
if (data.type === 'offer') {
await peerConnection.setRemoteDescription(new RTCSessionDescription(data.offer));
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);
ws.send(JSON.stringify({ type: 'answer', answer: answer }));
} else if (data.type === 'answer') {
await peerConnection.setRemoteDescription(new RTCSessionDescription(data.answer));
} else if (data.type === 'ice-candidate') {
await peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate));
}
};
startButton.onclick = startCall;
</script>
</body>
</html>
三、运行代码
node server.js