我这两年在流媒体项目里,没少和 RTSP、RTMP 打交道。最近 WHIP、WHEP 这两个名字经常出现在技术群里,尤其在聊网页低延迟直播和 WebRTC 接入的时候。做直播、监控上云、云导播的同学都在问同一个问题:WebRTC 的新接入协议出来了,RTSP、RTMP 是不是该退场了?加上 SmartMediaKit 这类多协议网关越来越普及,一台服务既能收 RTSP 摄像头流、也能接 RTMP 推流、还能让浏览器直接低延迟播放,似乎“大统一”已经不远。这篇文章我想把协议层面的思考和一段实战过程都摊开聊,给正在选流媒体方案的人做个参考,也帮刚接触的朋友把 WHIP/WHEP 到底解决什么问题看清楚。

1. 先说结论:RTSP/RTMP 依然能打,WHIP/WHEP 补上了最后一公里

1.1 RTSP:安防生态的中流砥柱,只是没想着给浏览器用

RTSP 是 IETF 在 1998 年提出的流媒体会话控制协议,它本身不负责传输音视频数据,真正跑媒体的是 RTP/RTCP。客户端通过 DESCRIBE 拿到 SDP 描述,用 SETUP 建立传输通道,发 PLAY 开始收流,整个过程和“控制播放器”很像。由于设计目标就是远程播放和点播控制,它在安防领域混得非常好,IPC、NVR、ONVIF 协议栈几乎都带 RTSP 支持,延迟也能稳定做到 0.2 到 1 秒。RTSP 的问题也很突出:NAT 穿透基本靠端口映射,公网拉流往往要借助中间媒体服务器;加密不是标配,RTP 明文在公网跑让人不太安心;浏览器没有任何原生播放能力,用户要么装 VLC,要么靠后端转封装转协议。

1.2 RTMP:Flash 退休了,协议还在直播推流里跑

RTMP 是 Adobe 时代的产物,基于 TCP 长连接,默认 1935 端口,通过握手、connect、createStream、publish/play 完成推拉流。为什么到现在还在大量使用?核心原因在推流侧:OBS、FFmpeg、各种手机推流 SDK 都支持 RTMP,CDN 的直播摄取入口也普遍默认收 RTMP,整个工具链和运维习惯都是按它长出来的。播放侧则比较尴尬,Flash 退场后浏览器不再原生支持 RTMP,实际播放要依赖服务端再转出 HTTP-FLV 或 HLS。再加上 RTMP 走 TCP,队头阻塞问题在高丢包、弱网环境下会导致延迟抖动明显,所以今天 RTMP 更适合当“生产端协议”,不适合当“消费端协议”。

1.3 WHIP/WHEP:WebRTC 终于有了统一接入入口

WebRTC 在浏览器端很强:支持 ICE 穿透、DTLS-SRTP 加密、SRTP 媒体传输、NetEQ 抖动缓冲、GCC 拥塞控制,端到端延迟能做到 500ms 以内。问题是它一直缺少像“RTMP 推流”这样标准的接入协议,过去想跟 WebRTC 服务对接,必须自己搭信令服务,或者套用一套复杂的 WebSocket 协议。WHIP 解决推流接入,把建立 WebRTC 会话抽象成一次 HTTP POST:客户端提交 SDP Offer,服务端返回 201 和 SDP Answer,推流会话就建立起来了。WHEP 负责播放侧,拉流同样走 HTTP 资源,媒体流方向反过来。两者配套之后,WebRTC 第一次有了类似 RTSP/RTMP 的“统一协议入口”。

项目 RTSP RTMP WHIP WHEP
传输层 通常 UDP(RTP),兼容 TCP TCP 长连接 UDP(SRTP over ICE) 同左
加密能力 默认弱,可加扩展 RTMPS/RTMPE 用得少 DTLS-SRTP 强制加密 同左
浏览器原生播放 不支持 不支持 支持 支持
端到端延迟 0.2s ~ 1s 1s ~ 5s 0.3s ~ 0.8s 0.3s ~ 0.8s
NAT 穿透 依赖端口映射 依赖公网端口 ICE 自动打洞 同左
典型场景 监控、播放器拉流 推流、CDN 摄取 采集端 WebRTC 推流 浏览器低延迟播放

