HTML5的video标签原生只支持HLS、MP4等格式,并不直接支持RTSP协议,因此很多监控项目都需要先解决协议转换问题,才能进一步实现录制和回放。本文围绕网页端播放RTSP、录制视频流、历史录像回放三个功能点,介绍几种常见的技术方案,并分析各自的优缺点,帮助大家根据项目实际情况做出选型。
浏览器为什么不直接支持RTSP,播放环节怎么解决
RTSP是流媒体传输控制协议,底层通常搭配RTP传输数据,常见端口为554。而浏览器出于安全和架构考虑,早已移除了对RTSP的原生支持,Chrome、Firefox、Edge都无法通过video标签直接打开rtsp地址。所以要实现HTML5播放RTSP,必须有一个中间层把RTSP流转成浏览器能识别的协议,常见的就是HLS、HTTP-FLV或者WebRTC。
目前主流的做法有三种。第一种是使用流媒体服务器做转协议,比如ZLMediaKit、SRS、mediamtx(原rtsp-simple-server)等开源服务,把摄像头的RTSP流拉过来,同时输出HLS或WebRTC给网页。第二种是部署现成的RTSP转WebRTC网关,延迟可以做到几百毫秒以内,非常适合需要实时查看的场景。第三种是在客户端本地方案,比如通过本地安装的服务程序拉流转成HTTP-FLV,再用flv.js在前端解码播放。
以mediamtx为例,配置非常简单,启动后它会读取配置文件中的路径定义,把摄像头流转成多协议输出:
# mediamtx.yml 配置示例
paths:
cam1:
source: rtsp://admin:password@192.168.1.64:554/h264/ch1/main/av_stream
sourceOnDemand: yes
配置完成后,网页端可以直接通过WebRTC地址(如http://服务器IP:8889/cam1)或HLS地址播放。HLS方案兼容性最好但延迟通常在几秒到十几秒,WebRTC方案延迟低但对服务器和浏览器要求稍高。播放环节选型会直接影响后面录制功能的实现方式,这一点需要在架构设计阶段就想清楚。
HTML5页面播放RTSP流时,录制功能有哪几种实现方式
先回答标题里的问题:能录,但不能靠video标签本身。HTML5没有提供直接录制远程视频流的API,录制必须借助MediaRecorder、服务端转存或者专门的采集手段。下面分几种典型路径来说明。
第一种是服务端录制,也是最推荐的方案。既然流媒体服务器已经在拉流转码,顺手把流写入磁盘即可。以FFmpeg为例,一条命令就能把RTSP流保存为MP4文件,同时保留给网页播放的输出:
# 边转码边录制,录制文件按时间分片 ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.64:554/stream \ -c copy -f segment -segment_time 600 \ -reset_timestamps 1 -strftime 1 /data/rec/%Y-%m-%d_%H-%M-%S.mp4
这种方式的优点是录制质量无损(如果直接copy不转码)、不依赖用户是否打开网页、可以7×24小时运行。缺点是需要服务器有足够的存储和带宽。实际项目中通常由后端服务管理录制任务,提供开始录制、停止录制的接口,前端只负责调用。
第二种是前端使用MediaRecorder录制。MediaRecorder可以捕获canvas、video元素或者MediaStream的内容。如果流是通过WebRTC播放的,可以直接拿到MediaStream对象进行录制:
// 获取WebRTC播放产生的媒体流后进行录制
const stream = videoElement.srcObject;
const chunks = [];
const recorder = new MediaRecorder(stream, { mimeType: "video/webm;codecs=vp8" });
recorder.ondataavailable = (e) => {
if (e.data.size > 0) chunks.push(e.data);
};
recorder.onstop = () => {
const blob = new Blob(chunks, { type: "video/webm" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "record.webm";
a.click();
};
recorder.start();
// 停止录制
// recorder.stop();
这种方案实现简单,用户点一下就能把正在看的画面保存下来。但局限也很明显:只能录制用户打开页面期间的内容,页面关了录制就断了;录出来的一般是webm格式,部分播放器兼容性一般;录制质量受网络抖动影响。如果流是通过flv.js或HLS播放的,无法直接拿到MediaStream,需要用captureStream方法从video元素间接获取,性能开销会更大。
第三种是所谓的录屏思路,即通过getDisplayMedia让用户选择屏幕或窗口进行录制。这属于通用录屏能力,和RTSP流本身没有绑定关系,一般不推荐作为监控录制的主方案,但在调试或者取证类需求中可以作为一种补充手段。
录制完成后的历史回放功能如何设计与实现
录制只是第一步,真正的监控类项目通常还要求能按时间检索、点播历史录像。回放功能的核心是录像文件的组织和检索,服务端需要有清晰的存储结构和索引。
推荐的存储结构是按通道和日期分目录,文件名包含精确时间戳,同时用数据库或JSON索引记录每个文件的起止时间。这样前端传入通道ID和时间段,后端就能快速定位对应的文件列表:
// 后端接口示例:根据时间段返回录像文件列表
// GET /api/record/list?channel=cam1&start=1717000000&end=1717086400
app.get("/api/record/list", async (req, res) => {
const { channel, start, end } = req.query;
// 查询索引表,返回匹配时间段的文件及偏移信息
const files = await db.query(
"SELECT file_path, start_time, end_time FROM record_index WHERE channel = ? AND start_time <= ? AND end_time >= ? ORDER BY start_time",
[channel, end, start]
);
res.json({ code: 0, data: files });
});
回放播放可以直接复用播放环节的架构:把录像文件交给流媒体服务器,以点播方式输出HLS或HTTP-FLV,前端用video或flv.js播放即可。如果需要拖动进度条精确定位,MP4文件配合HTTP Range请求就能实现秒级seek;如果录制时分片较小,还可以在分片之间做无缝拼接播放。
此外还有几个工程细节值得注意。一是存储清理策略,监控录像会持续膨胀,必须配合定时任务按保留天数删除过期文件,并同步清理索引。二是录制中断处理,网络抖动导致断流后应自动重连并开新的录制分片,避免单个文件损坏影响整段录像。三是格式选择,如果回放需要在各端浏览器顺畅播放,建议录制时输出标准H.264编码的MP4,避免使用浏览器支持不佳的编码格式。
总结一下:HTML5本身不能直接播放RTSP,更不能直接录制RTSP,需要借助流媒体服务器做协议转换;录制功能推荐在服务端完成,前端MediaRecorder适合用户手动截取片段的场景;回放功能依赖良好的录像分片和索引设计,配合HTTP点播即可实现完整体验。按照这个思路搭建,播放、录制、回放三个功能就能在一套架构下稳定运行。
HTML5 RTSP网页录制视频回放修改时间:2026-08-31 07:17:01