前端 WebRTC 全解析与应用

一、WebRTC 是什么

WebRTC,全称 Web Real-Time Communication,是浏览器提供的一套实时音视频和点对点数据通信能力。它允许网页在不安装插件的情况下,直接采集摄像头、麦克风、屏幕内容,并在浏览器、移动端、桌面端之间进行低延迟传输。

WebRTC 常见应用包括:

  • 音视频通话
  • 在线会议
  • 直播连麦
  • 屏幕共享
  • 在线教育
  • 远程面试
  • 远程协助
  • 浏览器 P2P 文件传输
  • 低延迟互动游戏
  • 实时白板和协同编辑

一句话概括:WebRTC 是浏览器原生的实时通信基础设施。

flowchart TD A[浏览器页面] --> B[采集摄像头和麦克风] A --> C[建立 RTCPeerConnection] C --> D[协商媒体能力] D --> E[建立连接] E --> F[传输音视频] E --> G[传输 DataChannel 数据]

二、WebRTC 解决了什么问题

传统 Web 应用如果要做音视频通信,通常需要插件、客户端、Flash 或专门的原生应用。WebRTC 把实时通信能力下沉到了浏览器,让网页可以直接完成音视频采集、编码、传输、解码和播放。

它主要解决以下问题。

1. 浏览器直接采集媒体

通过 getUserMedia,网页可以在用户授权后访问摄像头和麦克风。

2. 低延迟实时传输

WebRTC 基于 UDP、RTP、SRTP、DTLS、ICE 等技术,目标是降低端到端延迟。

3. 点对点通信

在网络允许的情况下,两个浏览器可以直接建立 P2P 连接,不必让所有音视频流都经过业务服务器。

4. NAT 穿透

现实网络中,大多数设备都在路由器、防火墙或 NAT 后面。WebRTC 通过 ICE、STUN、TURN 尝试建立可用连接。

5. 安全传输

WebRTC 默认要求加密传输,媒体流通常通过 SRTP 保护,数据通道通过 DTLS 保护。

flowchart TD A[实时通信需求] --> B[媒体采集] A --> C[低延迟传输] A --> D[网络穿透] A --> E[安全加密] B --> F[getUserMedia] C --> G[RTP 和 SRTP] D --> H[ICE STUN TURN] E --> I[DTLS 加密]

三、WebRTC 的核心 API

WebRTC 前端开发主要围绕几个核心 API 展开。

API 作用
navigator.mediaDevices.getUserMedia 获取摄像头和麦克风
navigator.mediaDevices.getDisplayMedia 获取屏幕共享流
RTCPeerConnection 建立点对点连接,传输音视频
RTCDataChannel 点对点传输任意数据
MediaStream 表示媒体流,由多个 Track 组成
MediaStreamTrack 表示单条音频轨或视频轨
RTCSessionDescription 表示 SDP offer 或 answer
RTCIceCandidate 表示 ICE 候选连接地址
flowchart TD A[WebRTC API] --> B[getUserMedia] A --> C[getDisplayMedia] A --> D[RTCPeerConnection] A --> E[RTCDataChannel] B --> F[获取音视频流] C --> G[获取屏幕共享] D --> H[传输媒体流] E --> I[传输自定义数据]

四、WebRTC 的整体架构

WebRTC 并不是只有浏览器之间的直接连接。一个完整系统通常还需要业务服务器和信令服务器。

典型架构包括:

  • 前端页面:采集、播放、协商、连接管理。
  • 信令服务器:交换 offer、answer、ICE candidate 等协商信息。
  • STUN 服务器:帮助发现公网地址。
  • TURN 服务器:P2P 不通时转发媒体流。
  • 业务服务器:房间、用户、权限、录制、计费、日志等业务能力。
flowchart TD A[用户 A 浏览器] --> B[信令服务器] C[用户 B 浏览器] --> B[信令服务器] A --> D[STUN 服务器] C --> D[STUN 服务器] A --> E[TURN 服务器] C --> E[TURN 服务器] A --> F[媒体连接] C --> F[媒体连接] B --> G[业务服务器]

需要注意:信令服务器不属于 WebRTC 标准的一部分,WebRTC 只规定浏览器实时通信能力,如何交换协商消息由业务自行实现。常见信令通道可以是 WebSocket、Socket.IO、HTTP 轮询、MQTT 等。

