一、WebRTC 初探:它到底是什么?

我第一次接触 WebRTC 是在 2015 年。当时有个客户说:「我想在浏览器里直接视频通话,不要插件。」我心想,这怎么可能?

结果一查,还真有。WebRTC,全称 Web Real-Time Communication,是 Google 牵头搞的一套开源技术。说白了,它让浏览器之间能直接传音频、视频和数据,不需要装任何软件。

你想想看,以前要视频通话,得装 Skype、Zoom 客户端。现在打开网页就行。这就是 WebRTC 的魔力。

核心定义:WebRTC 是一套浏览器原生支持的实时通信 API,包含音视频采集、编码传输、网络穿透等完整能力。

1.1 它能做什么?

我这些年用 WebRTC 做过不少项目。简单列几个典型场景:

  • 视频会议——最经典的应用,Zoom、Google Meet 底层都在用
  • 远程桌面——我在项目中做过一个,延迟控制在 200ms 以内
  • 文件传输——点对点传大文件,不走服务器,又快又省带宽
  • 在线教育——白板共享 + 实时音视频,学生端零安装
  • IoT 监控——摄像头画面直接推送到浏览器

嗯,这里要注意:WebRTC 不是只能做视频通话。它的数据通道(DataChannel)可以传任何二进制数据。我曾经用它做过一个实时协作编辑工具,效果出奇的好。

1.2 通信原理概览

很多人觉得 WebRTC 原理很复杂。其实拆开来看,就三个核心步骤:

  1. 获取媒体流——打开摄像头、麦克风
  2. 建立连接——让两个浏览器互相找到对方
  3. 传输数据——音视频实时编码、发送、解码

第二步最难。为什么?因为大多数设备都在局域网后面,没有公网 IP。两个内网设备怎么直接通信?

WebRTC 用了 ICE(交互式连接建立)框架。它会尝试多种路径:

  • 先试直连(同一局域网下最快)
  • 不行就通过 STUN 服务器获取公网映射
  • 还不行就用 TURN 服务器中转

我踩过一个坑:当时部署时没配 TURN 服务器,结果有些严格防火墙下的用户死活连不上。后来加了 TURN,问题解决。

避坑指南:生产环境一定要部署 TURN 服务器。我曾经以为 STUN 就够了,结果被客户投诉「视频打不开」。加了 TURN 后,连接成功率从 70% 提升到 99%。

1.3 核心架构图

下面这张图是我自己画的,把 WebRTC 的整体流程串起来了:

WebRTC 通信架构图 WebRTC 通信架构图 浏览器 A 采集音视频 编码打包 ICE 候选收集 浏览器 B 解码播放 接收数据 ICE 候选收集 信令服务器 交换 SDP / ICE 候选 SDP 交换 SDP 交换 STUN / TURN 网络穿透 / 中转 候选收集 候选收集 P2P 音视频数据流 说明: 信令服务器只负责建立连接,不传输音视频数据。 连接建立后,数据直接在浏览器之间传输(或经 TURN 中转)。

1.4 关键协议速览

WebRTC 不是单一协议,而是一套协议栈。我整理了一个表格,方便你对照:

协议/组件 作用 我的经验
ICE 交互式连接建立,找到最优通信路径 默认配置通常够用,但复杂网络下要调超时参数
STUN 获取公网 IP 和端口映射 免费 STUN 服务器很多,但生产环境建议自建
TURN 无法直连时做数据中转 带宽成本高,但必须备着。我吃过亏
SDP 描述媒体格式、编码参数、网络信息 格式看起来复杂,但不用手写,API 自动生成
DTLS 加密传输,保证安全性 默认开启,别关。曾经有人为了性能关掉,结果被攻击
SRTP/SCTP 音视频和数据通道的传输协议 SRTP 传音视频,SCTP 传数据,分工明确

重要提醒:WebRTC 强制加密。所有音视频数据都经过 DTLS 握手和 SRTP 加密。这不是可选项,是规范要求。别想着「先不加密跑通再说」——浏览器会直接拒绝。

1.5 一个最简单的例子

说了这么多,不如看段代码。下面这个例子,打开摄像头并把画面显示在页面上:

// 获取摄像头视频流
async function startCamera() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true
    });
    
    // 把流绑定到 video 元素
    const video = document.getElementById('localVideo');
    video.srcObject = stream;
    video.play();
    
    console.log('摄像头已开启');
  } catch (err) {
    console.error('获取摄像头失败:', err);
  }
}

// 调用
startCamera();

这段代码我写过无数次。注意 getUserMedia 需要用户交互触发(比如点击按钮),不能页面加载时自动调用。这是浏览器的安全策略。

嗯,这里有个小技巧:如果用户拒绝授权,catch 里会收到 NotAllowedError。你可以优雅地提示用户手动开启权限,而不是直接报错。

1.6 本章小结

WebRTC 的核心就三件事:采集 → 连接 → 传输。连接建立是最复杂的部分,涉及 ICE/STUN/TURN 这套机制。但好消息是,浏览器把这些都封装好了,你只需要调用 API。

我个人觉得,WebRTC 最大的价值是让实时通信变得「平民化」。以前做视频通话,得懂流媒体协议、编解码、NAT 穿透。现在,一个前端工程师就能搞定。