
1. 先想清楚我们在讨论“取代”时到底在讨论什么前两天我把一台摄像头、一台笔记本编码器、两个手机浏览器和一台 SmartMediaKit 服务器串起来做了一组实验目标很简单回答那个被反复问的问题——WHIP/WHEP 到底能不能取代 RTSP、RTMP跑了几天之后我得出的结论不算中庸能但只会在它该取代的地方取代。这不是和稀泥而是因为这三套协议背后的生态位完全不同。RTSP 是监控和广电设备之间的“手拉手”协议RTMP 是 CDN 分发链路里的老黄牛WHIP/WHEP 则是浏览器原生实时互动时代的新入场者。它们看起来都在传视频实际上各自解决的问题差异非常大讨论取代之前必须先把这些差异拆开。先说清楚三个基本事实。第一RTSP 和 RTMP 都是上个时代的产物设计时根本没考虑“浏览器可以直接播放”这件事RTSP 依赖大量附加信令和多端口传输RTMP 虽然走单一 TCP 端口但播放端一直以来强依赖 Flash 或专用播放器。第二WHIP/WHEP 的本质不是新编码而是把 WebRTC 里复杂的 SDP 协商过程压缩成一条 HTTP 请求让任何支持 WebRTC 的浏览器都能以极低的门槛推流和拉流。第三SmartMediaKit 这类流媒体服务器做的事情是把几套协议统一收编成内部媒体流再按需分发出去所以它天然是观察这场“取代”的最佳试验台。这篇文章我会用我实际搭建 SmartMediaKit 的配置、推拉流命令、延迟测试数据和踩坑记录尽量把这个问题讲透。适合正在做低延迟直播、WebRTC 接入、安防流媒体平台或者在纠结要不要把现有 RTMP 架构改造成 WHIP/WHEP 的开发者看。1.1 两个新协议到底解决了谁的痛点WHIP 是 WebRTC-HTTP Ingestion ProtocolWHEP 是 WebRTC-HTTP Egress Protocol看名字就知道它们是一对一个负责推流一个负责拉流。它们做的事情可以理解成“给 WebRTC 装了一个极简 HTTP 门把手”。以前要在浏览器里推流最痛苦的不是编码而是信令。WebRTC 本身是一套点对点媒体传输体系两个端必须交换 SDPSession Description Protocol交换 ICE candidate处理 NAT 穿透维护 PeerConnection 状态。这些术语听着就头大实际调试起来更是能熬掉半条命。WHIP 把“创建 offer - 交换 - 拿到 answer”这一整套流程收敛成了一个 POST 请求你把本地生成的 SDP 作为请求体发给服务器服务器把 answer SDP 作为响应体返回推流通道就建立起来了。整个过程浏览器原生 API 就能跑不用引入任何 SDK。WHEP 同理拉流端拿到一个播放地址后通过一条 HTTP 请求和服务器完成协商然后直接消费 WebRTC 媒体流。对前端工程师来说这意味着不再需要搞清楚什么叫 DTLS什么叫 SRTP只需要知道 fetch 一个地址、拿回一个 answer、把媒体流怼给 video 标签。所以 WHIP/WHEP 真正解决的痛点是“浏览器到媒体服务器之间最后那一公里的接入成本”。以前这一公里要么靠 Flash要么靠 WebSocket 中转视频数据要么靠插件体验和工程成本都一言难尽。现在浏览器里直接跑 WebRTC延迟又是毫秒级这在交互直播、在线教育连麦、远程操控这些场景里是刚需。1.2 RTSP 和 RTMP 最核心的“家底”在哪里RTSP 活了这么多年最大的家底是安防设备生态。市面上绝大多数网络摄像头、NVR、视频编码器都把 RTSP 作为默认输出协议很多监控平台的标准接入规范也建立在 RTSP/RTP 基础上。它采用 C/S 模式信令走 RTSP媒体走 RTP传输可以选 UDP 或 TCP而且天然支持回放控制PLAY、PAUSE、TEARDOWN 这些命令就是干这个的。只要你想做摄像头接入、录像回放、PTZ 控制这类功能RTSP 依然是绕不开的存在WHIP/WHEP 目前根本覆盖不了这个领域。RTMP 的家底则在 CDN 分发链路和推流终端上。直播平台的老架构里OBS 推流到边缘节点、节点之间转推、源站接入绝大多数走的是 RTMP。虽然近年来很多平台把播放侧换成了 HTTP-FLV、HLS但“推流进入直播网络”这一步RTMP 依然是大规模使用的方案。大量硬件编码器、无人机遥控端、嵌入式设备把 RTMP 当作标准能力在做这个存量市场非常庞大。换句话说RTSP 统治着“设备到设备”的专网世界RTMP 统治着“采集端到分发网络”的传统互联网直播世界而 WHIP/WHEP 目前主要拿下的是“浏览器到服务器”的实时互动世界。三个世界有交集但远没到完全重叠的程度这就是我开头说“只能在该取代的地方取代”的原因。2. 协议对比浏览器、延迟、NAT穿越三个维度看差别要判断能不能取代最直接的办法是把它们放在同一个维度上量。我把 SmartMediaKit 作为共同的中转点让同一路视频分别走 RTSP、RTMP 和 WHIP/WHEP 拉流记录端到端延迟、接入复杂度、NAT 表现下面这张表是我这套环境的实测结果和长期经验值。维度RTSP/RTPRTMPWHIP/WHEP媒体协商方式多命令信令 多端口传输固定 TCP 端口握手简单一条 HTTP 请求完成 SDP 交换浏览器原生播放不支持不支持原生支持局域网端到端延迟约 80-200ms通常 1 秒以上约 100-300ms公网 NAT 穿透很麻烦需手动映射只需放行 TCP 端口但易被防火墙拦截内置 ICE/STUN/TURN 机制移动端支持需集成三方播放器需集成三方播放器或 SDKAndroid/iOS 现代浏览器均可跑回放与录像控制原生支持成熟不支持需额外设计不支持需额外设计硬件生态成熟度监控摄像头/编码器标配推流编码器/CDN 标配浏览器为主硬件少见首帧体验较快受缓冲影响非常快几乎点开即播2.1 最直观的差别在延迟与媒体协商方式延迟差异是最能给人直观冲击的部分。我在同一台服务器上用同一路 ffmpeg 编码的视频流分别验证RTSP 走 TCP 时延大约在 180ms 上下WHIP/WHEP 在 Chrome 里实测约 220ms这两者基本处于同一个量级都属于“实时”范畴。RTMP 转 HTTP-FLV 则通常在 1 到 3 秒主要瓶颈是播放器为防抖动设置的缓冲以及 RTMP 本身偏重稳定性的传输设计。媒体协商方式的对比更有意思。RTSP 的会话过程是先 OPTIONS 探测、DESCRIBE 拿描述、SETUP 建立传输通道、PLAY 开始播放一套组合拳打下来服务端还要在额外端口上跑 RTP/RTCP。RTMP 走 1935 端口握手之后在一个长连接里复用 chunk逻辑上简单但协议格式非常繁琐靠道听途说很难调通必须啃规范。到了 WHIP/WHEP 这里整个过程简化成人类一眼能懂的行为发一个 POST 请求拿到一个 SDP answer完事。打个比方RTSP 是去政务大厅办事每个窗口都要排队交材料RTMP 是拿了号在一个窗口把所有事办完但那个窗口的业务员规矩特别多WHIP/WHEP 是全程线上点一个按钮后台自己把事办了。这也是为什么大量前端团队接触 WebRTC 时容易一头雾水但封装一层 WHIP/WHEP 之后接入成本能大幅下降。2.2 真正决定选型的是应用场景而不是协议性能很多人对比协议时喜欢把延迟和吞吐量当成唯一标准我觉得这是误区。实际决定你选哪套方案的是你手里最核心的应用场景。如果你做的是监控和安防摄像头设备固定支持 RTSP平台还要做录像、回放、报警联动那 WHIP/WHEP 现阶段根本替代不了。最多是上层用 WHEP 做 Web 端低延迟预览底层接入依然是 RTSP。如果你做的是秀场直播、赛事直播这种传统 CDN 分发模式RTMP 推流 HTTP-FLV/HLS 播放的组合极其稳定整个链路都有非常成熟的运维体系没必要为了“新协议”三个字去重构。但如果你做的是在线教育、视频连麦、远程操控、网页端低延迟监控这类强互动场景用户就是用浏览器打开网页那 RTSP 和 RTMP 都差点意思而 WHIP/WHEP 几乎是为这个场景量身定做的。还有个容易被忽略的点是网络穿越能力。WHIP/WHEP 底层是 WebRTC自带 ICE 框架通过 STUN 服务器发现公网地址通过 TURN 服务器在点对点失败时中继流量所以在复杂的家庭网络、企业 NAT、4G/5G 移动网络下更容易连通。RTSP 要穿透 NAT 非常痛苦通常得给摄像头做端口映射或者依赖流媒体服务器主动从内网拉流RTMP 虽然只要放行一个 TCP 端口但在一些限制严格的办公网络里非标准端口经常被掐。别小看这一层很多项目跨公网联调时最后都被卡在网络穿透上。3. SmartMediaKit 是怎么同时扛下四路协议的光谈协议不落到服务器上没有意义。我选择用 SmartMediaKit 做这个对比实验主要是看中它比传统流媒体服务器的协议面更宽RTSP 拉流推流、RTMP 推流、HTTP-FLV/HLS 分发、WebRTC 推拉流都能接内部有一套统一媒体流转发机制。简单说它把输入协议和输出协议解耦了你从任何一路推进去都可以从任何一路拉出来这正好用来验证“一条输入多条输出”的场景。它的核心设计思路可以概括成三层接入层负责接收各种协议的推拉流请求内部媒体层是统一轨道抽象和流转发逻辑输出层再根据请求协议把媒体流重新封装分发。这样做的好处是上游新增一种采集协议不需要重写下游所有播放能力反之亦然。当你需要同时服务 RTSP 播放器、浏览器播放器和移动端 App 时这种分层的价值会非常明显。3.1 选择 WebRTC 承载 WHIP/WHEP 的底层逻辑WHIP/WHEP 只是信令层协议真正的媒体传输是 WebRTC。所以 SmartMediaKit 要支持它们本质上是要做好一个 WebRTC 网关。WebRTC 的核心能力是 P2P但服务器端介入时通常是 SFU 或网关角色把每个端过来的 RTP 包接收、重写、转发。这里有几个关键点。第一编解码器协商必须灵活。WebRTC 的 SDP 里会带 PTPayload Type映射、H264 profile-level-id、VP8/VP9 支持情况等一堆参数网关需要能正确解析并且把参数透传给其他端。实际项目里我踩过最深的一个坑就是 H264 的 profile 协商不一致推流端是 High Profile拉流端只支持 Baseline画面直接绿屏或黑屏。第二SIMULCAST 和 RTX 机制要处理好。分辨率高、码率大的推流端如果开了 Simulcast会同时发多路不同质量的流网关要么做多路转发要么做降级选择。第三WebRTC 的丢包重传机制和 JitterBuffer 策略会影响上行带宽占用网关在转发时要平衡延迟和稳定性。SmartMediaKit 把 WebRTC 网关跟其他协议模块放在同一个进程里意味着数据可以不经外部转码直接在内存里从 RTMP 流转换到 WebRTC 流。这个架构对延迟控制非常友好因为少了跨进程、跨网络的拷贝和封装开销。3.2 搭建和跑通一次真实的推拉流测试我把我这版的搭建方式写一下配置可能随着版本更新有变化但大体流程是一样的。服务端我用二进制包直接启动配置主体大致如下# 按官方仓库 examples 目录调整 [rtmp] addr :1935 [rtsp] addr :8554 [http] addr :8080 [rtc] enable true # 如果跑在NAT后面把这里改成服务器公网IP externalIP 1.2.3.4启动服务后先用 ffmpeg 推一路本地视频流到 RTMPffmpeg -re -stream_loop -1 -i test.mp4 \ -c:v libx264 \ -c:a aac \ -f flv rtmp://127.0.0.1/live/test然后从三个不同的口子同时拉流。第一个口子走 RTSP用 ffplay 播放ffplay -fflags nobuffer -analyzeduration 1000000 \ -rtsp_transport tcp rtsp://127.0.0.1:8554/live/test第二个口子走 HTTP-FLV也就是 RTMP 进来的流重新封装成 FLV 分发地址直接是 http://127.0.0.1:8080/live/test.flv用浏览器或 VLC 打开都能放。第三个口子走 WHEP我写了一个最简页面用浏览器原生 API 去拉流。这里要强调一个细节RTSP 端口我用的是 8554不是默认的 554因为很多服务器上 554 需要 root 权限容易被防火墙盯上开发环境用 8554 省事得多。RTMP 的 1935 是常规端口只要保持默认就行。WHEP 的地址格式一般是 http://127.0.0.1:8080/live/test/whep具体路径要看版本规则拉流端直接 fetch 这个地址拿 SDP answer。我拉流时的关键 JS 逻辑大概是这个思路const pc new RTCPeerConnection({ iceServers: [{ urls: stun:127.0.0.1:3478 }] }); const offer await pc.createOffer(); await pc.setLocalDescription(offer); const resp await fetch(whepUrl, { method: POST, headers: { Content-Type: application/sdp }, body: pc.localDescription.sdp }); const answerSdp await resp.text(); await pc.setRemoteDescription({ type: answer, sdp: answerSdp }); pc.ontrack (evt) { video.srcObject evt.streams[0]; };这段逻辑不复杂但很多新手会挂在本地 SDP 和远端 answer 的先后顺序上。要注意在 createOffer 之后必须先 setLocalDescription 拿到本地 SDP才能把这个 SDP 发出去应答回来之后还要 setRemoteDescription整个协商才算闭环。3.3 一次公网 NAT 穿透实验带来的意外收获初次公网联调时我图省事把 SmartMediaKit 直接跑在一台云主机上云主机安全组放行了所有 UDP 端口但浏览器那边一直黑屏PeerConnection 的 ICE 状态停在 checking 不往下走。排查链路是这样的先看信令层拉流页面已经成功拿到 answer SDP说明 HTTP 交互没问题再看媒体层浏览器控制台没有明显的报错最后打开 WebRTC 的 candidate 日志发现拉流端拿到的 answer 里candidate 全是云主机内网地址 10.x.x.x而浏览器尝试去连这个内网地址当然连不上。问题根源是SmartMediaKit 跑在 NAT 后面它给自己上报的候选地址是内网网卡地址STUN 没有拿到正确的公网映射。解决办法有两个一是把服务配置里的 externalIP 改成云主机公网地址让它在生成 SDP 时直接携带公网 candidate二是架设 TURN 服务在用户网络无法点对点穿透时走中继流量。我两个方案都试过发现 local 场景下 externalIP 配置最立竿见影而公网跨运营商、跨地域场景下 TURN 才是最稳妥的兜底方案。这个坑几乎人人会踩。尤其是在 Docker 里跑流媒体服务时容器网络默认是 NAT服务对外看到的网卡地址和宿主机公网地址完全不同不显式指定 externalIP 就一定会出现候选地址错误。我的习惯是无论本地还是云上只要部署环境存在 NAT就一定要检查服务产生的 SDP 里的 candidate 是不是可达地址。4. 从实测看延迟把参数调到可用级别WHIP/WHEP 被吹得最多的就是低延迟但“低延迟”三个字不是白来的。WebRTC 的优势是传输层实时性好但推流端、服务器、拉流端任何一个环节没调好延迟照样飙升。这一节我把测试方法和细节参数讲透。4.1 延迟到底能压到多少怎么量的我测延迟的方法很朴素但很准确推流端电脑屏幕放一个毫秒级计时器页面拉流端设备拍一张照片两边计时器差值就是端到端延迟。同一局域网环境下剔除首帧加载影响后的稳态延迟数据大概是这样的拉流方式稳态端到端延迟首帧时间说明RTSPTCP 拉流170-200ms约 300msffplay 播放缓冲调到最低RTMP 转 HTTP-FLV1200-2000ms约 800ms播放器默认缓冲影响很大WHEPWebRTC 拉流210-240ms约 400msChrome 原生播放注意这里说的“HTTP-FLV 延迟 1 秒以上”不代表所有 RTMP 场景都这样它在弱网下的抗抖动能力是通过缓冲区换来的。如果你把播放器的 buffer 调小也能把 HTTP-FLV 的延迟压到 500ms 左右但弱网下卡顿会明显加剧。而 WHEP 的延迟能稳定在 200ms 左右主要得益于 WebRTC 自身的 JitterBuffer 算法和丢包重传机制是动态适应的。如果你也想做一轮对比测试我的建议是严格控制变量同一台推流端、同一路由网络、同一个视频源、同一台服务器只切换拉流协议。测的时候不要把首帧时间和稳态延迟混在一起统计首帧时间受播放器初始化影响大稳态延迟才代表协议的实时性能。4.2 那些让延迟失控的隐藏因素参数调对之后延迟还可能被几个隐藏因素拉爆。第一个是编码器的 GOP 设置。如果推流端的关键帧间隔太大拉流端加入会话后必须等下一个关键帧才能出画面轻则黑屏几秒重则一直卡在缓冲。对低延迟场景我建议把关键帧间隔设置到 1 到 2 秒比如 30fps 下 GOP 给 30 或 60。第二个是 B 帧。WebRTC 的实时传输对帧顺序很敏感B 帧依赖后续帧才能解码在弱网下会显著增加延迟和花屏概率。ffmpeg 推流时我通常加-bf 0强制关闭 B 帧x264 编码参数里再补上-x264-params keyint60:scenecut0固定关键帧间隔。第三个隐藏因素是播放端自动协商的拥塞控制策略。WebRTC 的 GCCGoogle Congestion Control会动态调节码率如果推流端码率设置过高网络出现拥塞时它会经历一段下行码率退化过程画面会突然模糊延迟反而轻微上升等拥塞缓解后再尝试恢复。以前在固定码率场景下没有这种动态反馈很多从 RTMP 转过来的人会不适应这种“码率会自动降”的行为其实这是为了保住实时性。第四个因素是服务端的转发策略。如果服务器支持转码转码本身会引入几十到几百毫秒的额外延迟如果只是纯转发延迟基本可以控制在 10ms 以内。SmartMediaKit 这类支持协议转换但不强制转码的架构在延迟控制上天然有优势。我的建议是能不改编码就尽量不改编码转码留给你真正必须处理的时候。5. 关于“取代”的结论路线选择与避坑清单到这你可能已经发现了我的核心判断是WHIP/WHEP 的核心战场是“网页端实时互动”RTSP 的核心战场是“设备接入与监控”RTMP 的核心战场是“传统直播分发”。三者短期不冲突但长期看凡是需要在浏览器里实现实时视频的领域WHIP/WHEP 确实会逐步吃掉 RTSP 和 RTMP 的地盘。具体到业务决策我给你一套比较实用的判断方法。5.1 什么业务适合现在就切 WHIP/WHEP如果你的产品形态是用户用浏览器就能完成的视频操作那现在切换是性价比最高的时机。典型场景包括视频面试、在线医疗问诊、直播连麦、远程摄像头网页预览、大屏监控、无人驾驶远程操控等。这类业务有几个共同特点用户不能安装任何软件、延迟要求低于 1 秒、播放端可能是五花八门的终端设备。我经常给团队的建议是用 WHIP/WHEP 可以大幅降低前端的播放器集成成本。以前安卓端要缓存 RTSP 流得集成 VLC 或者 ExoPlayer 做一堆适配iOS 端又要考虑 HLS 的延迟问题现在只要用 WebView 打开一个 WHEP 页面原生播放能力直接被浏览器接管了这在“只说给内部做工具”的项目里尤其爽前端一个人就能扛起来。SmartMediaKit 这类服务器在这里的角色就是一个统一的媒体入口采集端不管是摄像头推送 RTSP还是编码器推送 RTMP进到服务器之后浏览器用户统一用 WHEP 拉流。这样既能继续吃存量设备又能给用户提供实时互动的体验。5.2 什么业务暂时不切也不要焦虑如果你做的是广电级的直播转播、大规模赛事、秀场直播传统的 RTMP 推流加 CDN 分发链路已经非常成熟我确实不推荐为了追新而追新。RTMP 生态的好处是每个环节都有完整的监控、限流、转码、录制方案而这些能力在 WHIP/WHEP 的世界里还在慢慢积累中。你在做监控存储与回放这种偏后端能力的需求时也暂时不需要过多考虑 WHIP/WHEP。RTSP 的 PLAY/PAUSE/SEEK 控制非常成熟录像回放和按时间定位播放都有现成机制WebRTC 不是为文件回放设计的要在 WHIP/WHEP 之上实现真正的录像控制得自己在外层补一套信令逻辑性价比不高。还有一类大规模观众场景要提醒你WebRTC 虽然低延迟但它是为点对点或小规模互动设计的大规模分发如果要靠服务器逐路转发带宽和性能成本会爆炸。真正的大规模低延迟直播通常还是要回到 CDN 或 MESH 方案WHIP/WHEP 可以在入口和出口处做接入中间分发层依然需要传统架构。5.3 我在实践中踩过最深的三个坑第一个坑是浏览器 H264 编解码兼容性。WHIP 推流天然支持 VP8/VP9/H264但不同浏览器支持情况完全不一样Chrome 对 H264 的支持受限于授权Firefox 在部分平台只支持 VP8/VP9iOS Safari 只硬解 H264软解 VP8 性能很差。我的解决办法是把 H264 作为首选编码同时服务端做编解码能力协商在 SDP 层面保证拉流端能正确解析。如果你不做协商就把 H264 强制推给 Firefox黑屏是大概率事件。第二个坑是云服务器公网部署时的 candidate 配置。我在 3.3 里说过Docker 容器和 NAT 环境里的流媒体服务如果不显式配置公网 IPSDP 里的 candidate 全是内网地址。这里有个更隐蔽的分支情况即便你配了 externalIP如果云主机没有放行对应 UDP 端口范围浏览器侧仍然会在 STUN 协商阶段失败。排查时建议先用 WebRTC 的 ICE candidate 日志确认双方地址可达性再检查安全组和防火墙别一上来就怀疑代码。第三个坑是嵌入式设备推流的兼容性。有人问我“ESP32 这类板子能不能直接支持 WHIP”现实是嵌入式端做 WebRTC 集成非常吃力码率、内存、音视频同步都很难做。实际项目中更好的做法是让嵌入式设备继续走 RTMP 推流到 SmartMediaKit服务器转成 WHIP/WHEP 给浏览器播放。这样既保住了嵌入式开发成本又让 Web 端获得了低延迟体验。我在测试时踩过的是这类设备推流时码率波动大服务端如果不做码率缓冲WebRTC 侧会出现间歇性卡顿给推流加上平滑缓冲参数之后明显好转。5.4 回到标题的问题我的判断绕了一圈最后还是那句话WHIP/WHEP 不会把 RTSP、RTMP 彻底打死但会吃掉一大块“实时网页互动”的戏份。RTSP 在监控和广电设备侧的地位短期内依旧稳固RTMP 在存量 CDN 和采集端生态里还能服役很多年但新一代业务只要面向浏览器选择 WHIP/WHEP 基本都是少走弯路的方向。SmartMediaKit 这类能同时在四套协议之间自由转换的服务器会是这个过渡期里最实用的润滑剂——你不用一次性推翻老架构只需要在最需要实时互动的接入点上逐步把它们切到 WHIP/WHEP 上。我在实际调试里最大的体会是别被新协议的光环冲昏头也别被老协议的惯性锁死。判断的依据永远是你自己的用户在哪里打开你的视频如果他们都在浏览器里那就放心往 WHIP/WHEP 靠。最后再分享一个小技巧如果你也想快速验证一条流的多协议表现不要到处找公开的测试地址自己用 ffmpeg 往本地 SmartMediaKit 推一路循环视频三分钟就能得到一条稳定可控的测试流比在公网上一遍遍试别人的源舒服太多。