从这张表能看出,WHIP/WHEP 并不是在“所有维度”碾压 RTSP/RTMP。它解决的是 Web 端接入和低延迟体验这两个痛点,而 RTSP 在安防生态、RTMP 在推流工具链上的积累依然扎实。与其说“取代”,不如说它们补上了历史欠账。

2. WHIP/WHEP 原理拆解:为什么“发一个 POST”就能建立实时流

2.1 WHIP 推流的完整会话流程

WHIP 现在的正式编号是 RFC 9753,WHEP 也作为配套协议落地。整套流程比很多人想象中简单:

  1. 推流端创建 PeerConnection,生成 SDP Offer。Offer 里带有媒体描述、ICE candidates、DTLS 指纹等关键信息。
  2. 推流端把这个 SDP Offer 通过 HTTP POST 发到 WHIP 资源 URL,比如 http://127.0.0.1:8080/whip/live/test_whip ,请求头 Content-Type: application/sdp 。
  3. 服务端收到请求后创建 WebRTC PeerConnection,返回 201 Created 。响应体是 SDP Answer,响应头 Location 指向会话控制 URL。
  4. 双方开始 ICE 连通性检查,完成 NAT 穿透,然后做 DTLS 握手,媒体流通过 SRTP 从推流端推到服务端。
  5. 推流过程中遇到网络切换,客户端可以发送 PATCH 请求做 trickle ICE,或触发 ICE restart。推流结束直接 DELETE 会话 URL,服务端回收资源。

这个设计聪明在把信令和会话控制全部套进 HTTP 语义里,鉴权网关、负载均衡、日志审计都能直接复用现成 HTTP 设施。媒体面则完全交给 WebRTC,加密、降码率、重传都由标准协议栈处理。对于服务端开发者来说,接入 WHIP 相当于在 HTTP 层多了一个“POST 后建立推流会话”的路由。

2.2 WHEP 拉流:方向反了,套路不变

WHEP 的流程跟 WHIP 几乎对称,只是媒体流从服务端流向播放端。播放器向 WHEP 资源 URL 发起 HTTP POST,提交一个 SDP Offer,这个 Offer 通常可以是空 Offer,主要由服务端返回可用的媒体编码能力。服务端返回 201 Created 和 SDP Answer,后面就是标准 WebRTC 播放过程。

WHEP 最适合的场景是“浏览器里直接低延迟看流”。之前做网页直播,想要低延迟一般两条路:一条是走 WebSocket + MSE 自定义播放器,另一条是接第三方低延迟播放组件,两条路都费劲。WHEP 把“从服务端拉一路 WebRTC 流”变成了一个标准资源,网页播放器只要实现了 WHEP 客户端逻辑,就能像点开一个播放地址一样看流。服务端也不需要考虑“源是什么协议”,RTSP、RTMP、HTTP-FLV 这些入站协议都可以先变成内部媒体源,再靠 WHEP 出口转给浏览器。

一个简化版 SDP Offer 长这样:

v=0
o=- 8987654 2 IN IP4 127.0.0.1
s=-
c=IN IP4 0.0.0.0
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 96 97
a=mid:0
a=ice-ufrag:abcd
a=ice-pwd:efgh
a=fingerprint:sha-256 AA:BB:CC:DD:...
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1

里面的核心字段就三类:媒体编码信息、ICE 身份校验、DTLS 指纹。看到服务端返回 201 Created ,并且响应体里同样带 fingerprint、ice-ufrag 这些字段时,说明信令层面已经通了。

2.3 SmartMediaKit 的核心价值:做协议的“翻译官”

单独用 WHIP/WHEP,你还要解决“源从哪里来”的问题。摄像头大多只说 RTSP,OBS 推流大多默认 RTMP,浏览器又只想走 WebRTC,三者的沟通成本很高。SmartMediaKit 这类多协议网关的做法是在内部做一个统一媒体源管理:RTSP 拉流、RTMP 推流、WHIP 推流先把媒体落到同一个 MediaSource,播放侧再按需从 MediaSource 转成 WHEP、RTSP、RTMP、HTTP-FLV 等不同出口。

