Skip to content

WebRTC(Web Real-Time Communication)是浏览器内置的实时音视频通信标准,核心特点是: 媒体数据尽量不经过服务器,两端直连(P2P) ,服务器只负责“牵线搭桥”。下面用两张图 + 文字把它讲清楚。

先看一次通话连接是如何建立起来的。 WebRtc通话连接时序图

上图的四个阶段拆开讲:

1. 信令协商(SDP Offer/Answer) ​

WebRTC 标准刻意 不定义信令怎么传 ——它只规定两端要交换什么内容(SDP),传输方式由业务自己实现。在 boxim 里就是 im-platform 的POST /webrtc/private/call (发 Offer)和accept (回 Answer),底层再经 im-server 的 WebSocket 推给对端。SDP 里描述的是“我支持哪些编解码、什么分辨率、媒体走哪个端口”。

2. ICE 穿透(核心技术难点) ​

两台设备通常都躲在 NAT/防火墙后面,没有公网 IP,怎么直连?这就是 ICE 框架要解决的:

  • STUN :“你是谁”服务器。浏览器向它发一个包,它回一句“我看到你来自 1.2.3.4:56789”,这就是该 NAT 映射出的公网地址,成为一个 ICE candidate(候选地址)。本机局域网 IP 也是一个候选。
  • 双方把各自的候选通过信令服务器互换 (Trickle ICE,边发现边发)。
  • 连通性检查 :双方用收集到的候选互相发 STUN 探测包尝试打洞。能通就选定这条路。
  • TURN (兜底):遇到对称型 NAT 等打洞必败的场景,双方都连到 TURN 服务器,由它中继转发流量——这就是配置里turn:www.boxim.online:3478 的作用, 牺牲 P2P 换连通性 。

3. 安全与媒体传输 ​

  • 连接建立时双方先做 DTLS 握手,协商出加密密钥;
  • 音视频用 SRTP 加密传输;数据消息走 SCTP (DataChannel);
  • 即使经 TURN 中继,TURN 服务器也 看不到内容 ,只是搬运密文。

前端 API 一览 ​

javascript
const pc = new RTCPeerConnection({ iceServers });   // iceServers 来自 /system/config
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach(t => pc.addTrack(t, stream));
pc.onicecandidate = e => ws.send(JSON.stringify(e.candidate)); // 候选发给信令
pc.ontrack = e => videoEl.srcObject = e.streams[0];            // 收到对方画面

多人通话时这套直连模型会遇到带宽爆炸的问题,这也正是配置里max-channel: 9 存在的原因。 多人通话的三种架构

三种架构的取舍 ​

  • Mesh(本项目) :每人与其他所有人建直连。n 人时全网有 n×(n-1)/2 条连接,每人要 编码 n-1 路上行 ——9 人时每端同时编 8 路视频,已经是普通设备和宽带的舒适区边缘;16 人是绝对上限。好处是 服务器零媒体成本 ,只出信令和 coturn。
  • SFU :主流方案。每人只上行 1 路,服务器按需向每人转发,服务器不做编解码,成本集中在带宽。要扩到几十上百人就换它。
  • MCU :服务器把多路解码、合成一路画面再编码下发,端侧最省资源但服务器成本最高,常见于传统硬件会议终端。

与项目配置的对应关系 ​

配置项 承担的角色

配置项承担的角色
stun:www.boxim.online:3478ICE 探测公网地址(打洞用)
turn:www.boxim.online:3478 + credential打洞失败时的中继兜底(coturn 认证)
max-channel: 9Mesh 架构下的人数安全阀
POST /webrtc/private/call 等接口SDP Offer/Answer 与 candidate 的信令通道

一句话总结: WebRTC = 媒体 P2P + 信令自建 + STUN/TURN 穿透 + DTLS/SRTP 加密 。服务器只负责“介绍认识”(信令)和“实在见不着面时帮忙传话”(TURN),音视频数据本身绝大多数情况不经过任何服务器。

Released under the MIT License.