五、媒体采集:getUserMedia

1. 获取摄像头和麦克风

js 复制代码
async function startLocalMedia() {
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: true,
    video: true
  });

  const video = document.querySelector('#localVideo');
  video.srcObject = stream;
}

浏览器会弹出权限确认。只有用户授权后,页面才能获得媒体流。

2. 指定采集约束

js 复制代码
const stream = await navigator.mediaDevices.getUserMedia({
  audio: {
    echoCancellation: true,
    noiseSuppression: true,
    autoGainControl: true
  },
  video: {
    width: { ideal: 1280 },
    height: { ideal: 720 },
    frameRate: { ideal: 30 },
    facingMode: 'user'
  }
});

常见视频约束包括分辨率、帧率、前后摄像头等。常见音频约束包括回声消除、降噪、自动增益。

3. 获取设备列表

js 复制代码
const devices = await navigator.mediaDevices.enumerateDevices();
const cameras = devices.filter(device => device.kind === 'videoinput');
const microphones = devices.filter(device => device.kind === 'audioinput');

用户授权前,浏览器可能隐藏设备名称。

4. 切换摄像头

js 复制代码
async function switchCamera(deviceId) {
  return navigator.mediaDevices.getUserMedia({
    audio: true,
    video: { deviceId: { exact: deviceId } }
  });
}

切换后需要替换本地预览和 PeerConnection 中发送的视频轨。

六、屏幕共享:getDisplayMedia

屏幕共享使用 getDisplayMedia

js 复制代码
async function startScreenShare() {
  const stream = await navigator.mediaDevices.getDisplayMedia({
    video: true,
    audio: true
  });

  document.querySelector('#screenVideo').srcObject = stream;
}

常见用途:

  • 在线会议共享桌面。
  • 在线教育共享课件。
  • 远程协助查看用户屏幕。
  • 产品演示和直播推流。

监听用户停止共享:

js 复制代码
const [track] = stream.getVideoTracks();
track.addEventListener('ended', () => {
  console.log('用户停止了屏幕共享');
});
flowchart TD A[用户点击共享屏幕] --> B[调用 getDisplayMedia] B --> C[浏览器弹出选择窗口] C --> D[用户选择屏幕或标签页] D --> E[返回屏幕 MediaStream] E --> F[本地预览] E --> G[发送给远端]

七、RTCPeerConnection 是什么

RTCPeerConnection 是 WebRTC 的核心对象,负责:

  • 管理媒体轨道。
  • 生成 SDP offer 和 answer。
  • 收集 ICE candidate。
  • 建立 P2P 或中继连接。
  • 发送和接收音视频流。
  • 统计连接质量。
  • 管理 DataChannel。

创建连接:

js 复制代码
const peerConnection = new RTCPeerConnection({
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    {
      urls: 'turn:turn.example.com:3478',
      username: 'user',
      credential: 'password'
    }
  ]
});

iceServers 用于配置 STUN 和 TURN 服务器,帮助双方找到可用连接路径。

八、WebRTC 建连核心流程

WebRTC 建连可以理解为:采集媒体、创建连接、交换 SDP、交换 ICE、建立媒体通道。

flowchart TD A[用户 A 创建 PeerConnection] --> B[添加本地媒体轨] B --> C[创建 Offer] C --> D[设置本地描述] D --> E[通过信令发送 Offer] E --> F[用户 B 设置远端描述] F --> G[用户 B 创建 Answer] G --> H[用户 B 设置本地描述] H --> I[通过信令发送 Answer] I --> J[用户 A 设置远端描述] J --> K[双方交换 ICE Candidate] K --> L[连接建立并传输媒体]

1. 发起方创建 Offer

js 复制代码
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);

signaling.send({
  type: 'offer',
  sdp: offer
});

2. 接收方处理 Offer 并创建 Answer

js 复制代码
await peerConnection.setRemoteDescription(offer);

const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);

signaling.send({
  type: 'answer',
  sdp: answer
});

3. 发起方处理 Answer

js 复制代码
await peerConnection.setRemoteDescription(answer);

4. 双方交换 ICE Candidate