这样最大的好处是“入口和出口解耦”。你在接入层不用逼着设备升级协议,在分发层也不用为了不同播放端写多套对接。比如一台老款 IPC 摄像头只支持 RTSP,SmartMediaKit 把 RTSP 拉进来,浏览器播放端直接用 WHEP 看流就可以。这个过程中摄像头完全不知道 WHEP 的存在,浏览器也不需要装任何插件。真正的 SFU 产品,比如 Janus、LiveKit,也能做 WHIP/WHEP,但设计目标更偏向多人实时会话;SmartMediaKit 这类型网关更贴合直播和监控管道,按需拉流、录像、转封装这些能力用起来更顺手。

3. SmartMediaKit 实战:从 RTSP/RTMP 接入到 WHEP 浏览器播放

3.1 先搭环境:端口规划与 Docker 部署

我在本地验证时用的是 Docker 部署,命令大致如下:

docker run -d --name smartmediakit \
  -p 1935:1935 \
  -p 554:554 \
  -p 8080:8080 \
  -p 8443:8443 \
  your-registry/smartmediakit:latest

端口作用分别说一下:1935 是 RTMP 默认端口,收 OBS/FFmpeg 推流用;554 是 RTSP 默认端口,供 IPC/NVR 或 VLC 拉流;8080 是 HTTP 服务端口,WHIP/WHEP 的信令和管理接口一般挂在这里;8443 给 HTTPS 用,上线环境建议必须开。浏览器访问 WebRTC 业务时,很多时候要求 secure context,也就是 HTTPS 或者 localhost。如果只是本机联调, http://localhost:8080 能用;远程调试或生产环境,一定加一层 HTTPS 反代,否则某些浏览器会限制音视频相关能力。

注意:SmartMediaKit 不同版本的接口路径会有差异,我这里用 /whip/{app}/{stream} 和 /whep/{app}/{stream} 风格的地址举例,配置前以你实际部署版本的文档为准。

3.2 准备测试流:用 GStreamer 和 FFmpeg 自建 RTSP/RTMP 源

网上那些公开测试流地址不太靠谱,很多是内网或特定网络环境才能访问,真正练手最好自己生成测试源。GStreamer 自带 rtsp-server 的示例程序,可以快速起一路 RTSP 源:

git clone https://gitlab.freedesktop.org/gstreamer/gst-rtsp-server.git
cd gst-rtsp-server/examples
./test-launch "( videotestsrc ! video/x-raw,width=1280,height=720 ! x264enc tune=zerolatency ! rtph264pay name=pay0 pt=96 )"

执行后默认监听 8554 端口,地址是 rtsp://127.0.0.1:8554/test 。这路流虽然只是测试画面,但已经是标准 H.264 编码,能模拟不少摄像头场景。如果更想模拟 OBS 推流,用 FFmpeg 推 RTMP 也很方便:

ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
  -f lavfi -i sine=frequency=1000:sample_rate=48000 \
  -c:v libx264 -preset veryfast -tune zerolatency \
  -c:a aac \
  -f flv rtmp://127.0.0.1:1935/live/test_rtmp

然后在 SmartMediaKit 管理端添加“拉流代理”,把 rtsp://127.0.0.1:8554/test 拉进来,给它一个本地 streamId,比如 test 。这一步很关键,相当于让 SmartMediaKit 内部先缓存一路 RTSP 源,后续 WHEP 播放只是“消费”这个内部源。

3.3 验证 WHIP 推流入口:OBS 和 curl 都能测

先测 WHIP 推流入口是否正常。新版 OBS 的直播服务里直接有 WHIP 选项,服务地址填 http://127.0.0.1:8080/whip/live/test_whip ,有鉴权就填 Bearer Token,然后点开始推流。如果信令成功,SmartMediaKit 里会出现一路 test_whip 的流。

没有 OBS 的时候,也可以用 curl 验证 WHIP 端点:

