ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WHIP与WHEP协议详解:WebRTC低延迟直播推拉流标准化接入指南

WHIP与WHEP协议详解:WebRTC低延迟直播推拉流标准化接入指南 做流媒体的朋友应该都有这种感觉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 OKbody是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毫秒之间远低于RTMPHLS的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/whipauthentication控制是否强制鉴权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?useradminpassadmin注意几个关键点-re参数表示按原始帧率读取输入文件模拟实时推流推直播必须加否则推流速度会远超实时-tune zerolatency和-preset veryfast都是为了降低编码延迟让整条链路满足低延迟需求编码器必须是WebRTC兼容的H264或者VP8/VP9不能推HEVCH265或MPEG2否则播放端无法解码?useradminpassadmin是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资源播放端根据带宽切换资源地址。相比RTMPHLS可以做切片级自适应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穿越和鉴权能省很多不必要的调试时间。
返回列表