22、WebRTC与直播:WHIP/WHEP协议、低延迟直播方案、LL-HLS对比

聊到WebRTC和直播的结合,很多人第一反应是“WebRTC不是做实时通信的吗?跟直播有什么关系?”

嗯,这个问题我几年前也困惑过。后来在做一个互动直播项目时,被延迟问题折磨得够呛,才真正开始研究WebRTC在直播场景下的落地。今天咱们就把这块掰开揉碎了讲清楚。

一、直播延迟的痛点:为什么传统直播不够用?

先说说传统直播的延迟情况。HLS(HTTP Live Streaming)和DASH是主流方案,但它们有个天然缺陷——切片机制。

HLS把视频切成一个个小片段,每个片段2-10秒。播放器下载完一个片段才能播,再加上缓冲区,延迟轻松到20-30秒。你想想看,直播间里观众刷“主播你好”,主播30秒后才看到,这互动体验能好吗?

我在做电商直播项目时,遇到过最夸张的情况:主播说“上链接”,观众看到时商品已经抢光了。延迟整整45秒。从那以后,低延迟就成了我重点关注的方向。

核心矛盾:传统直播追求稳定性和兼容性,牺牲了延迟。而互动场景需要延迟在1秒以内。

二、WHIP/WHEP协议:WebRTC进入直播的钥匙

WHIP(WebRTC HTTP Ingestion Protocol)和WHEP(WebRTC HTTP Egress Protocol)是IETF标准化的协议。说白了,它们解决了两个问题:

  • WHIP:推流端怎么把视频流送进服务器
  • WHEP:播放端怎么从服务器拉流播放

为什么需要这两个协议?因为WebRTC原本是P2P的,没有“服务器中转”的标准。你直接用WebRTC推流到CDN?不行,CDN不认识SDP和ICE。WHIP/WHEP就是那个“翻译官”。

WHIP推流流程

  1. 推流端创建PeerConnection,生成SDP Offer
  2. 通过HTTP POST发送SDP到WHIP端点
  3. 服务器返回SDP Answer,并分配一个资源URL
  4. ICE连接建立,开始推流
// WHIP推流示例(简化版)
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach(track => pc.addTrack(track, stream));

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// 发送到WHIP端点
const response = await fetch('https://whip-server.example.com/whip', {
  method: 'POST',
  headers: { 'Content-Type': 'application/sdp' },
  body: pc.localDescription.sdp
});

const answerSdp = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp });
个人经验:WHIP的ICE重连机制比传统RTMP强很多。我在弱网环境下测试,RTMP断了基本就黑了,WHIP能在3-5秒内自动恢复。这一点在移动端直播时特别重要。

WHEP拉流流程

WHEP和WHIP类似,只是方向相反。播放端向WHEP端点请求流,服务器返回SDP,然后建立WebRTC连接。

// WHEP拉流示例
const pc = new RTCPeerConnection();
pc.ontrack = event => {
  videoElement.srcObject = event.streams[0];
};

const response = await fetch('https://whip-server.example.com/whep/stream-123');
const offerSdp = await response.text();
await pc.setRemoteDescription({ type: 'offer', sdp: offerSdp });

const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);

// 把Answer发回服务器
await fetch(`https://whip-server.example.com/whep/stream-123`, {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/sdp' },
  body: pc.localDescription.sdp
});
注意:WHEP的SDP交换顺序和WHIP是反的。WHIP是客户端发Offer,WHEP是服务器发Offer。搞反了连接会失败。我曾经在这个坑里爬了整整一天。

三、低延迟直播方案:不止WebRTC一条路

说到低延迟直播,市面上主要有几个流派。我整理了一张对比表,方便你直观感受差异。

方案 延迟范围 协议基础 浏览器兼容性 适用场景
WebRTC (WHIP/WHEP) 200ms - 1s UDP + SRTP Chrome/Firefox/Edge原生支持 互动直播、在线教育、远程医疗
LL-HLS 3-6s HTTP + TS/fMP4 所有浏览器(通过HLS.js) 大规模直播、赛事转播
SRT 500ms - 2s UDP + 自定义ARQ 需插件或Native SDK 广电级传输、跨国推流
RTMP 3-8s TCP 需Flash(已淘汰) 老旧系统兼容

从表里能看出来,WebRTC在延迟上优势明显。但为什么不是所有场景都用WebRTC?因为成本高、服务器压力大。WebRTC是UDP + 加密传输,对CPU和带宽消耗都比HLS大。

四、LL-HLS:苹果的改良方案

LL-HLS(Low-Latency HLS)是苹果在2019年推出的。它改进了传统HLS的切片方式,把延迟从20-30秒降到了3-6秒。

怎么做到的?核心是两个技术:

  • 部分片段(Partial Segments):不再等整个切片完成再发布,而是边录制边发布小片段
  • 预加载提示(Preload Hints):播放器可以提前请求下一个片段,减少等待时间

但说实话,LL-HLS的3-6秒延迟在互动场景下还是不够。我做在线答题直播时,要求延迟在1秒以内,LL-HLS完全扛不住。最后只能上WebRTC。

我的建议:如果场景是“看为主、互动为辅”(比如演唱会直播),LL-HLS够用。如果是“强互动”(比如连麦、弹幕互动、在线课堂),直接上WebRTC。

五、核心逻辑:什么时候选什么方案?

下面这张图是我自己总结的选型逻辑,帮你快速决策。

低延迟直播方案选型逻辑 直播延迟需求 延迟 < 1秒(强互动) 延迟 3-6秒(弱互动) 推荐:WebRTC (WHIP/WHEP) 延迟200ms-1s,支持双向通信 推荐:LL-HLS 延迟3-6s,兼容性好,成本低 注意:需要WebRTC服务器(如Mediasoup、Janus) 优势:CDN成熟,支持大规模并发 选型核心:看互动强度,而不是只看延迟数字

六、实战避坑指南

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

坑1:WebRTC的ICE连接在NAT环境下不稳定
我曾经在某个教育项目中,发现20%的用户连不上WebRTC。排查后发现是Symmetric NAT导致的。解决方案是部署TURN服务器,但TURN成本高,建议只在必要时启用。
坑2:LL-HLS的延迟不稳定
你以为LL-HLS能稳定在3秒?不一定。如果播放器缓冲区设置不当,或者网络抖动,延迟可能跳到10秒以上。我建议在播放器端做动态缓冲区调整,根据网络状况自动缩短或延长缓冲区。
坑3:WHIP/WHEP的SDP协商顺序
这个前面提过,但值得再说一遍。WHIP是客户端发Offer,WHEP是服务器发Offer。如果你用同一个代码库处理推流和拉流,一定要区分逻辑。我当初就是偷懒没区分,结果推流正常、拉流全挂。

好了,关于WebRTC和直播的结合,今天就聊到这儿。WHIP/WHEP让WebRTC进入了直播领域,LL-HLS则在传统HLS基础上做了改良。选哪个,取决于你的场景是强互动还是弱互动。

记住一句话:没有最好的协议,只有最合适的方案。


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