ARTICLE DETAIL

资讯详情

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

WHIP/WHEP:基于HTTP的WebRTC接入协议,实现秒级低延迟直播

WHIP/WHEP:基于HTTP的WebRTC接入协议,实现秒级低延迟直播 做流媒体开发的这两年一定没少被问“能不能把延迟降到一秒以内”。传统的RTMP推流加HLS分发架构再优化也是秒级起步碰上互动直播、远程操控、连麦PK这种场景基本束手无策。WebRTC技术栈能解决低延迟问题但落地时有一个很尴尬的坎推流端和播放端怎么用最简单的HTTP方式接入WebRTC分发网络。WHIP和WHEP这两个协议就是IETF为这件事推的标准。很多人第一次看到这俩缩写会懵以为是什么新出的传输协议其实它们根本不是传输层的东西而是定义在HTTP之上、专门用来“描述WebRTC会话如何建立”的应用层协议。简单说一个是负责把音视频流从客户端推上去一个是负责把流从服务器拉下来。这篇就结合我自己的实际部署和排查经验把这两个协议的差异、交互流程、踩坑点一次说清楚。1. 这两个协议到底解决什么问题1.1 WebRTC接入的老大难信令谁来做WebRTC本身不是一个完整协议它是一套浏览器内置的实时通信能力包括采集、编码、传输、渲染。但它有个特点媒体面走的是SRTP over UDP控制面却需要自己协商。两个端要交换SDP会话描述、交换ICE候选网络路径探测这中间的过程就叫信令交互。标准WebRTC规范没有规定信令怎么传只定义了信令必须携带的信息格式。这就导致一个问题每个人都自己写一套信令服务器格式千奇百怪联通性极差。做过WebRTC网关接入的人应该深有体会对接一个第三方客户端光看对方的信令交互时序就要花一两天还经常有私有扩展。WHIP和WHEP的思路是用HTTP的方法语义和RESTful资源模型把信令交互简化成几个HTTP请求。不搞WebSocket长连接不搞自定义消息格式就是一个POST、一个PATCH、一个DELETE干净利落。这让WebRTC的接入门槛从“理解整套信令状态机”降到了“会发HTTP请求”对推流工具、播放器、物联网设备都非常友好。用生活化的类比来说WebRTC像两个人要建立一条加密专线通话SDP就是各自的“通话方案说明书”ICE是“各自探测到的可达地址清单”。以前你得雇一个专门的信令员用对讲机来回传纸条现在WHIP/WHEP规定了你直接往一个固定信箱投递纸条取件时再去另一个信箱拿回执流程统一了对接自然快。1.2 WHIP和WHEP是一对镜像设计WHIP全称是WebRTC HTTP Ingestion ProtocolIngestion就是“摄入、推入”它的定位是上行推流。WHEP全称是WebRTC HTTP Egress ProtocolEgress是“出口、流出”定位是下行拉流。一个进一个出设计思路上基本是镜像的但细节和角色分工完全不同。先说WHIP。客户端OBS、FFmpeg、自研推流器是offerer负责生成SDP offer通过HTTP POST发送给服务器。服务器作为answerer解析offer之后生成SDP answer返回。之后如果客户端的ICE候选发生变化可以用PATCH方法增量更新。整个会话的生命周期由客户端通过DELETE方法主动结束。再说WHEP。客户端浏览器播放器、移动端SDK反过来是answerer它先GET一个流资源的URL拿到服务器生成的SDP offer然后自己生成SDP answer通过POST返回给服务器。服务器确认后客户端就可以开始收流播放。注意这里方向颠倒服务器反而成了offerer。如果你已经接触过WebRTC原生流程会发现WHIP里客户端就是标准的offer/answer模型里的主叫方WHEP里客户端是应答方。这个角色的颠倒决定了两个协议在交互时序、资源模型、错误处理上的很多差异下面细说。2. 协议交互流程的逐段拆解2.1 WHIP推流的一次完整会话先看WHIP。我用一个实际例子来说客户端推流到MediaMTX这类支持WHIP的服务器。第一步客户端构造一个SDP offer里面包含音频和视频的m-line、编解码参数、ICE候选有些实现还会把ICE候选后续单独发。然后向服务器发起POST请求POST /whip/icecast HTTP/1.1 Host: live.example.com Content-Type: application/sdp Authorization: Bearer token v0 o- 4611738379501246791 2 IN IP4 127.0.0.1 ...服务器收到之后会验证鉴权、创建会话资源生成SDP answer返回201 Created响应头里带Location指向这个会话资源的URL同时返回ETag用于后续并发控制的版本校验。HTTP/1.1 201 Created Location: https://live.example.com/whip/icecast/abc123 ETag: abc123-1 v0 o- 6847426145889484212 2 IN IP4 192.168.1.10 ...这一步狠关键Location就是整条会话的控制句柄后面所有更新和销毁都指向它。有些实现搞不清楚以为拿到answer就完事了ICE候选还没到齐直接用这个answer去建媒体通道结果卡在连接中。第二步如果客户端启用了Trickle ICE会在拿到answer之后继续通过PATCH请求把后续发现的ICE候选增量上报。几乎所有的浏览器和主流推流工具默认都开Trickle ICE所以这一步不是可选项而是常态。PATCH /whip/icecast/abc123 HTTP/1.1 Content-Type: application/trickle-ice-sdpfrag If-Match: abc123-1 aice-ufrag:xyz acandidate:1 1 UDP 2122252543 192.168.1.5 61234 typ host服务器收到后如果处理成功返回204 No Content。如果If-Match的ETag不匹配说明会话已被并发修改需要客户端重新拉取最新状态再做合并这个机制避免了多个PATCH互相覆盖的竞态问题。第三步推流结束客户端用DELETE请求销毁会话资源服务器释放端口、ICE状态、编码器上下文等资源。DELETE /whip/icecast/abc123 HTTP/1.1 Host: live.example.com返回204之后整个推流会话才算完整闭环。2.2 WHEP拉流和WHIP正好相反WHEP的流程从客户端的角度看类似“先获取流资源再订阅并播放”。第一步播放端向服务器GET一个流资源URL。这个URL通常是一个直播流的标识或者是某个房间的播放地址。GET /whep/channel/abc123 HTTP/1.1 Host: live.example.com Authorization: Bearer token服务器返回200 OKContent-Type是application/sdpbody是服务器的SDP offer。这里的offer包含服务器的ICE候选、DTLS指纹、媒体参数。注意服务器是offerer所以它必须把自己的ICE候选一次性塞进offer里之后如果服务器侧候选有变化需要通过后续机制补充。第二步客户端解析offer生成自己的SDP answer用POST回传给服务器POST /whep/channel/abc123 HTTP/1.1 Host: live.example.com Content-Type: application/sdp v0 o- 9067820494168763021 2 IN IP4 127.0.0.1 ...服务器验证answer后返回201 Created创建播放会话资源响应头同样带Location和ETag用于后续会话管理和重协商。第三步播放中如果发生重协商比如码率切换、转码参数变化客户端或服务器通过PATCH更新SDP片段逻辑和WHIP基本一致。播放结束用DELETE释放会话。2.3 一句话总结两者差异对比维度WHIPWHEP全称WebRTC HTTP Ingestion ProtocolWebRTC HTTP Egress Protocol用途推流/发布拉流/订阅客户端角色offerer生成offeranswerer生成answer服务器角色answerer生成answerofferer生成offer初始请求POST SDP offer 创建资源GET 获取SDP offer后续请求PATCH 更新 ICE/重协商POST SDP answer 确认订阅资源语义创建新资源获取已有资源并创建订阅典型场景摄像头推流、OBS直播、无人机图传网页播放器、小程序播放、监控大屏3. 为什么说WHIP/WHEP比RTMP、SRT更适合现代直播3.1 浏览器原生播放省掉转码和分发链路RTMP能活这么多年靠的是协议简单、工具链成熟但它有两个死穴一是RTMP本身是Adobe私有协议浏览器不原生支持必须通过Flash已经停服或HTTP-FLV、HLS转封装才能播二是RTMP默认走TCP长连接在弱网下的表现远不如WebRTC基于UDP的拥塞控制灵活。WHIP把推流端直接变成了浏览器能认识的WebRTC服务器收到流之后如果播放端也是WebRTC整条链路可以做到不用任何转码直接UDP转发端到端延迟能稳定在300~800毫秒。我实测下来在上海到北京的跨地域推流场景下WHIP转WHEP的延迟大概在400毫秒左右同样的网络条件用RTMP加HLS至少三到五秒。SRT是另一个常在直播场景出现的协议它基于UDP但在应用层做重传和加密穿透性很强但SRT的问题是生态里没有浏览器原生播放方案要播SRT流基本得靠ffplay、VLC这些桌面软件或自研播放器。而WHIP/WHEP天然面向浏览器和移动端可以直接用JavaScript或原生SDK收流播放部署成本低了不止一个量级。3.2 和MQTT、CAN这些协议不是一个赛道经常有人把WHIP和MQTT、Modbus、CAN、UART这些词放在一起搜索以为它们是同类东西。其实这里有个概念层级的问题。MQTT、Modbus、CAN这类协议解决的是“设备之间如何结构化传递消息/控制指令”它们工作在IoT网关、PLC、传感器网络这一层传输的是控制指令或小幅数据。WHIP/WHEP解决的是“实时音视频媒体流如何接入分发网络”它们工作在最上层应用传输的是SRTP封装的媒体包和ICE/DTLS控制信息。做个类比MQTT像是仓库里的货物调度单只传达“把A箱子搬到B区”这样的指令WHIP/WHEP则是一辆常驻的冷链货车专门负责把生鲜从产地运到超市车厢里温度、路径都是实时可控的。你不可能用MQTT传1080P60帧的视频也不该用WHIP去下发传感器的开关命令协议选型之前先把层次理清楚能少走很多弯路。3.3 服务器选型从MediaMTX到自定义网关如果你只是想快速验证WHIP和WHEP目前最友好的开源实现是MediaMTX它同时支持WHIP推流和WHEP拉流编译好之后一条命令就能起服务。LiveKit、Janus也都在跟进这两个协议的标准实现但配置复杂度高一些适合做大规模分布式部署。我自己的建议是验证阶段用MediaMTX快速摸清交互细节生产阶段根据并发规模考虑LiveKit或其他商业方案或者基于pion/webrtc自研轻量网关。自研网关的核心工作量其实不在信令解析而在ICE候选的管理、NAT穿透的兜底策略、以及和已有鉴权体系的打通。4. 实操中容易踩的坑和排查思路4.1 ICE Candidate不全导致连接卡死这是我在对接OBS的WHIP插件时遇到最多的现象POST请求成功返回了answer也拿到了但客户端一直卡在连接中几秒后超时。抓包发现服务器的SDP answer里没有包含足够的ICE候选尤其是内网环境和公网环境的地址映射关系没建立好。排查思路是先看服务器的网络拓扑。如果服务器是单网卡且直接暴露在公网或内网ICE候选通常能自然生成但如果服务器前面有NAT、负载均衡、防火墙就需要在服务器配置里显式指定外网IP映射。MediaMTX里对应的是iceHostNAT这类参数LiveKit则靠UDPPort和UseExternalIP配置。另外客户端和服务器都开启Trickle ICE时PATCH的时序决定成败。某些播放器不支持Trickle ICE只在offer/answer里一次性带全候选此时服务器若开启了Trickle且没把初始候选塞全就会出问题。稳妥做法是服务器端同时支持“SDP内联候选”和“Trickle ICE PATCH”兼容不同客户端。4.2 ETag并发控制不是摆设WHIP/WHEP的PATCH更新带If-Match一开始我觉得这是多余设计直到有一次生产环境出现诡异的现象一个推流端频繁重协商另一个监控客户端同时也在更新会话两个PATCH交叉执行服务器的会话状态被后写的旧数据覆盖导致SDP和实际编码参数对不上播放端出现花屏。后来我做了个修改服务器对每个会话资源维护主版本号所有PATCH必须带当前ETag如果版本不一致直接返回412 Precondition Failed由客户端重新GET资源状态再合并更新。改完之后再没出现过这个竞态问题。这里提醒一句不要为了省事关掉ETag校验尤其在多客户端共享同一流资源的场景下ETag是唯一能防止状态回退的屏障。4.3 WHEP播放端黑屏但不报错的问题WHEP拉流有个隐蔽的问题播放器拿到SDP answer并返回POST之后显示“已连接”但画面一直黑屏日志里也抓不到报错。这种情况九成是音频参数或视频参数协商不一致服务器实际发送的编码格式和播放端answer里的m-line顺序对不上。我的排查方法是在服务器端打开DTLS日志和SRTP解包日志对比协商出来的codec payload type。很多WebRTC库默认用动态payload type如果不固定双方协商结果可能都是96、98这类动态值但含义不同媒体数据自然解不出来。解决方案是显式设置编码参数表比如H.264固定用96Opus固定用111并且禁止协商结果落到H.265这类浏览器不支持的编码上。在MediaMTX里配置videoCodec和audioCodec字段就能控制自研网关的话在生成offer时直接过滤编码空间。4.4 鉴权和跨域别忘了WHIP/WHEP本质是HTTP所以所有HTTP层的老问题都会找上来。实际对接第三方设备时最常见的是CORS跨域问题设备网页跑在A域推流请求发到B域的WHIP服务器浏览器直接拦截预检请求。解决方式是在服务器统一加Access-Control-Allow-Origin响应头并且处理好OPTIONS预检。鉴权方面WHIP/WHEP没有规定具体鉴权格式主流实现都是在Authorization头里放Bearer Token或者自定义一个X-Session-Token。我建议统一走Bearer Token配合HTTPSToken里绑定会话ID和时间戳服务端校验通过后再创建会话资源。4.5 网络环境的NAT穿透兜底WebRTC不是万能的魔法它只是把STUN/TURN的机制整合了进来。WHIP/WHEP服务器如果只配了STUN客户端在全锥型NAT或对称NAT后面媒体流还是可能打不通。我的经验是公网生产环境必须配TURN服务否则总有那么一部分用户投诉连不上。TURN的选型现在基本就是coturn配置也不复杂只需要在WHIP/WHEP服务器的ICE配置里把urls指到coturn的地址并填好用户名的静态凭据。注意TURN端口最好固定UDP 3478方便防火墙放行但实际媒体流量会走TURN分配的临时端口防火墙策略要放行范围端口否则同样会失败。5. 实际案例复盘一套低延迟监控系统的接入去年我参与了一个连锁零售门店的远程巡店项目需求是门店端用海康摄像头推流总部运营人员在网页上实时查看要求延迟低于一秒。一开始方案是摄像头RTSP拉流到中心服务器转成HLS播放结果延迟在三秒以上巡店体验很差。后来改成WHIP/WHEP方案门店边缘侧用MediaMTX接收摄像头RTSP流再通过WHIP推流到中心节点实际上MediaMTX支持直接把RTSP转成WHIP推出去。总部网页播放器用WHEP拉流浏览器原生播放不需要安装任何插件。整个链路是摄像头RTSP - MediaMTX拉流 - WHIP上行 - 中心节点 - WHEP下行 - 浏览器播放。首屏打开时间在500毫秒左右端到端延迟稳定在600到900毫秒之间基本满足“实时”的需求。踩过的坑有两个值得拿出来说。第一门店出口路由器的NAT老化时间短导致ICE候选里的内网地址在几秒后失效媒体流频繁重协商。后来我在MediaMTX里把STUN探测间隔调短并给核心推流客户端配置了TURN中继问题就消失了。第二部分老旧摄像头生成的RTP时间戳抖动大中心节点从RTSP拉到WHIP再编码时出现音画不同步最后在MediaMTX的转推配置里打开音视频同步校正才算稳定。6. 我对WHIP和WHEP的实际使用心得这两个协议现在是WebRTC生态里最值得投入精力研究的方向不是说它们能取代RTMP、SRT这类老牌协议而是它们把WebRTC的接入成本降到了“HTTP级”让更多非浏览器设备摄像头、无人机、智能眼镜可以轻松接入实时音视频分发网络。我个人在实际项目里的做法是新设计的低延迟直播架构优先考虑WHIP推流加WHEP拉流如果客户端是纯浏览器或移动端APP这套方案几乎不需要额外的协议适配工作如果客户端是OBS这类桌面推流软件配合OBS的WHIP插件效果已经很好。传统协议RTMP/SRT继续留着做兼容备份用来对接老设备或跨平台分发。最后再分享一个小技巧自研WHIP/WHEP网关时一定不要把ICE状态机做得太复杂尽量让offer/answer携带完整候选PATCH只负责增量更新减少不必要的状态分支。我见过很多实现把Trickle ICE做得过于灵活反而引入一堆并发bug。简单、稳定的协议交互比花哨的特性堆砌重要得多。
返回列表