WebRTC技术解析

WebRTC技术解析

一个无需插件、开箱即用的 P2P 音视频传输方案

什么是 WebRTC

WebRTC(Web Real-Time Communication)是 Google 开源的一项实时通信技术,直接内置于浏览器,无需安装任何插件或第三方软件,就能实现浏览器之间的音视频通话、数据传输和屏幕共享。

核心指标 :端到端延迟可控制在 200ms 以内 ,相比传统基于服务器的轮询方案延迟降低 90% ,且服务器带宽成本可减少 70% 以上(因为媒体流不经过服务器中转)。

解决了什么问题

传统网页实现视频通话需要:

  • 浏览器插件(Flash、Silverlight)→ 用户需手动安装,已淘汰

  • RTMP + Flash 流媒体服务器 → 延迟高、维护复杂

  • Socket.io + 服务端转发 → 服务器压力大,无法承载大规模并发

WebRTC 的核心突破:

  1. NAT 穿透 :通过 ICE(交互式连接建立)协议自动尝试 STUN/TURN 服务器,成功率可达 95% 以上

  2. 端到端加密:基于 DTLS 和 SRTP,媒体流传输过程全程加密

  3. 自适应码率:根据网络状况动态调整视频分辨率、帧率和码率,弱网下仍能保持通话

  4. 直接 P2P 传输 :媒体流不经过服务器,降低服务端带宽消耗 80% 以上

最简单的使用流程

WebRTC 连接建立需要信令服务器 (可用 Socket.io 实现)来交换连接信息,但实际媒体流是 P2P 的。

1. 获取本地媒体流

javascript 复制代码
// 获取摄像头和麦克风
const localStream = await navigator.mediaDevices.getUserMedia({
  video: true,
  audio: true
});
// 将流绑定到 video 元素
document.getElementById('localVideo').srcObject = localStream;

2. 创建 RTCPeerConnection 并添加流

javascript 复制代码
// 配置 STUN 服务器(用于 NAT 穿透)
const configuration = {
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
};
const peerConnection = new RTCPeerConnection(configuration);
// 将本地流的所有 track 添加到连接中
localStream.getTracks().forEach(track => {
  peerConnection.addTrack(track, localStream);
});
// 监听远程流并播放
peerConnection.ontrack = (event) => {
  document.getElementById('remoteVideo').srcObject = event.streams[0];
};

3. 创建 Offer 并交换 SDP

发起方(Caller)

javascript 复制代码
// 创建 offer(包含本地媒体能力描述)
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
// 通过信令服务器发送 offer 给对端
signalingSocket.emit('offer', { offer });

接收方(Callee)

javascript 复制代码
// 收到 offer 后设置远程描述,并创建 answer
await peerConnection.setRemoteDescription(offer);
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);
// 发送 answer 回对端
signalingSocket.emit('answer', { answer });

发起方收到 answer

javascript 复制代码
await peerConnection.setRemoteDescription(answer);
// 此时连接建立完成,ontrack 会触发

4. ICE 候选交换

连接过程中,浏览器会自动收集 ICE 候选(即可能的网络路径),双方需互相交换:

javascript

javascript 复制代码
// 监听本地 ICE 候选
peerConnection.onicecandidate = (event) => {
  if (event.candidate) {
    signalingSocket.emit('ice-candidate', { candidate: event.candidate });
  }
};
// 收到对端候选时添加
signalingSocket.on('ice-candidate', async ({ candidate }) => {
  await peerConnection.addIceCandidate(candidate);
});

完整的最小 Demo(配合 Socket.io 信令)

服务端(server.js)

javascript 复制代码
const io = require('socket.io')(3000);
io.on('connection', (socket) => {
  socket.on('offer', (data) => socket.broadcast.emit('offer', data));
  socket.on('answer', (data) => socket.broadcast.emit('answer', data));
  socket.on('ice-candidate', (data) => socket.broadcast.emit('ice-candidate', data));
});

客户端核心代码(省略 HTML 元素绑定)

javascript 复制代码
// 统一封装信令处理
const socket = io('http://localhost:3000');
let pc = null;
async function startCall(isInitiator) {
 const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
 document.getElementById('localVideo').srcObject = stream;

const config = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };
 pc = new RTCPeerConnection(config);

stream.getTracks().forEach(t => pc.addTrack(t, stream));
 pc.ontrack = e => document.getElementById('remoteVideo').srcObject = e.streams[0];
 pc.onicecandidate = e => e.candidate && socket.emit('ice-candidate', e.candidate);

if (isInitiator) {
 const offer = await pc.createOffer();
 await pc.setLocalDescription(offer);
 socket.emit('offer', { offer });
 }

socket.on('offer', async ({ offer }) => {
 await pc.setRemoteDescription(offer);
 const answer = await pc.createAnswer();
 await pc.setLocalDescription(answer);
 socket.emit('answer', { answer });
 });

socket.on('answer', async ({ answer }) => {
 await pc.setRemoteDescription(answer);
 });

socket.on('ice-candidate', async ({ candidate }) => {
 await pc.addIceCandidate(candidate);
 });
}
// 页面加载后决定是否作为发起方(例如通过 URL 参数)
startCall(window.location.search.includes('initiator=true'));
相关推荐
喵了几个咪1 天前
Kratos WebRTC 传输中间件:H5游戏P2P实时音视频与数据通信实战
游戏·微服务·中间件·golang·webrtc·实时音视频·kratos
喵个咪2 天前
Kratos + WebRTC 实战:实现浏览器 P2P 音视频通话与实时数据通信
后端·微服务·webrtc
肖爱Kun3 天前
Webrtc本端发candidate给对端
webrtc
肖爱Kun3 天前
Webrtc本端和对端信令交互步骤
服务器·webrtc
肖爱Kun4 天前
Webrtc信令交互
服务器·webrtc
Fisher3Star6 天前
WebRTC Transport 两种创建方式的差异解析
webrtc
Fisher3Star6 天前
FFmpeg推流至Mediasoup全流程指南
webrtc
Fisher3Star6 天前
mediasoup 创建Router全流程详解
webrtc
声网6 天前
OpenAI 的 WebRTC 秘密架构:没有 SFU?没有问题!丨 Voice Agent 学习笔记
学习·架构·webrtc