3. WebRTC 架构概览:整体架构、P2P连接建立流程、媒体引擎与编解码器、RTP/RTCP协议基础
各位同学,欢迎来到第三章。这一章我们聊聊WebRTC的整体架构。说白了,就是搞清楚WebRTC到底长什么样,各个模块怎么配合的。
我刚开始接触WebRTC时,也被那一堆模块搞晕过。后来带团队做项目,踩了不少坑,才慢慢理清脉络。今天我把这些经验分享给你。
3.1 WebRTC整体架构
WebRTC不是单一的技术,而是一套协议栈和API的集合。它主要分三层:
- Web API层:暴露给JavaScript开发者的接口,比如
getUserMedia、RTCPeerConnection、RTCDataChannel。 - 核心引擎层:C++实现的底层模块,包括音频引擎、视频引擎、传输模块。
- 网络传输层:处理ICE、STUN、TURN、DTLS、SRTP等协议。
我习惯把WebRTC比作一个三层蛋糕。最上面是给前端吃的,中间是核心逻辑,最下面是网络通信。每一层各司其职,但又紧密耦合。
核心要点:WebRTC的架构设计遵循"最小权限原则"——浏览器只暴露必要的API,底层细节对开发者透明。你不需要关心P2P连接怎么打洞,也不需要手动管理编解码器,框架帮你做了。
下面这张图是我自己整理的WebRTC架构分层图,你看一眼就能明白整体脉络。
3.2 P2P连接建立流程
P2P连接建立,是WebRTC最核心的流程之一。很多新手觉得这一步很玄乎,其实拆开来看就四个步骤。
- 信令交换:通过信令服务器交换SDP(Session Description Protocol)。SDP里包含了媒体信息、网络信息、安全参数。
- ICE候选收集:收集本端所有可能的网络地址(主机地址、STUN反射地址、TURN中继地址)。
- 连通性检查:双方交换ICE候选后,进行连通性检查。谁先通就用谁。
- DTLS握手 + SRTP密钥协商:建立加密通道,后续媒体流走SRTP。
我的经验:我在项目中遇到过一个问题——ICE候选收集超时。后来发现是STUN服务器配置错了。建议你在生产环境至少配置两个STUN服务器,一个挂了还有备用。
这里有个细节很多人忽略:ICE提名(ICE Nomination)。当双方都完成连通性检查后,需要一方发起提名,确认最终使用的候选对。我见过一些实现没处理好提名逻辑,导致连接建立后频繁切换路径,丢包率飙升。
3.3 媒体引擎与编解码器
WebRTC的媒体引擎,说白了就是负责采集、编码、解码、渲染的模块。它内置了多种编解码器,但不同浏览器支持情况不一样。
| 编解码器 | 类型 | 比特率范围 | 浏览器支持 | 丢包恢复能力 |
|---|---|---|---|---|
| Opus | 音频 | 6-510 kbps | Chrome/Firefox/Safari | 内置PLC(丢包隐藏) |
| VP8 | 视频 | 100-2000 kbps | Chrome/Firefox | 参考帧恢复 |
| VP9 | 视频 | 50-1500 kbps | Chrome | SVC分层恢复 |
| H.264 | 视频 | 100-2000 kbps | Chrome/Firefox/Safari | NAL单元FEC |
| AV1 | 视频 | 30-800 kbps | Chrome(实验性) | 参考帧恢复 |
你看这个表,Opus在音频领域几乎是统治级的。它支持可变比特率,还能在丢包时自动隐藏。我做过一个测试,30%丢包率下Opus还能保持基本可懂,换成其他编解码器早就断断续续了。
视频方面,VP8和H.264是主流。VP9和AV1虽然压缩率更高,但解码开销也大。我个人建议:如果兼容性优先,选H.264;如果压缩率优先,选VP9。
注意:编解码器协商是通过SDP中的rtpmap和fmtp字段完成的。我曾经遇到过一个bug——双方都支持H.264,但协商失败。查了半天发现是packetization-mode参数不一致。一方设了1,另一方没设,导致协商失败。
3.4 RTP/RTCP协议基础
RTP(Real-time Transport Protocol)是WebRTC传输媒体数据的核心协议。RTCP(RTP Control Protocol)则是它的控制协议,负责反馈质量信息。
我习惯把RTP比作快递员,RTCP比作客服。快递员只管送包裹,客服告诉你包裹有没有丢、延迟多久、需不需要重发。
RTP头部结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
几个关键字段:
- sequence number:16位序列号,用于检测丢包和排序。每发一个包加1。
- timestamp:32位时间戳,用于播放同步。音频和视频的时间戳时钟频率不同。
- SSRC:同步源标识符,唯一标识一个媒体流。
RTCP主要有几种报文类型:
- SR(Sender Report):发送方报告,包含发送的包数、字节数、NTP时间戳。
- RR(Receiver Report):接收方报告,包含丢包率、累计丢包数、抖动、延迟。
- SDES(Source Description):源描述,包含CNAME等信息。
- BYE:结束会话。
丢包恢复的关键:RTCP的RR报文里包含了丢包率(fraction lost)和累计丢包数(cumulative number of packets lost)。接收方通过这两个值告诉发送方网络质量。发送方据此调整码率、开启FEC或请求重传。这就是WebRTC拥塞控制和丢包恢复的基础。
嗯,这里要注意:RTCP的发送间隔是有规范的。RFC 3550建议RTCP带宽占RTP总带宽的5%。如果RTCP发得太频繁,会占用媒体带宽;发得太少,反馈不及时。WebRTC内部有一套自适应算法,会根据网络状况动态调整RTCP间隔。
我在项目中遇到过一个问题:RTCP RR报文里的丢包率突然飙升到50%,但实际网络并没有那么差。后来发现是接收方的缓冲区溢出导致丢包,而不是网络丢包。这个坑提醒我们:丢包率不等于网络丢包率,也可能是接收端处理不过来。
好了,这一章的内容就到这里。WebRTC的架构、P2P连接流程、编解码器、RTP/RTCP协议,这些都是后续丢包恢复技术的基础。你把这些搞清楚了,后面讲FEC、NACK、SVC时就会轻松很多。