最近在做一套流媒体接入网关,客户需求非常典型:无人机要 GB28181 回传,园区摄像头要 RTSP 拉流,还有一拨人非要在浏览器里低延迟看画面。与此同时,社区里讨论最热的是 WHIP、WHEP 和 MoQ 这些新协议。热搜归热搜,真正落到项目里,我发现大部分时间还是花在 RTSP、RTMP、GB28181 上。这篇文章聊聊我的真实感受:拥抱新协议没问题,但老协议的基本功,才是流媒体工程师最该做扎实的地方。
很多人觉得新协议出来后,老协议就该退场了。实际做项目时完全不是这么回事。我给自己也算了一笔账:这个网关从拿到需求到能跑通端到端,真正让项目卡壳的,全是老协议的兼容性细节;而新协议反而在标准化之后,接入起来轻松得多。所以我想把这些经验写出来,尤其适合正在做视频平台、安防接入、无人机直播这类项目的朋友参考。
1. 新协议到底新在哪:先把 WHIP、WHEP、MoQ 说清楚
1.1 WHIP/WHEP:WebRTC 的标准化接插件
先说 WHIP,全称 WebRTC-HTTP Ingestion Protocol(RFC 9728),2025 年初正式发布。它解决的是 WebRTC 推流接入不统一的问题。以前你想让浏览器或者 OBS 往自己的流媒体服务器推 WebRTC 流,得自己定义一套信令交换流程,协议里只说用 SDP 协商,但怎么交换、交换完怎么办,完全百花齐放。WHIP 把这件事收敛成了"HTTP POST 一个 SDP Offer,服务器回 200 OK 带 Answer",后面就按 WebRTC 的 ICE 和 DTLS 流程走。就这么简单,但正因为简单,它成了事实标准。
WHEP 是 RFC 9729,和 WHIP 对称,解决拉流侧的问题。浏览器请求一个 WHEP 地址,先 HTTP 拿 SDP,然后建立 WebRTC 会话接收媒体。这个模型对前端开发极度友好,一个 fetch 请求就完成了接入,剩下的交给播放器。
我在项目里实测下来,WHIP/WHEP 最大的价值在于"接插件化"。服务端只要实现了这两个协议,前端和 OBS 之类的工具就能开箱即用,不用再纠结私有信令的兼容问题。但要注意,WHIP/WHEP 只标准化了接入方式,媒体分发层面还是要靠 SFU 或者网关去打通,它本身不负责把流推到千家万户。
1.2 MoQ:换一个传输底座搞直播
MoQ 是 Media over QUIC 的缩写,IETF 正在推进的草案,目前还没转正,但热度已经很高。它的核心是抛弃 TCP 或者 UDP+RTCP 这套老组合,直接在 QUIC 上传输媒体对象。QUIC 是 HTTP/3 的底层协议,有 0-RTT 连接、多路复用、单条流丢包不影响其他流这些特性,所以 MoQ 在低延迟分发上天生有优势。
为什么业界关注 MoQ?因为现有直播分发的痛点非常明确。RTMP/HTTP-FLV 走 TCP,遇到丢包会重传,延迟和卡顿容易被放大;WebRTC 虽然低延迟,但每个连接都是独立会话,在大规模分发场景下 SFU 压力很大,而且 WebRTC 的缓存、录制、转码支持并没有标准化。MoQ 想做的是"媒体也能像数据一样缓存和分发",CDN 节点可以缓存媒体对象,用户从最近的节点拉流,延迟能控制在亚秒级,又不像 WebRTC 那样重。
不过我这里得说句实在话:MoQ 目前生产环境落地还少,客户端库成熟度也不够,我接触的大多数项目还在观望。但它的传输理念是对的,尤其是面向大规模直播分发,很可能是下一个阶段的主流方向。
1.3 新协议的边界:什么场景下暂时靠不住
这部分是我踩过坑之后才想明白的。WHIP/WHEP 好归好,但它依赖 WebRTC 那一整套 ICE/DTLS/SRTP 体系,对网络环境有要求。我在一个客户的园区网络里调试,UDP 被限制得厉害,ICE 候选选不通,结果还是切回 RTSP over TCP 才稳定。这类问题在政企网络、专网环境里非常常见,不是你代码写得对就能绕过去的。
MoQ 的问题在于生态。它现在还在草案阶段,规范变来变去,我用过几个早期实现,API 差异很大,根本不敢直接上生产。另外 MoQ 解决的是"分发"环节,但源的接入、设备的兼容、历史录像的调度,它一概不管。也就是说,新协议更像"大脑"和"新血管",但四肢仍然需要老协议去接。
一句话总结新协议的价值:它们在"接入标准化"和"传输效率"上做了重要突破,但并没有覆盖流媒体全链路。这就引出了今天的核心问题——老协议为什么还丢不掉。
2. 为什么老协议依然是生产环境的压舱石
2.1 海量摄像头和无人机:GB28181、RTSP 是设备的出厂语言
先说硬件侧。全球范围内的 IP 摄像机、NVR、执法记录仪,出厂支持的协议主要是 RTSP 和 GB28181,这不是厂商不想升级,而是整个安防行业过去十几年的存量太大了。一个中型园区可能有几百路摄像头,换设备周期是按年算的。你不可能为了用 WebRTC 把所有摄像头都换一遍。
GB28181 更是特殊,在公共安全视频监控领域是硬性要求,平台侧必须能接入国标设备。热词里提到的大疆经纬 M300 RTK、M200 系列、御 Mavic 2 行业版,这些无人机本身就内置 GB28181 能力。我做过一个应急指挥项目,无人机起飞后直接把画面通过 GB28181 推到指挥中心平台,再从平台转发到大屏和手机端,整个过程根本不需要在飞机上装额外软件。
RTSP 的情况类似,海康、大华这些设备的取流地址几乎成了行业暗号。海康是rtsp://user:pass@ip:554/Streaming/Channels/101,大华是rtsp://user:pass@ip:554/cam/realmonitor?channel=1&subtype=0,只要做安防接入,这些格式必须烂熟于心。安卓端想缓存 RTSP 流,Media3/ExoPlayer 可以直接播,但要做录像、做本地缓存,很多还是靠 RTSP 转 HLS 再缓存,走的还是老协议管线。
2.2 RTMP 的推流统治力:从 OBS 到 ESP32
再看 RTMP。它虽然是 Adobe 时代的老协议,但直播推流端的地位至今没有被真正撼动。OBS 默认推流协议是 RTMP 还是 RTMPS?我在多个直播平台配置里看,RTMP 依然是主流底座。演唱会直播、游戏直播、电商直播,大量源站接收的都是 RTMP 流,因为编码器、采集端的支持最成熟。
还有一个更极端的例子:ESP32 推 RTMP。我在业余项目里用 ESP32-S3 + OV2640 摄像头做网络摄像头,跑 RTMP 推流非常稳定,内存占用和 CPU 开销都在可接受范围。为什么不用 WebRTC?ESP32 的性能跑 DTLS/SRTP 那套太重了,WebRTC 的 ICE 协商在这么弱的芯片上也容易出问题。RTMP 基于 TCP,逻辑简单,推流几百 Kbps 的低分辨率视频完全够用,几十块钱的硬件成本就能搞定一个"会说话的摄像头"。这种场景下,RTMP 不是妥协,是最合适的选择。
2.3 调试、排障、可观测性的成熟度差着量级
这一点是我最想强调的。新协议的调试链路太长了,拉个 WebRTC 流要去看 SDP、ICE candidate、DTLS 握手、SRTP 密钥协商,任何一个环节出问题,报错信息都晦涩难懂。但 RTSP、RTMP、GB28181 不一样,几十年的沉淀下来,工具链非常完备。
ffprobe一条命令就能看 RTSP 流完整信息,ffplay直接播放;- Wireshark 对 RTP/RTCP、SIP、RTMP chunk 流的解析非常成熟,过滤器一抓一个准;
- GB28181 的 SIP 信令可以通过抓包软件直接看到 REGISTER、INVITE、MESSAGE 的交互过程。
我在现场排查问题的时候,大多是靠 ffprobe 和 Wireshark 先定位到老协议这一侧,反而 WHIP/WHEP 出了问题,经常要同时看服务端日志、WebRTC 统计、ICE 网络状态,排查链路长很多。这也是老协议在工程上不可替代的隐性价值。
3. 新老协议不是替代关系,是协同关系
3.1 我常用的混合接入架构
在实际项目里,我几乎从不做"只支持新协议"或者"只支持老协议"的方案。我常用的架构是"统一接入 + 协议网关 + 多态输出"。接入层把各种来源的流汇聚进来:摄像头走 RTSP、国标平台走 GB28181、网页/APP 推流走 WHIP/RTMP。汇聚之后,内部统一成一种中间格式,再按需输出给不同终端:浏览器用 WHEP、移动端用 HLS 或 HTTP-FLV、传统播放器用 RTSP。
这样做的好处是终端侧不用关心源是什么。你的前端只需要 WHEP 的播放地址,至于后面是无人机、海康摄像头还是手机推流,网关层全部处理掉。我管这个叫"翻译层",它让新协议和老协议各司其职。
3.2 协议转换到底在转什么
很多人以为协议转换是"把 RTSP 文件转成 WebRTC 文件",这是误区。流媒体协议转换本质上分两层:封装层转换和编码层转换。
封装层转换最常见。RTSP 和 WebRTC 的媒体面其实都是 RTP,但 RTSP 是裸 RTP,WebRTC 是 SRTP(加密的 RTP)。GB28181 更特殊,它的 RTP 里装的是 PS 封装(MPEG2-PS),得先把 PS 解出来还原成 H.264/H.265 的 Access Unit,再按 WebRTC 的 RTP 负载格式重新封装。这个过程不需要转码,CPU 开销很低,是网关首选方案。
编码层转换就费资源了。比如 GB28181 设备推了 H.265,但浏览器 WebRTC 解码支持参差不齐,这时候就得转码成 H.264。我一个项目中用 NVIDIA 硬编码器做这个转换,单路 1080p 的转码延迟能压在几十毫秒,但 CPU 转码就非常吃力。所以设计协议网关时,一定要先算好哪些链路只需要转封装,哪些链路必须转码。
3.3 一个完整接入链路:无人机 GB28181 → WHEP 浏览器播放
我举一个自己实际做过的链路,帮助你把上面这些串起来。
前端是无人机,通过 GB28181 往平台注册并推流。平台侧收到 SIP INVITE 后,会回带 SDP 的 200 OK,协商媒体端口,无人机随后用 RTP 把 PS 封装好的 H.264 视频推到平台媒体服务器。媒体服务器收到后,解 PS 封装,得到 H.264 裸流,再交给转封装模块按 WebRTC 的格式重新打包,同时把加密所需的 SRTP 参数与 WHEP 会话关联起来。用户浏览器打开页面,通过 WHEP 发起请求,拿到 SDP Answer,握手成功后即可低延迟播放无人机画面。
整个过程里,无人机侧只认识 GB28181,浏览器侧只认识 WHEP,中间的一切翻译工作都由网关完成。这个链路跑通之后,客户非常满意,因为前端开发不用懂任何 GB28181 的细节,只需要一个 WHEP 的 URL 就行。但反过来说,如果没有网关对 GB28181 的深度支持,这个需求根本做不出来。所以新协议和老协议,从来都是协作关系,不是二选一。
4. 实操:把老协议跑通、跑稳的关键细节
4.1 十分钟搭好 RTSP/RTMP 测试环境
如果你刚接触这块,我建议直接上 mediamtx(原来叫 rtsp-simple-server)。它是单个二进制文件,支持 RTSP、RTMP、WebRTC、SRT 等多种协议,非常适合本地测试和学习。下载解压后改个配置就能跑,默认端口 8554 给 RTSP、1935 给 RTMP。
我常用的测试方法是这样。先用ffmpeg把一个本地视频文件循环推给 mediamtx 的 RTMP 端口:
ffmpeg -re -stream_loop -1 -i test.mp4 -c:v libx264 -preset veryfast \ -tune zerolatency -c:a aac -f flv rtmp://localhost:1935/live/test推上去之后,用 VLC 打开rtsp://localhost:8554/test就能直接播放。这个链路跑通了,说明 RTMP 推流、RTSP 拉流、服务器转封装都正常,后续再往上叠 GB28181 和 WHIP/WHEP 就有底气了。
想用 GStreamer 搭 RTSP 服务器做更深入的测试,可以用gst-rtsp-server做开发,也可以直接用命令行起一个简单的测试源:
gst-launch-1.0 videotestsrc pattern=ball ! video/x-raw,width=1280,height=720 ! \ x264enc tune=zerolatency ! rtph264pay name=pay0 pt=96 ! rtspclientsink \ location=rtsp://localhost:8554/gst当然这个命令里rtspclientsink需要你安装对应的插件,实际直接用 mediamtx 会更省心。我建议你先把手上的工具跑熟,再去啃协议细节。
4.2 摄像头 RTSP 取流地址与参数详解
RTSP 取流最常踩的坑就是地址格式。海康的地址规则是rtsp://用户名:密码@IP:554/Streaming/Channels/101,注意最后一个101,1 表示通道 1,01 表示主码流,02 就是子码流。网上流传的很多海康取流地址写的是ch01_sub,那是老版本的支持。大华是rtsp://用户名:密码@IP:554/cam/realmonitor?channel=1&subtype=0,subtype=0 主码流,subtype=1 子码流。
用户权限问题也经常遇到。很多摄像头默认禁用了 RTSP 鉴权或者只允许管理员取流。现场排查时先用 VLC 打开地址试一下,如果是 401 Unauthorized,优先检查账号密码和摄像头"网络→集成协议"里的 RTSP 鉴权设置。
还有一个细节是 RTSP 的 TCP/UDP 模式。默认大多数播放器会用 UDP 传输 RTP,但在跨网段、防火墙严格的场景下,UDP 经常被丢包或者直接禁止。这时候可以强制走 TCP,在 ffplay 里加一个参数:
ffplay -rtsp_transport tcp -i "rtsp://user:pass@ip:554/Streaming/Channels/101"服务端收到 SETUP 消息中的 TCP 请求后,会把 RTP 包交错封装在 RTSP 的 TCP 连接里传过来。这个参数在项目联调里几乎天天用,建议直接记住。
4.3 RTMP 推流服务器搭建与推流参数选择
RTMP 推流服务器我推荐 SRS,开源、活跃度高,一条 Docker 命令就能拉起来:
docker run --rm -p 1935:1935 -p 1985:1985 -p 8080:8080 \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5SRS 默认配置就能接收 RTMP 推流,地址是rtmp://localhost:1935/live/livestream。如果你只想快速验证 push,SRS 官方还有公网测试地址rtmp://demo.ossrs.net/live/livestream,不过公网地址受网络环境影响,我建议还是本地搭一个实测。
推流参数选择直接影响延迟和画质。如果你做的是低延迟场景,记得加-tune zerolatency,关掉 B 帧,关键帧间隔设短一点(2 秒以内)。以 OBS 推流为例,码率控制用 CBR 或 VBR 都可以,但关键帧间隔务必设小,否则播放端首屏等待时间会很难看。RTMP 默认的 buffering 时间也比较大,服务器端如果开了 GOP cache,延迟会额外增加 0.5~1 秒。做低延迟直播建议关掉 GOP cache,或者用 SRS 的低延迟配置模板。
聊到 ESP32 推 RTMP,我的经验是用 ESP32-S3 + OV2640,帧率 15fps、分辨率 VGA、H.264 硬编码,推 800Kbps 到本地 SRS 完全稳定。要特别注意 ESP32 的 OV2640 输出的是 JPEG,做 H.264 编码要么用芯片的 JPEG 流先软编,要么选支持直接输出 H.264 的摄像头模组,否则 CPU 会扛不住。
4.4 GB28181 接入与语音对讲的注意点
GB28181 是 SIP + RTP + PS 封装的组合,接入流程比 RTSP 复杂。设备上电后会向平台的 SIP 服务器发送 REGISTER 请求,平台收到后回复 401 带认证,设备带上认证信息再 REGISTER 一次,注册成功。之后设备周期性发心跳,平台通过目录查询拿到设备列表。
拉流的核心是 INVITE 流程。平台向设备发 INVITE,SDP 里描述你要接收的媒体类型、编码格式、接收端口。设备回 200 OK 之后就开始往平台的媒体端口推 RTP/PS 流。这个流程里最容易出的问题是 NAT。设备在公网,平台在内网,设备回的 SDP 里带的媒体地址可能是内网地址,双方 RTCP 和 RTP 都到不了。解决方法是平台侧配置公网映射,或者设备侧支持在国标配置里设置"本机 IP"为公网地址。
语音对讲是 GB28181 接入里比较高级的功能。我们做过一个项目,指挥中心要和现场摄像机对话。这时候平台先给设备发一个双向的 INVITE,SDP 里同时协商上行和下行音频流。音频编码通常用 G.711A、G.711U 或 G.722,设备只支持其中一种,平台必须有对应的转码能力。真正跑起来之后,对讲延迟一般控制在 500ms 以内才算可用,如果延迟过大,优先检查是否经过了额外的转码链路,以及音频的 jitter buffer 是否设置得过大。
5. 常见问题与排查技巧实录
5.1 高频问题速查表
下面是我在多个项目里遇到的高频问题,整理成速查表,方便你对照排查。
| 问题现象 | 可能原因 | 排查方法 |
|---|---|---|
| RTSP 拉流 401 | 账号密码/权限不对或鉴权方式不匹配 | 检查摄像头集成协议设置,看是否启用了 RTSP 鉴权 |
| RTSP 有画面但很卡 | 网络丢包,UDP 被限制 | 强制-rtsp_transport tcp对比测试 |
| 海康只出子码流不出主码流 | 地址里的通道编号写错 | 确认/Streaming/Channels/101和102分别对应主/子码流 |
| RTMP 推流延迟越来越大 | 服务器开启了 GOP cache 或播放缓冲过大 | 关闭 GOP cache,调低播放端 buffer 时长 |
| GB28181 注册成功但拉不到流 | NAT 导致 RTP 端口不通 | 在设备/平台两侧核对媒体端口映射,抓包看 RTP 是否到达 |
| GB28181 语音对讲只有单边声音 | 双向流协商失败或音频编码不匹配 | 看 SDP 里 audio 方向和编码类型,确保两端一致 |
| WHIP 推流偶发黑屏 | 首帧关键帧未及时到达 | 设置推流端关键帧间隔为 1~2 秒,确认服务端没有丢弃关键帧 |
| WHEP 播放几分钟后花屏 | UDP 丢包导致 RTP 序列空洞 | 查看 WebRTC 统计,考虑切到具备丢包重传的 SFU 或走 TCP 候选 |
这个表不可能覆盖所有情况,但排查思路是一致的:先确定是信令问题还是媒体问题,再看是网络问题还是编码问题。分而治之,能省下大量时间。
5.2 排查链路与工具
我的排查习惯遵循一个固定链路。第一步确认源端是否有流,比如摄像头是否在出流,用 VLC 或 ffplay 直接打开源地址测试;第二步看协议交互是否正常,Wireshark 抓包,RTSP 就看 OPTIONS/DESCRIBE/SETUP/PLAY 的响应码,GB28181 就看 SIP 的 REGISTER 和 INVITE 事务;第三步看媒体传输,RTP 包是否到达目标端口,负载类型和时间戳是否正确。
工具方面,ffprobe 是我最常用的侦察兵。一条命令能看到编码格式、分辨率、帧率、SPS/PPS 等关键信息:
ffprobe -v error -show_streams -show_format rtmp://localhost:1935/live/testWireshark 用于协议细节,我习惯在过滤器里直接写rtsp || rtp || rtcp,或者在 GB28181 场景写sip || ps。如果怀疑是 RTP 丢包,可以加一个统计列,专门看 RTP sequence number 是否有跳变。Android 端缓存 RTSP 流这种需求,如果只是本地播放,直接 Media3 就能搞定;要是为了断网离线看,我一般建议服务端把 RTSP 转 HLS,客户端走 HLS 缓存,体感会稳很多。
5.3 我在项目里总结的三条经验
第一,老协议的新兼容层,投入产出比最高。RTSP 的 TCP 模式、GB28181 的 NAT 兼容、RTMP 的低延迟调参,这些“边缘细节”看似不起眼,但都是客户现场的高频问题。把这一层做好,项目的稳定性会有一个质的提升。
第二,新协议要选对场景上。WHIP/WHEP 适合浏览器端低延迟互动,MoQ 未来适合大规模分发,但别指望它们解决设备接入和存量兼容。我在项目里的原则是:能用老协议稳住的,不乱上新;新协议能带来明显体验提升的,果断用,但要留好降级回老协议的开关。
第三,协议网关的价值被低估了。很多时候客户说"我要 WebRTC",实际诉求只是"浏览器里低延迟看监控"。你不需要把整个系统推翻成 WebRTC,只需要在媒体服务器前面加一层网关,把 RTSP/GB28181 翻译成 WHEP 即可。这样既满足了体验,又把改动控制到最小。
说回我自己,现在每次拿到流媒体项目,我还是会从 RTSP、RTMP、GB28181 的接入稳固性入手,把底子打牢,再考虑加 WHIP、WHEP 和 MoQ 这些新成员。这不是守旧,是因为我知道,真正让系统撑住业务、撑住现场复杂环境的,往往不是最热门的协议,而是那些最扎实的基本功。