做流媒体的朋友应该都有这种感觉:WebRTC本身的传输能力已经非常成熟,但真正麻烦的是“怎么把流送进去”和“怎么把流拉出来”。以前要么自研信令服务,要么用RTMP转WebRTC网关,绕一大圈还容易出兼容性问题。WHIP和WHEP这两个协议就是用来解决这个问题的——它们是WebRTC官方标准化的HTTP接入/接出协议,一个负责推流入口,一个负责拉流出口。这篇文章把我对WHIP和WHEP协议的理解、实际配置过程、踩过的坑整理成一份完整笔记,适合正在搭建低延迟直播链路、做WebRTC网关或者准备替换RTMP方案的开发者参考。
先说结论:WHIP和WHEP不是竞争关系,而是同一套WebRTC标准化体系下的两个方向性协议。WHIP全称是WebRTC-HTTP Ingestion Protocol,核心是把外部媒体流推入WebRTC网络;WHEP全称是WebRTC-HTTP Egress Protocol,核心是把WebRTC网络里的流拉出来给播放器。一个管“入口”,一个管“出口”,配合起来才是一条完整的低延迟直播链路。
1. 先把底层逻辑搞清楚:WebRTC接入为什么需要一个“协议”
1.1 WebRTC传输已经成熟,接入环节却各自为政
WebRTC最厉害的地方在于,它把UDP传输、丢包重传、抖动缓冲、音视频编解码、加密传输这些能力全部内建在浏览器里。开发者只要调RTCPeerConnection接口,就能实现几百毫秒级别的低延迟音视频通信。但问题在于,WebRTC规范只定义了媒体面和控制面的传输方式,并没有统一“如何建立会话”的信令协议。各家平台都有自己的私有信令方案,导致做直播推流时,推流端和服务器之间的对接非常碎片化。
传统直播场景里,RTMP统治了推流端很多年。RTMP走TCP,链路稳定但延迟高,通常在3到10秒,而且浏览器原生不支持RTMP,播放端还得靠Flash或者转封装成HLS。RTSP虽然延迟低,但浏览器原生同样不支持,需要插件或者专门播放器。这些方案的共同痛点都是“接入WebRTC网络”非常麻烦:需要自己实现信令服务器、ICE候选交换、SDP协商逻辑,而且每个平台都要适配一遍。
WHIP和WHEP的价值就在这里。它们把WebRTC的会话建立过程封装成标准HTTP请求,推流端和播放端只需要通过HTTP接口就能完成SDP交换、ICE候选传递、会话资源创建。这套标准化接入方案不仅让服务端实现变简单,也让推流工具、播放器、云服务之间可以互相兼容。
1.2 WHIP和WHEP的定位:一入口,一出品
用生活化的类比来解释:WHIP是“大门”,外部的人(媒体流)通过这个门进入大楼(WebRTC网络);WHEP是“出口闸机”,大楼里的人(媒体流)通过这个闸机出去到观众端。一条低延迟直播链路里,推流端通过WHIP把流送进服务器,服务器完成转码或者直接转发,播放端通过WHEP把流拉出来,整个过程都是标准HTTP操作。
WHIP和WHEP的设计思路非常统一:都基于HTTP方法、都使用SDP描述媒体能力、都依赖ICE完成网络连通、最终都走SRTP加密媒体传输。它们的差异核心在于角色和方向。WHIP源于WebRTC允许浏览器主动向服务器推流的需求,它的客户端是“生产者”;WHEP的客户端是“消费者”,只需要请求一个资源就能得到可播放的媒体流。理解了这层定位,之后看信令流程就能抓住主线。
2. 核心差异逐项拆解:从协议流程到端侧体验
2.1 方向与角色:推流端与播放端根本不同
WHIP和WHEP最核心的区别在角色定位上。WHIP的客户端是推流端,一般是编码器、FFmpeg、OBS或者自研推流SDK,它主动向服务器发起推流请求。WHEP的客户端是播放端,可以是浏览器播放器、移动端播放器,它向服务器发起拉流请求,请求的目标是WHIP推流时创建的会话资源。
这个角色差异直接影响协议流程。WHIP协议流程大致是:推流端向预配置的WHIP endpoint发送HTTP POST请求,携带推流端的SDP offer,服务器创建会话后返回HTTP 201响应,响应体是服务器生成的SDP answer,响应头里的Location字段就是这条流的资源地址。WHEP协议流程则是:播放端向资源地址发送HTTP GET请求,服务器返回HTTP 200响应,响应体是一个SDP answer,这个answer描述了媒体流的状态,播放端拿到后建立RTCPeerConnection就能收流。
对比RTMP和RTSP能更直观理解:RTMP的推流端要主动“握手”并声明发布点,播放端则是通过RTMP拉流地址获取流;RTSP则是控制流和数据流分离,客户端要先DESCRIBE、SETUP、PLAY,才会收到RTP数据。WHIP和WHEP把这种“主动方/被动方”的角色关系变成了“POST创建/GET订阅”的HTTP语义,对开发者更友好。
2.2 信令与媒体传输流程对照
WHIP的完整信令流程可以拆成四步:
- 推流端向WHIP endpoint发送HTTP POST请求,body是SDP offer(描述推流端要推的音视频轨、编解码器、网络候选等),通常在Authorization头里带上鉴权凭证。
- 服务器校验鉴权后,生成自己的SDP answer,返回HTTP 201 Created,同时返回一个session resource URL放在Location头里,这个URL用于后续操作(比如DELETE停止推流)。
- 推流端拿到SDP answer后,与服务器交换ICE候选,建立DTLS连接,完成SRTP密钥协商。
- 媒体数据通过SRTP加密的RTP包传输,推流端可以随时通过DELETE请求关闭会话。
WHEP的完整信令流程则是:
- 播放端向session resource URL发送HTTP GET请求,通常带鉴权头。
- 服务器返回HTTP 200 OK,body是SDP answer,这个answer里已经包含了服务器的ICE候选和媒体描述,播放端原生RTCPeerConnection收到这个offer/answer后可以自动协商。
- 播放端建立自己的RTCPeerConnection,把SDP answer作为remote description,添加ICE候选,等待媒体流入。
- 媒体数据同样通过SRTP加密的RTP包发送到播放端。
两个流程对比下来,最明显的差异是WHIP需要推流端自己构造SDP offer,而WHEP的播放端只需要接收服务器给的SDP answer。原因在于:推流端需要向服务器声明自己将要推送的媒体能力(编码、分辨率、码率),所以必须是offer;播放端只需要告诉服务器“我要订阅这条流”,服务器直接给出匹配的answer,播放器实现起来更轻量。
2.3 鉴权与安全模型
生产环境里,鉴权是不可回避的问题。WHIP因为承担生产端职责,鉴权设计更严格。目前最常见的鉴权方式是HTTP Digest认证,推流端要在POST请求里带Authorization头,服务器校验通过才返回201。MediaMTX、Cloudflare Stream等实现都支持。WHEP因为是消费端,鉴权相对简单,多数实现用Bearer token或者URL参数里的token就能控制访问。
从实测经验看,我建议推流端的鉴权不要只用裸Bearer token,至少使用HTTP Digest或者Bearer + IP白名单的组合,避免推流地址泄露后被人乱推流。播放端的WHEP token可以做到每条播放会话独立,服务端到期失效,能有效控制盗链风险。
安全模型上,WHIP和WHEP都继承了WebRTC的传输层安全能力:媒体面使用SRTP加密,密钥交换通过DTLS完成,ICE候选交换和SDP协商都发生在HTTP层之上,所以信令内容本身也可以通过HTTPS保障。这意味着即使HTTP层被截获,攻击者拿到的也只是加密媒体流,无法直接解析内容。
2.4 端到端时延与浏览器兼容
WHIP和WHEP都走WebRTC,媒体传输天然低延迟。实测在良好网络条件下,一条WHIP推流到WHEP拉流的完整链路,端到端延迟通常在300到700毫秒之间,远低于RTMP+HLS的3到10秒,和WebRTC点对点通信延迟接近。时延主要消耗在网络抖动缓冲、编解码处理、ICE候选协商阶段。
浏览器兼容性方面,核心能力全部依赖原生API:推流端用RTCPeerConnection.addTrack然后createOffer,播放端用ontrack事件接收媒体。这意味着主流现代浏览器(Chrome、Firefox、Edge、Safari)都天然支持WHIP和WHEP的端侧实现。服务器端目前主流支持WHIP/WHEP的开源方案有MediaMTX、Cloudflare Stream、Mux、LiveKit等,几款产品都完成了标准化对接。
3. 实操配置与流程实现:用MediaMTX搭一套WHIP/WHEP链路
3.1 服务端配置与关键参数
我本地测试和生成环境用得最多的是MediaMTX,它配置简单、协议支持全,尤其适合快速搭建WHIP/WHEP链路。取最新版MediaMTX后,核心配置文件mediamtx.yml里需要启用WHIP和WHEP的endpoint。
whip: # 是否启用WHIP协议 enabled: true # WHIP endpoint路径 path: /whip # 是否启用鉴权 authentication: true whep: enabled: true path: /whep authentication: true # 也可以配置路径通配符,让每条流都有独立的资源路径 paths: all_others: # 或者指定具体路径 live: source: publisher这里有几个参数需要解释:
whip.enabled和whep.enabled控制是否对外提供协议端点,生产环境建议开启;path是HTTP接口路径,比如配置为/whip,推流端的POST请求就发到http://你的服务器:8888/whip;authentication控制是否强制鉴权,MediaMTX默认集成内置的用户名密码鉴权,推流端和播放端都要带凭证。
配置完保存并重启服务,用浏览器访问http://你的服务器:8888/就能看到MediaMTX控制台,确认WHIP/WHEP endpoint已启动。
我自己第一次配置时踩过一个坑:只启用了WHIP,没启用WHEP,结果推流端成功推流但播放端始终连不上。后来发现WHEP endpoint没露出来,播放端根本无法发起订阅。实际生产里两个endpoint都要对外暴露,否则一进一出就断了。
3.2 端侧推流实现:FFmpeg走WHIP协议
MediaMTX配置好之后,用FFmpeg就能通过WHIP推流。FFmpeg从很早就支持WHIP,官方编译版本基本都带。推流命令最基础长这样:
ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -tune zerolatency -c:a aac \ -f whip http://localhost:8888/whip?user=admin&pass=admin注意几个关键点:
-re参数表示按原始帧率读取输入文件,模拟实时推流,推直播必须加,否则推流速度会远超实时;-tune zerolatency和-preset veryfast都是为了降低编码延迟,让整条链路满足低延迟需求;- 编码器必须是WebRTC兼容的H264或者VP8/VP9,不能推HEVC(H265)或MPEG2,否则播放端无法解码;
?user=admin&pass=admin是MediaMTX的简单鉴权方式,生产环境建议用HTTP Digest或者Bearer token代替URL参数。
如果做直播场景,推流码率建议控制在2到8Mbps之间,GOP间隔不要太大,2秒一个关键帧比较合适,减少播放端首屏等待。
3.3 端侧播放实现:浏览器一行代码接WHEP
播放端WHEP实现比我想象中更简单。本质上就是发一个GET请求拿到SDP answer,然后丢给RTCPeerConnection,在ontrack事件里把媒体渲染到<video>标签上。一个最基础的播放器封装大概这样:
async function playWhep(whepUrl, videoElement) { const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }); pc.ontrack = (event) => { if (event.track.kind === 'video') { videoElement.srcObject = event.streams[0]; videoElement.play(); } }; const res = await fetch(whepUrl); const answer = await res.text(); const remoteDesc = new RTCSessionDescription({ type: 'answer', sdp: answer }); await pc.setRemoteDescription(remoteDesc); await pc.addIceCandidate({ candidate: '0', sdpMLineIndex: 0 }); }这个实现足够跑通WHEP拉流。要注意的是,服务器返回的SDP answer里已经带着ICE候选信息,播放端要正确设置remote description和ICE候选,否则连接建立不起来。实际生产里建议用pc.onicecandidate收集本地端候选并交给服务器,不过WHEP用服务器提供的单一候选通常也够用。
我实测过这个播放器,拉起一条MediaMTX上的WHIP推流,首屏时间大约在0.5到1秒之间,比RTMP转HLS的3秒以上快很多。如果网络质量差,则必须接入TURN服务器辅助穿越,否则视频会卡在连接阶段一直转圈。
3.4 生产环境链路组装:WHIP推流 + 转码节点 + WHEP播放
单机演示只是第一步,生产环境里我会把WHIP和WHEP组合成一条完整链路。典型部署架构是这样的:
- 推流端(OBS/FFmpeg编码器)通过WHIP把流推入边缘接入节点;
- 接入节点完成码率自适应或者多码率转码,也可以通过WHIP/WHEP协议把流转发到中心集群;
- 播放端(浏览器/移动端)通过WHEP从最近的边缘节点拉取流。
这种架构下,WHIP负责“边缘接入”,WHEP负责“边缘分发”,WebRTC传输面独立在HTTP信令之外。要注意的是,WHEP播放端如果需要多码率自适应,需要在服务端准备多路编码档位,并为每个档位生成独立的WHEP资源,播放端根据带宽切换资源地址。相比RTMP+HLS可以做切片级自适应,WHEP目前更接近“切换流地址”的自适应方式,细节需要额外设计。
4. 问题排查与经验速查:实战中的典型坑
4.1 连接建立类问题
实战中遇到最多的连接问题包括:播放端一直“加载中”、观看黑屏、推流成功但播放端无响应。这些问题的根源通常在ICE候选、防火墙UDP封禁或TURN没配。
如果推流成功、播放端能拿到SDP answer但画面一直不出来,先用浏览器开发者工具看RTCPeerConnection的连接状态。iceConnectionState停留在checking,基本就是UDP不通。多数云服务器默认策略不会封UDP,但公司内网、家用宽带经常屏蔽非标准UDP端口。解决方法是配置TURN服务器,让ICE候选包含转发的地址。
我踩过的坑是配置TURN后忘记在播放端iceServers里加上TURN地址,导致跨运营商网络时播放频繁卡顿,加上TURN后问题立刻解决。建议生产环境至少自建一个coturn服务,TURN地址作为STUN的补充,而不是完全替代。
4.2 编解码与媒体描述类问题
能建立连接但黑屏、有声音没画面、有画面没声音,基本都是媒体协商问题。WebRTC在Chrome里的H264解码支持有限制,推流端如果用了高Profile H264(比如High 4:4:4),播放端可能解析不了。FFmpeg推流时可以显式指定Profile:
-c:v libx264 -profile:v baseline -level 3.1Baseline Profile是WebRTC兼容性最好的档位之一。视频编码建议用H264 Baseline或Constrained Baseline,音频统一用Opus,这样所有现代浏览器都能解码。如果必须用AAC,要注意部分浏览器对AAC over WebRTC支持有限,不如直接转Opus省心。
GOP也是一个容易忽略的点。WebRTC传输按RTP包粒度,如果GOP太长(比如4秒一个关键帧),播放端加入中段流程时可能出现长时间等待画面。我把GOP锁定在2秒以内,实测加入中段的首屏时间明显缩短。
4.3 WHEP拉流鉴权与URL管理问题
WHEP常见问题是token失效后播放端还在反复请求。比如用Bearer token鉴权,token过期后播放端拉流失败,但浏览器可能缓存了GET请求结果,导致播放器一直表现异常。解决办法有两个:一是服务器端在token过期时返回401状态码,并且带上WWW-Authenticate头,播放端捕获到401就清缓存重新鉴权;二是前端播放器每次播放前手动拼接新的token参数,不依赖浏览器缓存。
WHIP推流端的鉴权管理也不容忽视。有些开发者图方便,直接用明文token放在URL里推流,token长期有效,很容易被爬虫扫描到。实测生产环境建议WHIP使用HTTP Digest认证,凭证至少30天轮换一次,并在服务端限制每个凭证的并发推流路数,防止账号被滥用。
4.4 常见问题速查表
整理一张速查表作为快速排查工具:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 播放端一直“加载中” | ICE连接未建立、UDP被封 | 添加STUN/TURN服务器,检查防火墙UDP放行 |
| 有声音无画面 | 视频编码不被支持 | 改为H264 Baseline/VP8/VP9,同步检查Profile |
| 画面卡顿、延迟高 | GOP过长、网络抖动大 | 减小GOP到2秒内,增加TURN转发,调整丢包重传 |
| WHEP拉流401鉴权失败 | token过期或缓存 | 服务端返回401清缓存,前端动态拼token |
| 推流成功但播放端拉不到流 | 路径不匹配或WHEP未启用 | 核对资源URL与WHEP endpoint路径,确认服务端路径配置 |
| 首屏时间过长 | 编码器未加zerolatency | 推流端加-tune zerolatency,降低编码缓冲 |
这条速查表是几次实际上线踩坑后总结的,遇到黑屏问题,先判断连接是否成功,再查编码,顺序很重要,别一上来就怀疑协议有问题。
5. 一些额外的心得和扩展思路
WHIP和WHEP不是二选一的替代方案。在实际项目中,它们往往配合使用:生产侧用WHIP把摄像机、编码器、直播推流端接入,分发侧用WHEP把流给浏览器和移动端播放器。如果做互动连麦,WHIP是连麦参与者进入会议通道的入口;如果做单路低延迟直播,WHEP就是观众端默认拉流通道。先把“推”和“拉”拆开看,再组合成链路,整个架构会清晰很多。
从部署角度看,WHIP/WHEP相比RTMP/HLS的优势不仅体现在延迟上,更重要的是标准化程度高。RTMP源于Flash时代,生态碎片化严重;WHIP/WHEP从设计之初就服务于浏览器原生WebRTC,服务端实现统一,协议演进路径也清晰。未来如果要做低延迟直播平台,这套HTTP接入方案应该是首选。
最后分享一个我自己测试时的小技巧:先用MediaMTX跑通本地WHIP到WHEP的端到端流程,确认推流和播放都正常后,再上云服务器配置TURN和域名HTTPS。本地网络环境干净,更容易定位问题,上云后再排查ICE穿越和鉴权,能省很多不必要的调试时间。