24、WebRTC与RTMP互通:WebRTC简介、WebRTC与RTMP协议转换、SFU与MCU架构
各位同学,今天我们来聊一个非常实际的话题——WebRTC和RTMP的互通。
说实话,我在做直播SDK之前,一直觉得这两个协议是“井水不犯河水”。RTMP是传统直播的老大哥,WebRTC是实时通信的新贵。但现实项目中,你经常需要让它们俩“握手”。比如,用户用浏览器(WebRTC)推流,但后台的转码集群只认RTMP。怎么办?
嗯,这节课我们就来拆解这个问题。
WebRTC简介:它到底强在哪?
WebRTC,全称Web Real-Time Communication。说白了,就是让浏览器之间能直接传音视频,不需要装任何插件。
我最早接触WebRTC是在2015年,那时候还在做视频通话App。当时最大的痛点就是:用户要装一个SDK才能通话。WebRTC一出来,直接打开网页就能连麦,体验完全不一样。
它的核心能力有三个:
- 音视频采集:通过getUserMedia API拿到摄像头和麦克风数据
- 数据传输:基于UDP的SRTP/SCTP,延迟极低
- NAT穿透:内置ICE/STUN/TURN,解决内网穿透问题
但WebRTC也有个“硬伤”——它不是一个“流媒体协议”。它更像个点对点的管道。你没法像RTMP那样,直接把流推到CDN上。这就引出了我们今天要解决的问题。
WebRTC与RTMP协议转换:核心思路
为什么需要转换?
我举个例子。你做了一个在线教育平台,老师用Chrome浏览器上课(WebRTC推流)。但你的后端用的是FFmpeg集群做录制和转码,FFmpeg只认RTMP。这时候,你就需要一个“翻译官”,把WebRTC的流转成RTMP。
转换的核心在于两个层面:
- 传输层:WebRTC用UDP,RTMP用TCP。需要把UDP包重新封装成RTMP的FLV格式。
- 编码层:WebRTC默认用VP8/VP9或H.264,RTMP通常用H.264。如果编码不一致,需要转码。
我在项目中常用的方案是这样的:
// 伪代码:WebRTC转RTMP的核心流程
// 1. 接收WebRTC的MediaStream
MediaStream stream = peerConnection.getRemoteStream();
// 2. 将MediaStream转成原始数据帧
VideoFrame frame = stream.getVideoTrack().getFrame();
// 3. 用FFmpeg重新封装成FLV格式
AVPacket packet = encodeToH264(frame);
av_write_frame(rtmpOutput, packet);
// 4. 推送到RTMP服务器
rtmp_send(rtmpOutput, "rtmp://your-server/live/stream");
这里有个坑,我曾经踩过:WebRTC的H.264编码参数和RTMP的期望参数可能不一致。比如WebRTC默认的Profile是Baseline,但RTMP服务器可能要求Main Profile。这时候就需要转码,而不是简单的封装转换。
SFU与MCU架构:两种不同的“翻译”方式
讲完协议转换,我们聊聊服务器端的架构。当多个WebRTC客户端和RTMP客户端需要互通时,服务器怎么组织?
主要有两种架构:SFU和MCU。
| 特性 | SFU(Selective Forwarding Unit) | MCU(Multipoint Control Unit) |
|---|---|---|
| 核心逻辑 | 只转发,不处理 | 混流/转码后再转发 |
| 延迟 | 低(毫秒级) | 较高(百毫秒级) |
| CPU消耗 | 低 | 高 |
| 带宽消耗 | 高(每个客户端独立流) | 低(只发一路混流) |
| 典型场景 | 视频会议、连麦 | 大型直播、录制 |
我个人习惯在项目中这样选型:
- 如果客户端数量少(比如4-6人连麦),用SFU。延迟低,体验好。
- 如果客户端数量多(比如上百人观看),用MCU。因为MCU只发一路流,客户端压力小。
但要注意,MCU的混流过程是有延迟的。我记得有一次做在线教育项目,老师端用WebRTC推流,学生端用RTMP拉流。我们用了MCU做混流,结果老师说话后,学生要等0.5秒才能听到。后来改成SFU+客户端自行混流,延迟降到了100ms以内。
SFU与MCU在互通场景中的角色
回到WebRTC和RTMP互通的问题上。SFU和MCU分别扮演什么角色?
我画了一张图,帮你理解:
从图中可以看到:
- SFU路线:WebRTC推流 → SFU转发 → 转封装成RTMP → RTMP服务器 → RTMP拉流端。这条路延迟最低,适合互动场景。
- MCU路线:WebRTC推流 → MCU混流转码 → RTMP服务器 → RTMP拉流端。这条路适合大规模分发,但延迟会高一些。
避坑指南:我曾经踩过的三个坑
最后,分享几个我在实际项目中遇到的坑,希望能帮你少走弯路。
- WebRTC的H.264 Profile问题:WebRTC默认用Baseline Profile,但很多RTMP服务器要求Main Profile。解决办法是在WebRTC的SDP协商时,强制指定Profile-Level-ID。
- 时间戳同步:WebRTC使用RTP时间戳,RTMP使用绝对时间戳。转换时如果不做映射,会导致音画不同步。我习惯在转封装时,用NTP时间作为基准。
- 丢包处理:WebRTC有NACK和FEC机制,但RTMP没有。如果网络不好,RTMP端可能会卡死。我的做法是在SFU层做缓冲,把WebRTC的丢包重传转成RTMP的简单重传。
嗯,关于WebRTC和RTMP的互通,今天就讲到这里。核心就是记住:协议转换是手段,SFU和MCU是架构选择。具体用哪个,取决于你的场景是“低延迟互动”还是“大规模分发”。
下次你在项目中遇到类似问题,不妨先画个架构图,再决定走哪条路。