WebRTC 架构概览:P2P连接、信令、媒体流、数据通道

WebRTC 这玩意儿,说白了就是让浏览器之间能直接“对话”。不用经过服务器中转,视频、音频、文件,点对点就传过去了。听起来很酷,对吧?但实现起来,坑不少。

我刚开始接触 WebRTC 时,以为就是打开摄像头、塞进一个管道、另一端接收就完事了。结果呢?光是建立连接这一步,就折腾了我好几天。信令怎么设计?NAT 穿透怎么搞?媒体流怎么同步?数据通道丢包了怎么办?

嗯,这一章我们就来拆解一下 WebRTC 的整体架构。你搞懂了这些,后面调试流控、对抗抖动,才有根基。

2.1 核心架构:四个模块

WebRTC 的架构可以分成四个核心模块。我习惯把它们比作“四兄弟”:

  • 信令(Signaling) —— 负责“牵线搭桥”,交换连接信息。
  • P2P 连接(PeerConnection) —— 真正的数据传输通道。
  • 媒体流(MediaStream) —— 摄像头、麦克风采集的音视频。
  • 数据通道(DataChannel) —— 传输任意二进制数据。

这四兄弟缺一不可。信令是“媒人”,P2P 是“婚车”,媒体流是“新娘”,数据通道是“嫁妆”。你想想看,没有媒人,两个人怎么认识?没有婚车,新娘怎么到现场?

核心要点: 信令不是 WebRTC 协议的一部分,但它是建立连接的前提。你必须自己实现信令服务器。

2.2 信令:连接的“媒人”

信令的作用很简单:让两个浏览器知道对方的存在,并交换建立连接所需的信息。这些信息包括:

  • SDP(Session Description Protocol) —— 描述媒体格式、编解码器、IP 地址、端口等。
  • ICE Candidate(Interactive Connectivity Establishment) —— 候选的网络路径。

信令的流程大致是这样的:

  1. 发起方创建 Offer(SDP),通过信令服务器发送给接收方。
  2. 接收方收到 Offer,创建 Answer(SDP),再通过信令服务器发回去。
  3. 双方交换 ICE Candidate,尝试建立 P2P 连接。

我曾经在一个项目中,信令服务器用的是 WebSocket。一开始觉得挺简单,结果发现 SDP 里携带的 IP 地址是内网的,根本连不上。后来才意识到,需要配合 STUN/TURN 服务器做 NAT 穿透。

个人建议: 信令协议的设计要尽量轻量。别搞太复杂的 JSON 结构,否则解析起来费劲,还容易出错。我一般就用三个字段:type(offer/answer/candidate)、sdp、candidate。

2.3 P2P 连接:真正的“高速公路”

信令交换完成后,WebRTC 就开始尝试建立 P2P 连接。这个过程叫 ICE(Interactive Connectivity Establishment)。

ICE 会尝试多种路径:

  • Host Candidate —— 本机 IP 地址,最快但只能在局域网内使用。
  • Srflx Candidate —— 通过 STUN 服务器获取的公网 IP 地址。
  • Relay Candidate —— 通过 TURN 服务器中转,最慢但最可靠。

ICE 会按照优先级排序,优先尝试 Host,不行再试 Srflx,最后才用 Relay。我遇到过不少情况,明明双方都在同一个局域网,ICE 却走了 Relay,延迟高得离谱。后来排查发现,是 STUN 服务器配置错了。

避坑指南: 我曾经在生产环境中忘记配置 TURN 服务器,结果用户在有对称 NAT 的网络环境下,死活连不上。那一次事故让我记住了:TURN 服务器不是可选项,是必选项。

下面这张图展示了 P2P 连接的建立过程:

WebRTC P2P 连接建立流程 WebRTC P2P 连接建立流程 发起方 (Offerer) 信令服务器 接收方 (Answerer) Offer (SDP) 转发 Offer Answer (SDP) 转发 Answer ICE 候选 ICE 候选 ICE 候选交换 P2P 连接建立成功 说明: ICE 会尝试 Host → Srflx → Relay 三种候选路径,优先选择延迟最低的路径。

2.4 媒体流:音视频的“血液”

P2P 连接建立后,媒体流就开始传输了。媒体流包括视频轨道(VideoTrack)和音频轨道(AudioTrack)。

WebRTC 使用 getUserMedia() 获取本地媒体流,然后通过 addTrack() 添加到 PeerConnection 中。接收方通过 ontrack 事件获取远程媒体流。

这里有个关键点:媒体流的编码和解码。WebRTC 默认使用 VP8/VP9 视频编码和 Opus 音频编码。但不同的浏览器支持的编码器不一样。我遇到过 Chrome 和 Safari 之间视频通话,Safari 不支持 VP9,结果 Chrome 只能降级到 VP8,画质差了不少。

个人经验: 在建立连接前,最好先协商一下双方都支持的编解码器。可以通过 SDP 的 rtpmap 字段来查看。我一般会优先使用 H.264,因为硬件编码支持更好,延迟更低。

2.5 数据通道:传输“任意数据”

数据通道(DataChannel)是 WebRTC 里一个容易被忽视但非常强大的功能。它可以在 P2P 连接上传输任意二进制数据,比如文件、游戏状态、聊天消息等。

数据通道有两种模式:

模式 特点 适用场景
可靠模式 基于 SCTP 协议,保证数据有序、不丢失 文件传输、聊天消息
不可靠模式 基于 SCTP 协议,允许丢包和乱序 实时游戏状态、音视频同步

我曾在做一个在线协作白板项目时,用数据通道传输画笔轨迹。一开始用的可靠模式,结果网络一抖,白板就卡住了。后来改成不可靠模式,丢几个点无所谓,用户体验反而更流畅。

避坑指南: 数据通道的 maxRetransmits 和 maxPacketLifeTime 参数不能同时设置。我曾经踩过这个坑,两个都设了,结果数据通道创建失败。记住:要么设置重传次数,要么设置生存时间,二选一。

2.6 架构总结:一张图看懂

好了,我们把整个 WebRTC 架构串起来。下面这张图展示了各模块之间的关系:

WebRTC 整体架构 WebRTC 整体架构 应用层 (Web App) WebRTC API (getUserMedia, PeerConnection, DataChannel) WebRTC 核心引擎 (VoiceEngine, VideoEngine, Transport) 网络层 (ICE, STUN, TURN, DTLS, SRTP) 核心要点: 信令层不属于 WebRTC 标准,但它是建立连接的前提。实际项目中,信令服务器通常使用 WebSocket 或 HTTP 实现。

你看,从应用层到网络层,每一层都有明确的职责。信令负责“牵线”,P2P 负责“修路”,媒体流和数据通道负责“跑车”。搞懂了这些,你就能理解为什么网络抖动会影响视频质量,为什么 ICE 连接会失败,为什么数据通道会丢包。