webrtc js实现
WebRTC JavaScript 实现
WebRTC(Web Real-Time Communication)是一种支持浏览器实时通信的开放标准。以下是通过 JavaScript 实现 WebRTC 的关键步骤和技术要点。
建立连接
WebRTC 的核心是建立点对点(P2P)连接。需要使用 RTCPeerConnection 对象来管理连接。创建一个实例并配置 STUN/TURN 服务器以穿越 NAT 和防火墙。
const configuration = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'turn:turn.example.com', username: 'user', credential: 'pass' }
]
};
const peerConnection = new RTCPeerConnection(configuration);
媒体流处理
获取本地媒体流(如摄像头和麦克风)并通过 addTrack 方法添加到连接中。
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
stream.getTracks().forEach(track => {
peerConnection.addTrack(track, stream);
});
document.getElementById('localVideo').srcObject = stream;
});
信令交换
WebRTC 需要信令服务器交换 SDP(Session Description Protocol)和 ICE(Interactive Connectivity Establishment)候选。通过 createOffer 和 createAnswer 生成 SDP 并发送给远端。
peerConnection.createOffer()
.then(offer => peerConnection.setLocalDescription(offer))
.then(() => {
// 发送 offer 到远端
sendSignalingMessage({ type: 'offer', sdp: peerConnection.localDescription });
});
peerConnection.onicecandidate = event => {
if (event.candidate) {
// 发送 ICE 候选到远端
sendSignalingMessage({ type: 'ice', candidate: event.candidate });
}
};
处理远端信号
接收远端发送的 SDP 和 ICE 候选,并通过 setRemoteDescription 和 addIceCandidate 处理。
// 处理远端 offer
peerConnection.setRemoteDescription(remoteOffer)
.then(() => peerConnection.createAnswer())
.then(answer => peerConnection.setLocalDescription(answer))
.then(() => {
// 发送 answer 到远端
sendSignalingMessage({ type: 'answer', sdp: peerConnection.localDescription });
});
// 处理 ICE 候选
peerConnection.addIceCandidate(new RTCIceCandidate(remoteCandidate));
显示远端流
通过 ontrack 事件捕获远端媒体流并显示。
peerConnection.ontrack = event => {
document.getElementById('remoteVideo').srcObject = event.streams[0];
};
错误处理
监听 oniceconnectionstatechange 和 onnegotiationneeded 事件以处理连接状态变化和重新协商。
peerConnection.oniceconnectionstatechange = () => {
if (peerConnection.iceConnectionState === 'failed') {
// 处理连接失败
}
};
完整示例
以下是一个简单的 WebRTC 视频通话实现示例:
<video id="localVideo" autoplay muted></video>
<video id="remoteVideo" autoplay></video>
<script>
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
const peerConnection = new RTCPeerConnection(configuration);
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
localVideo.srcObject = stream;
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
});
peerConnection.ontrack = event => {
remoteVideo.srcObject = event.streams[0];
};
peerConnection.onicecandidate = event => {
if (event.candidate) {
sendSignalingMessage({ type: 'ice', candidate: event.candidate });
}
};
function startCall() {
peerConnection.createOffer()
.then(offer => peerConnection.setLocalDescription(offer))
.then(() => {
sendSignalingMessage({ type: 'offer', sdp: peerConnection.localDescription });
});
}
function handleRemoteOffer(offer) {
peerConnection.setRemoteDescription(offer)
.then(() => peerConnection.createAnswer())
.then(answer => peerConnection.setLocalDescription(answer))
.then(() => {
sendSignalingMessage({ type: 'answer', sdp: peerConnection.localDescription });
});
}
</script>
注意事项
- 信令服务器需要自行实现,可以使用 WebSocket 或 HTTP 长轮询。
- STUN 服务器用于获取公网 IP,TURN 服务器用于中继流量(在 P2P 失败时使用)。
- 跨浏览器兼容性需测试,不同浏览器可能对编解码器支持不同。
- 安全性方面,确保使用 HTTPS 和 WSS(WebSocket Secure)以保护通信。