js 复制代码
peerConnection.onicecandidate = event => {
  if (event.candidate) {
    signaling.send({
      type: 'candidate',
      candidate: event.candidate
    });
  }
};

收到远端 candidate:

js 复制代码
await peerConnection.addIceCandidate(candidate);

九、什么是 SDP

SDP,全称 Session Description Protocol,用来描述媒体会话能力。WebRTC 中的 offer 和 answer 本质上都是 SDP。

SDP 会描述:

  • 支持的音视频编码格式。
  • 媒体方向,例如 sendrecv、sendonly、recvonly。
  • 音频和视频轨信息。
  • 网络传输参数。
  • DTLS 指纹。
  • ICE 用户名片段和密码。
  • 带宽、扩展头、编解码参数等。

示意:

txt 复制代码
v=0
o=- 46117326 2 IN IP4 127.0.0.1
s=-
t=0 0
m=audio 9 UDP/TLS/RTP/SAVPF 111
a=rtpmap:111 opus/48000/2
m=video 9 UDP/TLS/RTP/SAVPF 96
a=rtpmap:96 VP8/90000

前端通常不需要手写 SDP,但需要理解它是双方协商媒体能力的载体。

flowchart TD A[本地媒体能力] --> B[生成 SDP Offer] B --> C[发送给远端] C --> D[远端比较自身能力] D --> E[生成 SDP Answer] E --> F[双方确定编码和传输参数]

十、什么是 ICE、STUN、TURN

现实网络中,两个浏览器通常都在 NAT 或防火墙后面,不能简单地直接连接。ICE、STUN、TURN 就是为了解决连接路径问题。

1. ICE

ICE,全称 Interactive Connectivity Establishment,是一套连接候选路径收集、交换、检测和选择机制。

ICE 会尝试多种候选地址:

  • Host Candidate:本机局域网地址。
  • Server Reflexive Candidate:通过 STUN 发现的公网映射地址。
  • Relay Candidate:通过 TURN 中继服务器转发的地址。

2. STUN

STUN 用于帮助客户端发现自己在公网侧看到的地址和端口。

它不转发媒体,只帮助发现地址。

3. TURN

TURN 是中继服务器。当 P2P 连接无法建立时,音视频流会通过 TURN 转发。

TURN 成本更高,因为它要承载真实媒体流量。

flowchart TD A[开始 ICE 收集] --> B[收集本地 Host Candidate] A --> C[请求 STUN] C --> D[获得公网映射 Candidate] A --> E[请求 TURN] E --> F[获得中继 Candidate] B --> G[通过信令交换 Candidate] D --> G[通过信令交换 Candidate] F --> G[通过信令交换 Candidate] G --> H[连通性检测] H --> I[选择最佳路径]

十一、媒体轨道与流

WebRTC 中常见两个概念:

  • MediaStream:媒体流容器,可以包含多个轨道。
  • MediaStreamTrack:具体的一条音频轨或视频轨。
js 复制代码
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
const audioTracks = stream.getAudioTracks();
const videoTracks = stream.getVideoTracks();

把本地轨道添加到连接:

js 复制代码
stream.getTracks().forEach(track => {
  peerConnection.addTrack(track, stream);
});

接收远端媒体:

js 复制代码
peerConnection.ontrack = event => {
  const [remoteStream] = event.streams;
  remoteVideo.srcObject = remoteStream;
};
flowchart TD A[MediaStream] --> B[Audio Track] A --> C[Video Track] B --> D[addTrack 发送] C --> D[addTrack 发送] D --> E[RTCPeerConnection] E --> F[远端 ontrack 接收]

十二、静音、关闭摄像头和停止采集

1. 静音

js 复制代码
const [audioTrack] = localStream.getAudioTracks();
audioTrack.enabled = false;

enabled = false 表示仍保留轨道,但发送静音数据。

2. 关闭摄像头

js 复制代码
const [videoTrack] = localStream.getVideoTracks();
videoTrack.enabled = false;

远端通常会看到黑屏或冻结画面,具体取决于浏览器和播放处理。

3. 停止采集

js 复制代码
localStream.getTracks().forEach(track => track.stop());

stop() 会真正停止设备采集。如果之后要恢复,需要重新调用 getUserMedia

十三、替换媒体轨道

视频通话中经常需要切换摄像头、切换屏幕共享、恢复摄像头。推荐使用 RTCRtpSender.replaceTrack()