curl -X POST \
  -H "Content-Type: application/sdp" \
  --data-binary @offer.sdp \
  http://127.0.0.1:8080/whip/live/test_whip

把 offer.sdp 换成上面那份简化 SDP 或者标准 SDP,正常会返回 201 Created ,响应体是 SDP Answer。需要强调一下,curl 只能证明 WHIP 的信令通路是通的,真正推媒体还需要支持 WebRTC 的客户端,它不会主动发送媒体包。

3.4 用 WHEP 在浏览器里拉流:从信令看到画面

浏览器端验证 WHEP 最方便,打开 SmartMediaKit 自带的 WebRTC 播放页面,填 http://127.0.0.1:8080/whep/live/test ,就能看到路测试画面。也可以从 RTMP 源验证,把 streamId 换成 test_rtmp ,地址变成 http://127.0.0.1:8080/whep/live/test_rtmp ,同样能播放。也就是说,我们先用 FFmpeg 推了一路 RTMP 流,然后在浏览器里用 WHEP 点播,整套链路就是“RTMP 采集端 + WebRTC 分发端”。

想再深入一点,可以在播放时打开 Chrome 的 chrome://webrtc-internals ,看 inbound-rtp 里的媒体信息。正常情况下能看到 mediaType: video 、 bytesReceived 在持续增长,编码格式是 H264 或 VP8 之一。延迟体感很明显,基本在几百毫秒级别,比 RTMP+HLS 的几秒延迟舒服得多。

3.5 常见接线矩阵:哪些源到出口值得打通

源 -> 出口 典型场景 建议程度
RTSP IPC -> WHEP 浏览器 监控上云、远程巡检、大屏看板 强烈建议
RTMP OBS -> WHEP 浏览器 活动直播、电商开播、低延迟观看 推荐
WHIP 采集端 -> RTMP CDN WebRTC 进源站,继续用老分发链路 看上游支持
RTSP 摄像头 -> RTMP 分发 老牌方案,接入简单但延迟偏高 存量保留
WHIP 采集 -> RTSP/RTMP 转出 用 WebRTC 做接入,继续沿用老生态 过渡期好用

这张矩阵的价值在于提醒我们:技术选型不是“哪个新用哪个”,而是“输入端按设备能力选,输出端按终端能力选”。

4. 常见问题与排查:部署 WHIP/WHEP 最容易踩的坑

4.1 能拿到 SDP Answer,但浏览器一直黑屏

这是最常见的现象,信令已经通了,媒体却出不来。多半是编码不兼容。WebRTC 场景下浏览器对 H.264、VP8、VP9 支持最好,而摄像头常见的 H.265/HEVC 在 Chrome、Firefox 里支持很差。如果 SmartMediaKit 只做转封装不做转码,H.265 源发给浏览器就会黑屏或只有声音没有画面。排查方法就是打开 chrome://webrtc-internals ,看 inbound-rtp 的 mimeType;看到 video/H265 之类,基本就是源头编码问题。另外 H.264 的 profile 和 level 过高也可能触发兼容问题,尽量用 baseline 或 main profile 测试。

提示:WebRTC 不等于“所有编解码器都支持”。H.265 在部分 Safari 版本里可用,但绝不能作为默认兼容目标。

4.2 WHIP 推流推不上去,或者频繁断开

多数情况下是 ICE 打洞失败。WHIP 信令建立后,媒体能不能通,取决于两端能不能用 ICE 找到一条可用路径。内网测试时经常没问题,host candidate 就够了;一旦跨公网,没有 STUN/TURN 就只能碰运气。建议是:自建 coturn 或者使用云厂商的 TURN 服务,在 SmartMediaKit 的 WebRTC 配置里把 STUN/TURN 地址填上。排查时看 WebRTC 日志,确认有没有一对 srflx 或 relay candidate 进入 selected candidate pair。只有 host candidate,且两端不在一张网里,那必然不稳定。

4.3 WHEP 延迟飘忽、码率越看越低

