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。

转换的核心在于两个层面:

  1. 传输层:WebRTC用UDP,RTMP用TCP。需要把UDP包重新封装成RTMP的FLV格式。
  2. 编码层: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。这时候就需要转码,而不是简单的封装转换。

注意: 如果只是封装格式不同(比如WebRTC用H.264,RTMP也用H.264),可以用“转封装”方式,性能损耗很小。但如果编码格式不同(比如VP8转H.264),就必须做“转码”,CPU开销会大很多。

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分别扮演什么角色?

我画了一张图,帮你理解:

WebRTC与RTMP互通架构图 WebRTC 推流端 WebRTC 拉流端 UDP/SRTP SFU 服务器 只转发,不处理 MCU 服务器 混流+转码 可选级联 转封装 RTMP 服务器 转码+混流 RTMP 拉流端 图例说明: WebRTC客户端 RTMP客户端/服务器 SFU(低延迟转发) MCU(混流转码) 注:实际部署中,SFU和MCU可以单独使用,也可以级联组合

从图中可以看到:

  • SFU路线:WebRTC推流 → SFU转发 → 转封装成RTMP → RTMP服务器 → RTMP拉流端。这条路延迟最低,适合互动场景。
  • MCU路线:WebRTC推流 → MCU混流转码 → RTMP服务器 → RTMP拉流端。这条路适合大规模分发,但延迟会高一些。
我的建议: 如果你做的是“互动直播”(比如主播和观众连麦),优先用SFU。如果你做的是“大型直播”(比如万人观看),用MCU+CDN的方案更稳妥。我在一个百万级直播项目中,就是用的MCU混流后推到CDN,效果很稳定。

避坑指南:我曾经踩过的三个坑

最后,分享几个我在实际项目中遇到的坑,希望能帮你少走弯路。

  1. WebRTC的H.264 Profile问题:WebRTC默认用Baseline Profile,但很多RTMP服务器要求Main Profile。解决办法是在WebRTC的SDP协商时,强制指定Profile-Level-ID。
  2. 时间戳同步:WebRTC使用RTP时间戳,RTMP使用绝对时间戳。转换时如果不做映射,会导致音画不同步。我习惯在转封装时,用NTP时间作为基准。
  3. 丢包处理:WebRTC有NACK和FEC机制,但RTMP没有。如果网络不好,RTMP端可能会卡死。我的做法是在SFU层做缓冲,把WebRTC的丢包重传转成RTMP的简单重传。

嗯,关于WebRTC和RTMP的互通,今天就讲到这里。核心就是记住:协议转换是手段,SFU和MCU是架构选择。具体用哪个,取决于你的场景是“低延迟互动”还是“大规模分发”。

下次你在项目中遇到类似问题,不妨先画个架构图,再决定走哪条路。


公众号:蓝海资料掘金营,微信deep3321