js 复制代码
async function replaceVideoTrack(peerConnection, newTrack) {
  const sender = peerConnection
    .getSenders()
    .find(item => item.track && item.track.kind === 'video');

  if (sender) {
    await sender.replaceTrack(newTrack);
  }
}

使用 replaceTrack 通常不需要重新协商,体验更平滑。

flowchart TD A[用户切换摄像头或屏幕] --> B[获取新的 Video Track] B --> C[找到 video sender] C --> D[调用 replaceTrack] D --> E[远端继续接收同一路媒体]

十四、RTCDataChannel

除了音视频,WebRTC 还支持点对点数据通道 RTCDataChannel。它可以传输文本、二进制、文件分片、游戏状态、白板操作等数据。

创建 DataChannel:

js 复制代码
const channel = peerConnection.createDataChannel('chat');

channel.onopen = () => {
  channel.send('hello');
};

channel.onmessage = event => {
  console.log('收到消息', event.data);
};

接收远端 DataChannel:

js 复制代码
peerConnection.ondatachannel = event => {
  const channel = event.channel;
  channel.onmessage = messageEvent => {
    console.log(messageEvent.data);
  };
};

DataChannel 适合:

  • P2P 聊天。
  • 文件传输。
  • 游戏状态同步。
  • 实时白板操作。
  • 协同编辑操作广播。
  • 远程控制指令。
flowchart TD A[创建 RTCDataChannel] --> B[等待连接打开] B --> C[发送文本或二进制] C --> D[远端接收消息] D --> E[处理聊天 文件 白板 指令]

十五、信令服务器的作用

WebRTC 浏览器之间要通信,首先需要交换协商信息。但两个浏览器在连接建立前无法直接通信,所以需要信令服务器。

信令服务器负责交换:

  • 房间加入和离开消息。
  • 用户在线状态。
  • SDP offer。
  • SDP answer。
  • ICE candidate。
  • 通话控制消息,例如邀请、拒绝、挂断。
  • 业务消息,例如角色、权限、会议状态。

信令服务器不一定传输音视频流。大多数一对一 WebRTC 场景中,音视频流建立后可以走 P2P 或 TURN。

flowchart TD A[用户 A] --> B[发送 Offer 到信令服务器] B --> C[转发 Offer 给用户 B] C --> D[用户 B 生成 Answer] D --> B[发送 Answer 到信令服务器] B --> E[转发 Answer 给用户 A] A --> F[发送 ICE Candidate] F --> B[信令转发] B --> G[用户 B 添加 Candidate]

十六、一对一通话完整示例

下面是一个简化的一对一流程,省略了信令实现细节。

js 复制代码
const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});

const localStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true
});

localVideo.srcObject = localStream;

localStream.getTracks().forEach(track => {
  pc.addTrack(track, localStream);
});

pc.ontrack = event => {
  remoteVideo.srcObject = event.streams[0];
};

pc.onicecandidate = event => {
  if (event.candidate) {
    signaling.send({ type: 'candidate', candidate: event.candidate });
  }
};

发起方:

js 复制代码
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
signaling.send({ type: 'offer', sdp: offer });

接收方:

js 复制代码
await pc.setRemoteDescription(remoteOffer);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
signaling.send({ type: 'answer', sdp: answer });

发起方收到 answer:

js 复制代码
await pc.setRemoteDescription(remoteAnswer);

双方收到 candidate:

js 复制代码
await pc.addIceCandidate(remoteCandidate);

十七、多人通话架构

一对一通话可以 P2P,但多人会议要复杂得多。常见架构有 Mesh、SFU、MCU。

1. Mesh 架构

每个用户都和其他所有用户建立 P2P 连接。

优点:实现相对简单,不需要媒体服务器转发。

缺点:人数增加后连接数和上行带宽爆炸。

flowchart TD A[用户 A] --> B[用户 B] A --> C[用户 C] A --> D[用户 D] B --> C[用户 C] B --> D[用户 D] C --> D[用户 D]

2. SFU 架构

SFU,全称 Selective Forwarding Unit。每个用户把媒体流上传到 SFU,SFU 选择性转发给其他用户。

优点:适合多人会议,延迟较低,客户端压力可控。

