HTML5无法原生播放RTSP流,必须通过中转服务将RTSP转为WebRTC或HLS;WebRTC延迟低(

HTML5 本身不支持 RTSP,必须转流
浏览器原生 标签只认 HTTP(S) 协议下的 MP4、WebM、HLS(m3u8)、DASH 等格式,rtsp:// 地址直接扔进去会静默失败——既不报错也不播放。这不是兼容性问题,是协议层根本不通。所以“HTML5 播放 RTSP”这个需求,本质是“把 RTSP 流转成浏览器能解的流”,而 WebRTC 是目前延迟最低、体验最接近原生 RTSP 的方案之一。
主流可行路径:RTSP → WebRTC(需中转服务)
纯前端无法完成 RTSP 解析和 WebRTC 封包,必须依赖一个中间服务做拉流、解码、重封装。常见组合是:FFmpeg 或 GStreamer 拉 RTSP,再通过信令服务器(如 mediasoup、Janus、LiveKit)推 WebRTC。关键点不是“怎么写 HTML”,而是“怎么搭这条链路”:
-
FFmpeg命令示例(拉 RTSP 并推到 mediasoup 的 WebRTC ingest):ffmpeg -i "rtsp://192.168.1.100:554/stream" -c:v libx264 -b:v 1000k -f webm -content_type video/webm http://localhost:3000/ingest - 信令服务必须暴露 WebSocket 接口供前端调用,前端用
RTCPeerConnection接收 SDP offer/answer - 浏览器端不能直接连 RTSP 源,所有 SDP 交换、ICE 候选收集都走 JS 控制,不是自动发现
- 若用
Janus,需启用videoroom插件并配置rtspbridge;mediasoup则需搭配mediasoup-client和自定义 worker 逻辑
替代方案对比:HLS vs WebRTC
如果对延迟不敏感(可接受 5–30 秒),用 HLS 更轻量:
-
FFmpeg实时切片:ffmpeg -i "rtsp://..." -c:v libx264 -hls_time 2 -hls_list_size 5 -hls_flags delete_segments out.m3u8 - 前端只需
(需服务端支持 CORS + MIME 类型为application/vnd.apple.mpegurl) - HLS 无信令、无 ICE、无 SDP,调试简单,但首屏慢、卡顿恢复弱、不支持音频/视频单独订阅
- WebRTC 延迟可压到 500ms 内,支持动态码率、NACK/PLI 重传,但部署复杂、NAT 穿透失败时需 STUN/TURN
容易被忽略的坑
很多项目卡在看似无关的环节:
立即学习“前端免费学习笔记(深入)”;
- RTSP 源若用 H.265 编码,
FFmpeg转 WebRTC 时必须软解(-c:v libx264)或硬编支持,否则浏览器无法解码——RTCPeerConnection收到帧但video元素黑屏 - 信令服务器返回的 SDP 中,
a=setup:actpass和a=connection: new必须匹配客户端生成的 offer,否则 ICE 连接卡在checking - Chrome 对
RTCPeerConnection的addTransceiver调用顺序敏感:必须先 add,再 setLocalDescription,否则触发InvalidStateError - 内网 RTSP 源地址(如
rtsp://192.168.x.x)不能直接暴露给公网用户,中转服务必须部署在能访问该 RTSP 源的网络环境里
真正难的不是写几行 JS,而是让 FFmpeg 不崩、信令不丢包、ICE 穿透成功、编码参数和浏览器能力对齐——每个环节出问题,现象都是“没画面”,但原因可能差十层。