WebRTC 的 GCC 拥塞控制是“自适应降码率”的,链路丢包一上来,它会先把码率压下来保流畅,所以你会看到画面偶尔变模糊,但不会像 RTMP 那样明显卡顿。这不算故障,但能反映链路质量差。处理思路:一是检查网络丢包率,必要时换 TURN 路径或调整服务端部署位置;二是给流设定最大码率上限,防止突发带宽不足时拥塞控制反应过激;三是如果直播源本身码率很高,比如 4K 或高帧率,考虑用 Simulcast 或 SVC,让播放端按带宽选择合适层级。

4.4 多路并发一上来,CPU 和带宽双双告警

WebRTC 每路流都要做 SRTP 加解密、NACK 重传、拥塞控制,单路开销明显高于 RTMP 纯转发。压测时很容易发现 CPU 先顶不住。生产环境建议每路设置码率上限,打开 Simulcast/SVC 能力,让不同终端按需订阅,避免所有播放端都拿最全的流。横向扩展方面,多实例部署后按 streamId 维度做负载均衡,同一个流尽量集中在一个实例上,跨实例转发越少越好。SmartMediaKit 适合单机或中小规模,再往上就要引入集群架构。

现象 常见原因 检查项 应对
黑屏、无画面 编码不支持 / 源未转码 inbound-rtp mimeType 源转 H.264/VP8
WHIP 推不上流 ICE 打洞失败 selected candidate pair 配 STUN/TURN
卡顿、码率下降 丢包 / 拥塞控制生效 丢包率、码率走势 优化链路、限制码率
并发低、CPU 高 WebRTC 计算开销大 CPU、带宽利用率 限制码率 + 集群

5. 如果是我做选型:WHIP/WHEP 取代不了谁,但能补齐谁

5.1 不急着“全切”,先把入口和出口解耦

我的观点很明确:WHIP/WHEP 在未来三五年内不会彻底取代 RTSP/RTMP,而是补足 Web 原生低延迟这一块。RTSP 最大的依仗是安防设备生态,摄像头、NVR、指挥调度系统已经围绕它转了几十年;RTMP 最大的依仗是推流工具链,OBS、FFmpeg、CDN 摄取入口都把 RTMP 当默认项。你很难让存量摄像头直接推 WHIP,也很难让整个直播行业一夜之间抛弃 RTMP。更务实的做法是把 SmartMediaKit 这类网关放在中间,入口保持设备支持什么就用什么,出口按终端能力选择。浏览器用户给 WHEP,老播放器继续走 RTSP/RTMP,手机端该用 HLS 还是用 HLS。

5.2 几个可以直接套用的判断标准

  • 如果播放端以浏览器为主,对延迟要求低于 1 秒,优先 WHEP,不要再纠结 HLS。
  • 如果采集端以 OBS、手机推流 SDK 为主,先保留 RTMP 入口,再逐步试点 WHIP。
  • 如果是安防摄像头接入,入口坚持 RTSP/ONVIF,出口再考虑 WHEP。
  • 如果团队没有 WebRTC 基础,选 SmartMediaKit 这种封装好的网关,别从零实现信令和媒体栈,否则光 ICE 打洞和 DTLS 调试就能拖垮整个项目周期。

5.3 一条 30 分钟内跑通的最小验证路径

这里给一条可以直接照做的最小闭环:本机用 Docker 起 SmartMediaKit,用 GStreamer test-launch 起动一路 RTSP 源,在 SmartMediaKit 管理端添加代理拉流,然后浏览器访问 WHEP 地址播放。整个过程不涉及公网、不涉及摄像头采购,足以验证 WHIP/WHEP 的延迟和稳定性预期。之后再逐步叠加 OBS WHIP 推流、TURN 中继、多实例集群,看生产环境能跑到什么指标。

最后说点个人体会。我踩过最大的坑,是把“换个新协议”当成目标,其实最重要的是链路整体能不能达到业务要求。WHIP/WHEP 很好,但不是银弹;RTSP/RTMP 很旧,但生态壁垒还在。最聪明的用法是把它们放在 SmartMediaKit 这类网关后面,各自干各自擅长的事。你不需要在设备端和播放端之间强推同一套协议,只需要保证中间转换足够稳。

Logo

邀请您加入社区

更多推荐