缺点:需要部署媒体服务器。

flowchart TD A[用户 A] --> E[SFU 媒体服务器] B[用户 B] --> E[SFU 媒体服务器] C[用户 C] --> E[SFU 媒体服务器] D[用户 D] --> E[SFU 媒体服务器] E --> A[转发媒体] E --> B[转发媒体] E --> C[转发媒体] E --> D[转发媒体]

3. MCU 架构

MCU,全称 Multipoint Control Unit。服务器接收所有媒体流,进行混流、转码,再输出合成后的流。

优点:客户端压力小,兼容传统会议系统。

缺点:服务器成本高,延迟更高,扩展压力大。

flowchart TD A[用户 A] --> E[MCU 混流服务器] B[用户 B] --> E[MCU 混流服务器] C[用户 C] --> E[MCU 混流服务器] E --> F[合成单路音视频] F --> A[下发混流] F --> B[下发混流] F --> C[下发混流]

十八、WebRTC 与直播、连麦

WebRTC 适合低延迟互动直播和连麦,但传统大规模直播通常使用 HLS、FLV、DASH、RTMP 等链路。

常见组合:

  • 主播到服务器使用 WebRTC 推流。
  • 连麦用户使用 WebRTC 互动。
  • 观众大规模观看使用 HLS、FLV 或低延迟 HLS。
  • 服务器把 WebRTC 流转封装为直播流。
flowchart TD A[主播浏览器] --> B[WebRTC 推流] B --> C[媒体服务器] D[连麦用户] --> C[媒体服务器] C --> E[低延迟互动流] C --> F[转码转封装] F --> G[CDN 分发] G --> H[普通观众播放]

如果追求超低延迟互动,WebRTC 更合适。如果追求百万级分发,CDN 直播协议更成熟。

十九、WebRTC 质量控制

实时音视频不是只要连上就行,还要关注质量。

常见指标:

  • RTT:往返延迟。
  • Jitter:抖动。
  • Packet Loss:丢包率。
  • Bitrate:码率。
  • Frame Rate:帧率。
  • Resolution:分辨率。
  • Freeze Count:卡顿次数。
  • Audio Level:音量。
  • CPU 使用率。

获取统计信息:

js 复制代码
const stats = await peerConnection.getStats();
stats.forEach(report => {
  if (report.type === 'outbound-rtp' && report.kind === 'video') {
    console.log(report.bytesSent, report.framesEncoded);
  }
});

根据质量动态调整:

  • 网络差时降低分辨率。
  • 网络差时降低码率。
  • 丢包严重时关闭视频保音频。
  • 弱设备降低帧率。
  • 大房间中只订阅活跃说话人视频。
flowchart TD A[采集 getStats 指标] --> B[分析 RTT 丢包 码率 帧率] B --> C[网络良好] B --> D[网络较差] C --> E[保持或提升清晰度] D --> F[降低码率和分辨率] F --> G[必要时关闭视频保留音频]

二十、常见错误和状态

RTCPeerConnection 有多个状态可以监听。

js 复制代码
pc.onconnectionstatechange = () => {
  console.log('connectionState', pc.connectionState);
};

pc.oniceconnectionstatechange = () => {
  console.log('iceConnectionState', pc.iceConnectionState);
};

pc.onsignalingstatechange = () => {
  console.log('signalingState', pc.signalingState);
};

常见状态含义:

状态 说明
new 刚创建,还未连接
connecting 正在建立连接
connected 已连接
disconnected 连接暂时断开,可能恢复
failed 连接失败,需要重连或重建
closed 连接已关闭

常见问题:

  • 用户拒绝摄像头权限。
  • 设备被其他应用占用。
  • HTTPS 环境不满足。
  • STUN 或 TURN 配置错误。
  • 信令消息顺序错误。
  • Candidate 在 remoteDescription 设置前被添加。
  • NAT 严格导致必须走 TURN。
  • 移动端切后台导致连接中断。

二十一、重连与异常恢复

WebRTC 通话中断时,不能只依赖浏览器自动恢复。业务层通常需要设计重连机制。

基本策略:

  1. 监听连接状态。
  2. 短暂 disconnected 可以等待自动恢复。
  3. failed 后尝试 ICE restart。
  4. ICE restart 失败后重建 PeerConnection。
  5. 信令断开后重连 WebSocket。
  6. 重连期间保持 UI 状态提示。

