WebRTC:浏览器为什么能点对点音视频通话?ICE、STUN、TURN、SDP 分别是什么?
面试速答(30 秒版 TL;DR)
- WebRTC 是浏览器端实时通信方案,核心能力是:音视频采集、点对点传输、数据通道。
- 真正负责连接的是
RTCPeerConnection;真正负责采集的是getUserMedia;真正负责网络穿透的是 ICE + STUN + TURN;真正负责协商媒体参数的是 SDP offer/answer。 - 面试最核心的链路是:采集媒体 -> 建立 PeerConnection -> 交换 offer/answer -> 交换 ICE candidate -> 建链 -> 传输音视频/数据。
- WebRTC 不是“完全不需要服务器”,至少还需要 信令服务器 来交换协商信息。
心智模型:媒体传输是 P2P,但建链离不开信令
很多人对 WebRTC 的第一误解是:
- “既然点对点,那就不需要服务端”
实际上服务端至少常承担两件事:
- 信令(signaling):交换 offer、answer、ICE candidate
- TURN 中继:P2P 打不通时兜底转发
所以更准确的说法是:
- WebRTC 的媒体链路尽量 P2P
- 但建链过程和兜底链路通常离不开服务器
一、最核心的几个对象
| API | 作用 |
|---|---|
navigator.mediaDevices.getUserMedia() | 获取摄像头/麦克风媒体流 |
RTCPeerConnection | 建立点对点连接 |
RTCDataChannel | 建立数据通道 |
MediaStream / MediaStreamTrack | 承载音视频轨道 |
二、最小链路:先拿本地媒体
const localStream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
});
videoEl.srcObject = localStream;
这一步只解决:
- 设备权限
- 音视频采集
还没开始和对端通信。
三、RTCPeerConnection 做了什么
const pc = new RTCPeerConnection({
iceServers: [
{ urls: "stun:stun.l.google.com:19302" },
],
});
它负责:
- 媒体协商
- 网络候选收集
- 建立安全传输通道
- 发送/接收音视频与数据
把本地轨道加进去:
for (const track of localStream.getTracks()) {
pc.addTrack(track, localStream);
}
四、Offer / Answer 是什么
这是 WebRTC 高频核心题。
主叫方
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 通过信令服务器把 offer 发给对端
被叫方
await pc.setRemoteDescription(offer);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
// 通过信令服务器把 answer 回给主叫方
主叫方收到 answer
await pc.setRemoteDescription(answer);
面试口径:
offer/answer是协商双方能力和传输参数的描述文本- 这份描述通常使用 SDP 格式
五、SDP 是什么
SDP(Session Description Protocol)里通常描述:
- 支持的音视频编码
- 媒体轨道方向
- 网络相关参数
- 连接所需信息
你不需要背 SDP 文本格式,但要说清:
- SDP 负责“谈判媒体会话长什么样”
- 它不是“最终媒体数据本身”
六、ICE、STUN、TURN 各解决什么问题
ICE
- 候选地址收集与连接尝试机制
- 会尝试各种可能路径,看哪条能打通
STUN
- 帮你知道“我在公网看来是谁”
- 常用于 NAT 场景下发现自己的公网映射地址
TURN
- 当双方直连打不通时,走中继服务器转发
一句话背诵:
- STUN 用来找地址,TURN 用来做中继,ICE 用来组织候选和试连。
七、ICE candidate 怎么交换
本地收集候选:
pc.onicecandidate = (event) => {
if (event.candidate) {
signaling.send({ type: "candidate", candidate: event.candidate });
}
};
收到远端候选:
await pc.addIceCandidate(remoteCandidate);
这一步为什么必要:
- 对端得知道有哪些网络路径可以试
- 双方不断补充 candidate,直到连上或宣告失败
八、远端媒体怎么接收
pc.ontrack = (event) => {
remoteVideo.srcObject = event.streams[0];
};
也就是说:
- 对方把轨道加进连接
- 你这边通过
ontrack收到远端媒体流
九、数据通道 RTCDataChannel
WebRTC 不只能传音视频,也能传业务数据。
const channel = pc.createDataChannel("chat");
channel.onmessage = (e) => {
console.log(e.data);
};
channel.send("hello");
适合:
- 实时聊天
- 白板坐标同步
- 小文件/控制消息
十、为什么 WebRTC 适合低延迟实时场景
因为它的设计目标就是:
- 低延迟
- 实时互动
- 浏览器原生支持媒体与网络协商
但也要知道边界:
- 并不是所有网络环境都能稳定直连
- 大规模多人房间往往会引入 SFU/MCU 架构,而不是纯网状 P2P
十一、多人通话为什么常用 SFU
如果 10 个人全做 Mesh 网状互连:
- 每个人都要同时发给 9 个人
- 上行带宽和浏览器负担都很重
所以工程上常用:
- SFU(Selective Forwarding Unit):服务端转发媒体流,但不做重编码
面试答到这里通常已经足够加分。
典型题 & 标准答法
Q1:WebRTC 建链流程怎么说?
标准答法:
getUserMedia获取本地媒体- 创建
RTCPeerConnection addTrack- 创建 offer / answer 并通过信令服务器交换
- 交换 ICE candidate
- 建立连接并通过
ontrack接收远端流
Q2:STUN 和 TURN 有什么区别?
- STUN:帮助发现公网映射地址
- TURN:直连失败时做中继
Q3:为什么说 WebRTC 不是完全“去服务器化”?
因为至少还需要信令服务器,而复杂网络环境下通常还需要 TURN,很多多人通话还会用 SFU。
易错点/坑
- 以为 WebRTC 不需要服务端。
- 把 SDP 当成媒体数据本身。
- 忽略 NAT 穿透和 TURN 成本。
- 认为多人通话直接 Mesh 就能扩展到大规模。
速记要点(可背诵)
- 采集:
getUserMedia - 建链:
RTCPeerConnection - 协商:SDP offer/answer
- 穿透:ICE + STUN + TURN
- 多人场景常上 SFU