22、大规模直播场景:WebRTC与CDN结合、WHIP/WHEP协议、低延迟直播方案

各位同学,今天我们来聊一个实战性很强的话题——大规模直播。说实话,WebRTC 做一对一通话很成熟,但一旦要支撑上万甚至百万观众,问题就来了。我最早做直播项目时,天真地以为把 WebRTC 的 PeerConnection 堆上去就行,结果服务器直接被打爆……嗯,那会儿才意识到,大规模直播必须换一套思路。

为什么纯 WebRTC 搞不定大规模直播?

WebRTC 的设计初衷是 P2P 通信,每个观众都要跟主播建立一个独立的 PeerConnection。你想想看,如果主播上行带宽是 10Mbps,每个观众需要 2Mbps,那最多只能服务 5 个人。就算用 SFU(选择性转发单元)做服务端中转,一台 SFU 能承载的并发连接数也有限——我实测过,单台 8 核 16G 的服务器,撑死支持 2000 路并发,再往上延迟和丢包就失控了。

所以,大规模直播的核心矛盾是:WebRTC 的低延迟优势 vs CDN 的海量分发能力。我们需要把两者结合起来。

核心结论:纯 WebRTC 适合小规模互动(<1000人),CDN 适合大规模无互动直播(>1万人)。低延迟直播方案则是在两者之间找平衡。

WebRTC + CDN 的经典架构

我习惯把这种架构叫做“边缘混合架构”。主播端仍然用 WebRTC 推流到媒体服务器,但媒体服务器不直接转发给所有观众,而是把流转换成 HLS 或 DASH 格式,再推到 CDN 边缘节点。观众从最近的 CDN 节点拉流。

这样做的好处很明显:CDN 节点遍布全球,观众就近拉流,延迟虽然比纯 WebRTC 高一些(通常在 5-10 秒),但胜在稳定、成本低。我在一个教育直播项目中用过这套方案,同时在线 5 万人,服务器成本只有纯 SFU 方案的 1/10。

但问题也来了——5-10 秒的延迟,对于互动性强的场景(比如连麦、弹幕竞猜)来说,体验很差。于是就有了低延迟直播方案。

低延迟直播方案:LL-HLS 与 WebRTC 的折中

LL-HLS(Low-Latency HLS)是苹果推出的改进版 HLS,把切片从 6 秒缩短到 1-2 秒,并且支持部分下载(Partial Segments)。理论上延迟可以降到 3-5 秒。但说实话,我在项目中测试过,实际延迟受网络波动影响很大,经常跳到 8 秒以上。

另一种方案是直接用 WebRTC 做分发,但用 CDN 做“最后一公里”的加速。具体做法是:媒体服务器把 WebRTC 流转换成 RTP 包,通过 CDN 的专用回源链路分发到边缘节点,边缘节点再以 WebRTC 协议推给观众。这种方案延迟可以控制在 1-2 秒,但需要 CDN 厂商支持 WebRTC 边缘节点——目前阿里云、腾讯云、AWS 都有类似服务。

我的建议:如果你的直播场景需要实时互动(比如带货主播看弹幕、在线教育老师看学生举手),优先考虑 WebRTC + CDN 边缘节点方案。如果只是单向直播(比如演唱会、发布会),LL-HLS 就够用了,成本更低。

WHIP 和 WHEP 协议:标准化 WebRTC 推拉流

说到 WebRTC 与 CDN 的结合,就不得不提 WHIP 和 WHEP。这两个协议是 IETF 正在标准化的东西,说白了就是给 WebRTC 的推流和拉流定义了统一的 HTTP 接口。

WHIP(WebRTC HTTP Ingestion Protocol):用于推流。主播端通过 HTTP POST 请求创建一个“流资源”,然后通过 WebRTC 的 SDP 交换完成连接。我去年在一个直播工具中集成了 WHIP,发现它最大的好处是兼容性好——任何支持 WebRTC 的浏览器或客户端,只要发一个 HTTP 请求就能推流,不需要额外安装插件。

WHEP(WebRTC HTTP Egress Protocol):用于拉流。观众端通过 HTTP 请求获取流的 SDP 信息,然后建立 WebRTC 连接。WHEP 的好处是支持动态切换——观众可以在不同 CDN 节点之间无缝切换,不会断流。

下面是一个简单的 WHIP 推流流程示意图:

WHIP 推流流程 主播端 (浏览器) 媒体服务器 CDN 边缘节点 HTTP POST (SDP) WebRTC 媒体流 转码 + 分发 观众端 (WHEP) HTTP 拉流

低延迟直播的实战配置

下面是我在一个电商直播项目中用过的配置参数,你可以参考一下:

参数 纯 WebRTC WebRTC + CDN LL-HLS
端到端延迟 200-500ms 1-3s 3-8s
最大并发观众 ~2000 (单SFU) 10万+ 100万+
服务器成本
互动支持
浏览器兼容性 Chrome/Firefox/Safari Chrome/Firefox/Safari 所有浏览器

避坑指南:我曾经在一个项目中直接用 WHIP 推流到 CDN,结果发现 CDN 边缘节点不支持 WebRTC 的 FEC(前向纠错),导致丢包严重。后来我强制在推流端关闭了 FEC,改用 NACK 重传,问题才解决。所以,用 WHIP/WHEP 之前,一定要先确认 CDN 厂商支持的 WebRTC 特性列表

代码示例:基于 WHIP 的推流客户端

下面是一个简单的 JavaScript 示例,演示如何用 WHIP 协议推流到媒体服务器:

// 获取用户媒体流
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });

// 创建 PeerConnection
const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});

// 添加音视频轨道
stream.getTracks().forEach(track => pc.addTrack(track, stream));

// 创建 SDP Offer
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// 通过 WHIP 协议发送 SDP 到服务器
const response = await fetch('https://your-whip-server.com/whip/endpoint', {
  method: 'POST',
  headers: { 'Content-Type': 'application/sdp' },
  body: pc.localDescription.sdp
});

// 获取服务器返回的 SDP Answer
const answerSdp = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp });

console.log('WHIP 推流成功!');

这段代码看起来很简单,但实际部署时要注意:WHIP 服务器返回的 SDP 中可能包含特定的 ICE 候选地址,你需要确保客户端能访问这些地址。我在内网测试时一切正常,一上公网就发现 ICE 候选地址是内网 IP……嗯,后来在服务器端配置了正确的公网 IP 映射才解决。

低延迟直播的终极方案:WebRTC over CDN

如果你既想要 WebRTC 的低延迟,又想要 CDN 的海量分发,目前最成熟的方案是“WebRTC over CDN”。具体来说,就是 CDN 厂商在边缘节点部署 WebRTC 网关,观众通过 WebRTC 协议连接到最近的边缘节点,边缘节点之间通过专线或优化的公网链路传输媒体流。

我去年参与了一个跨国直播项目,主播在纽约,观众在中国。我们用 AWS 的 WebRTC 边缘节点服务,延迟稳定在 800ms 以内,比传统的 HLS 方案快了 10 倍。当然,成本也高了——每 GB 流量大约是 HLS 的 3 倍。所以,是否选择这个方案,取决于你的业务对延迟的敏感度

一句话总结:大规模直播没有银弹。纯 WebRTC 做互动,CDN 做分发,WHIP/WHEP 做标准化接口,低延迟方案则是在成本和体验之间做取舍。我个人习惯是:先评估观众规模和延迟要求,再选方案,而不是盲目追求技术上的“低延迟”。

好了,关于大规模直播的 WebRTC 与 CDN 结合,我就分享到这里。如果你在实际项目中遇到什么问题,欢迎随时交流。

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