ICE restart 示例:

js 复制代码
const offer = await pc.createOffer({ iceRestart: true });
await pc.setLocalDescription(offer);
signaling.send({ type: 'offer', sdp: offer });
flowchart TD A[连接状态异常] --> B[判断 disconnected] B --> C[等待短时间恢复] C --> D[恢复成功] C --> E[未恢复] E --> F[执行 ICE restart] F --> G[重新交换 Offer Answer] G --> H[恢复媒体连接] F --> I[失败则重建 PeerConnection]

二十二、安全与隐私

WebRTC 直接涉及摄像头、麦克风、屏幕和网络地址,安全与隐私非常重要。

1. 必须用户授权

摄像头、麦克风、屏幕共享必须经过用户授权,页面不能静默开启。

2. 推荐 HTTPS

getUserMedia 通常要求安全上下文,线上环境必须使用 HTTPS。

3. 防止误共享屏幕

屏幕共享 UI 要明确提示当前正在共享,并提供停止入口。

4. TURN 凭证要临时化

TURN 服务器成本高,凭证泄露可能被滥用。建议使用短期动态凭证。

5. 不要泄露敏感信令

SDP 和 ICE 信息不应随意写入公开日志,尤其要注意内网地址、设备信息、用户标识。

6. 权限和房间校验放在服务端

进入房间、发起通话、发布媒体、订阅媒体等权限不能只靠前端控制。

二十三、前端工程实践

1. 封装连接管理类

复杂项目不建议把 WebRTC 逻辑散落在组件中。可以封装为连接管理模块:

  • 创建和销毁 PeerConnection。
  • 管理本地流。
  • 管理远端流。
  • 处理信令消息。
  • 管理连接状态。
  • 处理重连和错误。
  • 暴露事件给 UI 层。

2. 明确信令协议

建议定义清晰的信令消息类型:

ts 复制代码
type SignalingMessage =
  | { type: 'join'; roomId: string; userId: string }
  | { type: 'offer'; from: string; to: string; sdp: RTCSessionDescriptionInit }
  | { type: 'answer'; from: string; to: string; sdp: RTCSessionDescriptionInit }
  | { type: 'candidate'; from: string; to: string; candidate: RTCIceCandidateInit }
  | { type: 'leave'; roomId: string; userId: string };

3. 处理 Candidate 缓存

有时 candidate 先于 remoteDescription 到达,直接添加会报错。可以先缓存,等设置远端描述后再批量添加。

js 复制代码
const pendingCandidates = [];

async function handleCandidate(candidate) {
  if (pc.remoteDescription) {
    await pc.addIceCandidate(candidate);
  } else {
    pendingCandidates.push(candidate);
  }
}

async function flushCandidates() {
  while (pendingCandidates.length > 0) {
    await pc.addIceCandidate(pendingCandidates.shift());
  }
}

4. 页面生命周期处理

需要处理:

  • 页面刷新。
  • 组件卸载。
  • 用户离开房间。
  • 浏览器切后台。
  • 移动端锁屏。
  • 网络从 Wi-Fi 切到蜂窝。

离开时应关闭连接和采集:

js 复制代码
function cleanup() {
  localStream?.getTracks().forEach(track => track.stop());
  pc?.getSenders().forEach(sender => sender.track?.stop());
  pc?.close();
}

二十四、WebRTC 应用场景详解

1. 在线会议

核心能力:多人音视频、屏幕共享、静音、摄像头开关、成员列表、活跃说话人、网络质量提示、录制。

推荐架构:多人会议通常使用 SFU。

2. 在线教育

核心能力:老师推流、学生连麦、课件共享、白板互动、举手、录制回放。

常见组合:WebRTC 负责低延迟互动,普通直播协议负责大规模旁路观看。

3. 远程面试

核心能力:一对一音视频、屏幕共享、代码编辑器协同、录制、设备检测。

重点关注稳定性、权限提示和异常恢复。

4. 远程协助

核心能力:屏幕共享、鼠标轨迹、键盘指令、文件传输、权限确认。

可结合 DataChannel 传输控制指令。

5. P2P 文件传输

核心能力:DataChannel、文件切片、进度展示、断点续传、哈希校验。

适合小规模点对点文件发送,不适合完全替代大文件分发系统。

6. 实时协同白板

核心能力:DataChannel 或信令通道传输绘图操作、WebRTC 音视频同步沟通、服务端持久化白板数据。

flowchart TD A[WebRTC 应用] --> B[音视频会议] A --> C[在线教育] A --> D[远程协助] A --> E[P2P 文件传输] A --> F[实时白板] B --> G[SFU 多人转发] C --> H[连麦和课件共享] D --> I[屏幕共享和控制指令] E --> J[DataChannel 文件分片] F --> K[DataChannel 同步操作]

二十五、WebRTC 与 WebSocket 的区别

WebRTC 和 WebSocket 经常一起出现,但它们不是替代关系。

对比项 WebRTC WebSocket
通信模式 可 P2P,也可经 TURN 或媒体服务器 客户端到服务器
主要用途 实时音视频、P2P 数据 信令、聊天、业务消息
传输内容 音视频、二进制、文本 文本、二进制
延迟 音视频场景低延迟优化 取决于服务器链路
NAT 穿透 内置 ICE 机制 不需要 P2P 穿透
复杂度 较高 较低

典型搭配:WebSocket 做信令,WebRTC 做媒体和 P2P 数据传输。

flowchart TD A[用户 A] --> B[WebSocket 信令服务器] C[用户 B] --> B[WebSocket 信令服务器] B --> D[交换 Offer Answer Candidate] D --> E[建立 WebRTC 连接] A --> E[发送媒体流] C --> E[接收媒体流]

二十六、WebRTC 与 WebTransport、HLS 的区别

1. WebRTC 与 HLS

HLS 适合大规模直播分发,但延迟通常较高。WebRTC 适合低延迟互动,但大规模分发成本更高。

2. WebRTC 与 WebTransport

WebTransport 提供基于 HTTP/3 的低延迟双向传输能力,但它不直接提供摄像头采集、音视频编解码、回声消除、抖动缓冲等实时音视频完整能力。

3. 如何选择

  • 一对一音视频:WebRTC。
  • 多人互动会议:WebRTC 加 SFU。
  • 大规模直播观看:HLS、DASH、FLV 或低延迟直播方案。
  • 低延迟自定义数据传输:可评估 WebTransport。
  • 浏览器 P2P 文件传输:WebRTC DataChannel。

二十七、调试 WebRTC

1. 浏览器内部页面

Chrome 可以使用:

txt 复制代码
chrome://webrtc-internals

可以查看 SDP、ICE 状态、码率、丢包、延迟、轨道信息等。

2. 控制台日志

建议记录:

  • 信令消息收发。
  • signalingState
  • iceConnectionState
  • connectionState
  • iceGatheringState
  • 本地和远端 SDP。
  • Candidate 类型。
  • getStats 关键指标。

3. 排查流程

flowchart TD A[WebRTC 连接失败] --> B[检查媒体权限] B --> C[检查信令是否通] C --> D[检查 Offer Answer 是否设置成功] D --> E[检查 ICE Candidate 是否交换] E --> F[检查 STUN TURN 是否可用] F --> G[查看 webrtc internals] G --> H[分析连接状态和统计指标]

二十八、常见面试题

1. WebRTC 是否不需要服务器

不是。WebRTC 的媒体流在理想情况下可以 P2P,但仍然需要信令服务器交换协商信息;复杂网络下还需要 TURN 服务器;多人会议通常还需要 SFU 或 MCU。

2. STUN 和 TURN 有什么区别

STUN 只帮助发现公网映射地址,不转发媒体。TURN 在无法 P2P 时负责中继媒体流,成本更高。

3. Offer 和 Answer 是什么

Offer 和 Answer 是双方基于 SDP 的媒体能力协商。Offer 表示发起方的能力和意图,Answer 表示接收方接受后的协商结果。

4. 为什么有时本地测试能通,线上用户不通

本地网络可能 NAT 简单,线上用户可能处于公司防火墙、对称 NAT、弱网或运营商复杂网络下。缺少可用 TURN 是常见原因。

5. WebRTC 能不能做万人直播

单纯浏览器 P2P 不适合万人直播。大规模直播通常需要媒体服务器、转码、CDN 分发。WebRTC 可以用于主播推流和低延迟连麦。

6. DataChannel 和 WebSocket 怎么选

如果需要客户端和服务器稳定通信,选 WebSocket。如果需要浏览器之间 P2P 传输数据,选 WebRTC DataChannel。实际 WebRTC 项目中常用 WebSocket 做信令,DataChannel 做点对点业务数据。

二十九、最佳实践清单

1. 媒体采集

  • 采集前做设备检测。
  • 用户授权失败要给出明确提示。
  • 移动端注意前后摄像头切换。
  • 停止通话时释放摄像头和麦克风。

2. 信令设计

  • 消息类型清晰。
  • 带上房间 ID、用户 ID、目标用户 ID。
  • 处理乱序、重复和延迟消息。
  • Candidate 到达过早时先缓存。

3. 网络穿透

  • 线上必须配置可靠 TURN。
  • TURN 凭证使用短期动态凭证。
  • 监控 TURN 使用比例和流量成本。

4. 连接稳定性

  • 监听连接状态。
  • 支持 ICE restart。
  • 支持重建 PeerConnection。
  • 信令断开要自动重连。
  • UI 上提示重连状态。

5. 音视频质量

  • 使用 getStats 采集质量指标。
  • 网络差时动态降级。
  • 多人会议使用 SFU。
  • 大房间避免订阅所有高清视频。

6. 安全隐私

  • 全站 HTTPS。
  • 房间权限放在服务端校验。
  • 屏幕共享提供明显状态提示。
  • 不在公开日志中记录敏感 SDP 和 ICE 信息。

三十、总结

WebRTC 是现代前端实时通信的重要基础能力。它让浏览器可以直接完成音视频采集、实时传输、P2P 数据通信和屏幕共享。

理解 WebRTC 可以抓住五条主线:

  1. 媒体采集:getUserMediagetDisplayMedia
  2. 协商建连:RTCPeerConnection、Offer、Answer、SDP。
  3. 网络穿透:ICE、STUN、TURN、Candidate。
  4. 媒体传输:Track、Stream、RTP、SRTP。
  5. 工程应用:信令、重连、质量监控、多人架构、安全隐私。
flowchart TD A[学习 WebRTC] --> B[掌握媒体采集] B --> C[理解 SDP 协商] C --> D[理解 ICE 穿透] D --> E[掌握媒体轨和 DataChannel] E --> F[理解信令和多人架构] F --> G[落地会议 直播 连麦 文件传输]

如果只做一对一通话,核心是 PeerConnection 加信令交换。如果做多人会议,重点会转向 SFU、订阅策略和质量控制。如果做直播连麦,重点是 WebRTC 与媒体服务器、CDN、转码链路的协作。

WebRTC 的复杂点不在 API 数量,而在网络环境、媒体质量、状态同步和异常恢复。真正稳定的 WebRTC 应用,需要把前端 API、信令服务、媒体服务器、网络穿透和监控体系一起设计。

相关推荐
angerdream16 分钟前
Android手把手编写儿童手机远程监控App之agentweb如何实现全屏
前端
星栈25 分钟前
10 分钟跑起第一个 Dioxus 应用:`dx` CLI、`rsx!` 和热更新好不好用
前端·rust·前端框架
奋斗吧程序媛38 分钟前
补充一个小知识点:有关@click.native
前端·vue.js
触底反弹1 小时前
🚀 手把手用 HTML5 Canvas 从零打造飞机大战游戏,代码全开源!
前端·javascript·canvas
DJ斯特拉1 小时前
axios快速使用
开发语言·前端·javascript
还有多久拿退休金1 小时前
Ant Design Tree 搜索定位避坑指南:虚拟滚动下如何实现高亮与精准定位
前端·react.js
小月土星1 小时前
CSS 3D 从入门到炫技:手把手教你写一个旋转立方体
前端·css
Hilaku1 小时前
AI 写代码越快,为什么 Code Review 越不能省?
前端·javascript·程序员
sugar__salt2 小时前
从网页小游戏到数据可视化:掌握 HTML5 Canvas 核心能力
前端·信息可视化·html5
北极星日淘2 小时前
前端 i18n 中日双语交互 + 翻译客服接口联动方案|日系海淘平台中文友好化开发实战
前端·交互