视频预览链路三件套:ZLMediaKit · MediaMTX · FFmpeg 完全指南
摄像头视频预览实现教程:从原理到落地(ZLMediaKit+ flv.js+ Spring Boot):
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/163018250
它们在本项目里的角色与链路
浏览器无法直接播放摄像头 RTSP 流,必须“服务端转协议 + 前端播放器”。本项目链路:
海康摄像头 RTSP (或 本地模拟的"假摄像头") │ RTSP 拉流 ▼ ZLMediaKit (MediaServer.exe) ← 把 RTSP 转封装成 HTTP-FLV(链路核心) │ HTTP-FLV ▼ 浏览器 flv.js 播放 (Vue2 设备页 / 大屏首页详情弹窗) === 本地模拟时多出的两环 === ffmpeg 循环推流 ──RTSP推流──▶ MediaMTX(RTSP服务) ──▶ ZLMediaKit (假摄像头) (8554/cam1) (80)| 软件 | 真实环境作用 | 本地模拟额外作用 |
|---|---|---|
| FFmpeg | 一般不直接用 | 把本地test.mp4循环推成 RTSP,充当“假摄像头” |
| MediaMTX | 一般不直接用 | 极简 RTSP 服务器,接收 ffmpeg 推流,提供rtsp://127.0.0.1:8554/cam1 |
| ZLMediaKit | 把摄像头 RTSP 转 HTTP-FLV,链路核心 | 同上,只是源来自 MediaMTX |
项目实际运行参数:ZLMediaKit 监听80端口,MediaMTX 监听8554(流名cam1),FFmpeg 推流到该源。前端最终播放地址形如http://127.0.0.1/live/dev_6.live.flv。
一、ZLMediaKit(MediaServer.exe)
1.1 软件介绍
- 定位:国产开源流媒体服务器(C++,GitHub:
ZLMediaKit/ZLMediaKit),主打“高性能、低延迟、多协议互通”。 - 核心能力:
- 协议互通:RTSP / RTMP / HLS / HTTP-FLV / WebRTC / SRT 间可互相转封装或转码。
- 拉流代理(本项目关键):
addStreamProxy主动拉取外部 RTSP/RTMP 源,转成多种格式对外提供,相当于“协议翻译官”。 - 按需拉流:无人观看时依
streamNoneReaderDelayMS自动断流;也支持 Hook 回调(如on_stream_none_reader)让业务系统决定何时关流。 - 完备 HTTP 管理 API(
/index/api/*):建流、查询、踢人、媒体列表等。
- 性能:纯 C++ 单进程,转封装(不转码)时 CPU 占用极低,普通服务器可支撑数十路甚至上百路子码流;开启转码才需评估 GPU/CPU。
- 为何选它:① 单 exe、零依赖、Windows 部署极简;② 原生 HTTP-FLV 与 flv.js 完美契合(1~3s 延迟,无插件);③ 标准 RTSP 接入,兼容海康/大华/宇视等多品牌;④ 同一套基础设施可平滑升级 WebRTC(<1s)做实时联动。
- 对比:相较 nginx-rtmp(配置繁琐、FLV 弱)、SRS(偏 Linux 服务化),ZLMediaKit 在 Windows 单机、轻量嵌入场景更顺手。
1.2 安装
方式一:预编译包(推荐)
GitHub Release 下载 Windows 构建(
windows.zip/ZLMediaKit_win64)。解压到固定目录(避免中文/空格),如
D:\tools\ZLMediaKit\:ZLMediaKit\ ├── MediaServer.exe # 核心主程序 ├── config.ini # 配置文件(必须) ├── ssl.p12 / default.pem# 证书(HTTPS/WebRTC 才需要) └── www\ # 内置测试页
方式二:源码编译(需自定义功能时):依赖 CMake、VS2019+、OpenSSL;git clone --recursive→cmake→ 编译。一般无需。
方式三:注册 Windows 服务(生产必做,开机自启)
nssm install ZLMediaKit "D:\tools\ZLMediaKit\MediaServer.exe" nssm set ZLMediaKit AppDirectory "D:\tools\ZLMediaKit" nssm set ZLMediaKit Start SERVICE_AUTO_START nssm start ZLMediaKit :: 状态/停止/卸载:nssm status|stop|remove ZLMediaKit confirm也可用“任务计划程序”建“计算机启动时运行”指向
MediaServer.exe -c config.ini。
验证:前台cd /d D:\tools\ZLMediaKit && MediaServer.exe,浏览器访问http://127.0.0.1:80/index/api/getServerConfig?secret=xxx返回 JSON 即成功。
系统要求:Windows 7+/Server 2008+,2 核 4G 起步(纯转封装 1 核 2G 也可跑几路)。
防火墙放行:
netsh advfirewall firewall add rule name="ZLM-HTTP" dir=in action=allow protocol=TCP localport=80 netsh advfirewall firewall add rule name="ZLM-RTSP" dir=in action=allow protocol=TCP localport=554 netsh advfirewall firewall add rule name="ZLM-RTMP" dir=in action=allow protocol=TCP localport=19351.3 配置(config.ini)
[api] secret=xxx # 调所有 /index/api/* 必须带此密钥;务必强随机,且与 application.yml 的 zlm.secret 完全一致。 [http] port=80 # HTTP-FLV 播放 + API 端口。80 被 IIS/系统占用就改 8080,并同步改 zlm.http-port 与前端地址。 [rtsp] port=554 # ZLM 自身 RTSP 服务端口(本项目是"主动拉"摄像头,一般不冲突) [rtmp] port=1935 [rtc] externIP=192.168.1.100 port=8000 # WebRTC 才需要,HTTP-FLV 方案暂不用 [hook] enable=1 on_stream_none_reader=http://127.0.0.1:8080/system/device/stream/none-reader # 高级控制:无人观看自动关流、播放鉴权。也可仅靠 streamNoneReaderDelayMS。 [general] streamNoneReaderDelayMS=20000 # 无人观看 20s 后自动断流,按需拉流核心。与 Spring Bootapplication.yml映射(两端必须对齐):
| config.ini | application.yml (zlm.*) | 说明 |
|---|---|---|
[api].secret | zlm.secret | 必须完全一致 |
[http].port | zlm.http-port | 必须完全一致 |
| — | zlm.host | 后端调 ZLM API 的地址(内网 IP) |
| — | zlm.play-host | 返回给浏览器的播放地址(跨网/域名时填公网可达地址) |
| — | zlm.app | 流应用名,本项目live,生成/live/xxx.flv |
host与play-host分离设计:后端与浏览器不同网络时,后端用host访问 API,把play-host(公网域名)返回前端播放,二者可不同。
1.4 指令 / API 详解
① 添加拉流代理
GET /index/api/addStreamProxy ?secret=<secret> &vhost=__defaultVhost__ &app=live &stream=dev_1 # 建议用 deviceId 作流名 &url=rtsp://admin:pwd@192.168.1.64:554/Streaming/Channels/102 &rtp_type=0 # 0=TCP 拉流(抗丢包,推荐) 1=UDP 返回: {"code":0,"data":{"key":"__defaultVhost__/live/dev_1"}}② 生成的播放地址
HTTP-FLV: http://<IP>:80/live/dev_1.live.flv ← 本项目前端用这个 HLS: http://<IP>:80/live/dev_1/hls.m3u8 (需 enable_hls=1) WebRTC: http://<IP>:80/index/api/webrtc?app=live&stream=dev_1&type=play③ 关闭代理(释放资源)
GET /index/api/delStreamProxy?secret=<secret>&streamKey=live/dev_1注意参数名:代码里用
streamKey,ZLM 文档常写key。本项目验证脚本直接调 ZLM 用key=live/dev_6;后端调 ZLM 用streamKey,需统一。
1.5 常见问题
| 现象 | 原因 / 解决 |
|---|---|
| 80 端口起不来 | 被 IIS / SVCHOST 占用 → 改config.ini [http].port=8080,同步改zlm.http-port |
| 前端黑屏一直加载 | ①F12 看 flv 请求是否 200 ②ZLM 是否真拉到 RTSP(看日志/getMediaList)③RTSP 账号密码/通道码流是否正确 |
| addStreamProxy 返回非 0 | 流已存在(可忽略,幂等)或 RTSP 不可达,用 VLC 打开该 RTSP 验证摄像头侧 |
| 延迟 >3s | 关 flv.jsstashBuffer、改子码流、rtp_type=0;仍不够升级 WebRTC |
| 局域网能看外网看不到 | 摄像头/ZLM 在内网,需 Nginx 反代或端口映射 |
1.6 使用场景示例
- 生产:设备页点“视频预览” → 后端按
deviceId查bus_device.video_url(海康 RTSP)→ 调addStreamProxy建流 → 返回http://IP:80/live/dev_x.live.flv→ flv.js 播放;关闭弹窗调delStreamProxy释放。 - 本机模拟:见第四节一键脚本。
二、MediaMTX(mediamtx.exe,原 rtsp-simple-server)
2.1 软件介绍
- 定位:极简、单文件、零依赖流媒体服务器(Go,GitHub:
bluenviron/mediamtx,原名 rtsp-simple-server)。 - 核心能力:支持 RTSP / RTMP / HLS / WebRTC / SRT / UDP-MPEGTS;开箱即用(无配置即监听默认端口);多路流按路径区分(
/cam1、/cam2)自动创建;内存占用极低(<50MB)。 - 在本项目角色:仅本地模拟时用,当“假摄像头的 RTSP 服务端”——接收 FFmpeg 推来的循环视频,对外提供
rtsp://127.0.0.1:8554/cam1供 ZLMediaKit 拉取。真实环境有真摄像头时不参与。 - 为何选它:比 ZLMediaKit 更轻、配置更少,专门解决“需要一个 RTSP 源”;与 FFmpeg 组合是业界标准模拟方案。对比 Live555/Wowza,单文件、跨平台、无授权费。
2.2 安装
- GitHub Release 下载
mediamtx_vX.X.X_windows_amd64.zip,解压得单文件mediamtx.exe,放到D:\tools\mediamtx\。 - (可选)同目录放
mediamtx.yml自定义;不放在则全默认。 - 系统要求:Windows 任意较新版本,几乎不挑机器。
- 启动验证:
D:\tools\mediamtx\mediamtx.exe→ 日志出现RTSP server listening on :8554即成功(此时还没推流,cam1会在 FFmpeg 推流时自动出现)。 - 其他平台:Linux/macOS 下
./mediamtx;Docker:docker run --rm -p 8554:8554 bluenviron/mediamtx。
2.3 配置(mediamtx.yml,默认即可用)
rtspAddress::8554# RTSP 监听地址:端口readTimeout:10s# 推流端断流后多久认为流结束# authMethods: [basic] # 可选鉴权# readUser: user# readPass: pass# rtmpAddress: :1935 # 也可开启 RTMP/HLS/WebRTC本项目约定:流路径固定cam1(rtsp://127.0.0.1:8554/cam1),与 FFmpeg 推流 URL、设备videoUrl三处必须一致;8554 被占用改:8555并同步另两处;它只提供 RTSP 源,HTTP-FLV 由 ZLMediaKit 生成。
2.4 指令 / 用法详解
MediaMTX 主要作接收端,配合 FFmpeg 推流:
- 推流地址格式:
rtsp://<host>:<port>/<stream-path>,本项目rtsp://127.0.0.1:8554/cam1。 - 多路:换路径即可(
/cam2)。也支持 RTMP 推流与 HLS 输出,按需使用。
2.5 常见问题
| 现象 | 解决 |
|---|---|
| ZLM 拉不到 cam1 | 先确认 mediamtx 在跑、8554 监听;再确认 ffmpeg 推流已启动(cam1 按需出现,没人推就没有) |
| 8554 被占用 | 改mediamtx.yml的rtspAddress,同步 ffmpeg 推流 URL |
| 推流后源无画面 | 用ffprobe验证;检查 ffmpeg 进程是否存活 |
2.6 使用场景示例
- 本地无摄像头调试:MediaMTX 当 RTSP 源服务器 + FFmpeg 把测试片循环推成
cam1,让整条预览链路(不含真实硬件)完整可验证。
三、FFmpeg(ffmpeg.exe)
3.1 软件介绍
- 定位:业界事实标准开源音视频处理命令行工具集(C,GitHub/FFmpeg),含
ffmpeg(转码/推流)、ffprobe(探测)、ffplay(播放)。 - 核心能力:格式互转、转码、剪辑、滤镜、截图、推/拉流,支持
file/rtsp/rtmp/http/udp/srt等海量协议。 - 在本项目角色:仅本地模拟时用,把
test.mp4循环推成 RTSP 流模拟“摄像头持续出画面”。真实环境摄像头自带 RTSP 输出,不经 FFmpeg。 - 为何选它:免费、跨平台,与 MediaMTX 组合是标准模拟方案;
-stream_loop -1无限循环完美模拟 7×24 监控。对比 OBS(偏 GUI 直播)、GStreamer(偏管线编程),FFmpeg 命令行最适合脚本化无人值守推流。
3.2 安装
- 官网 https://ffmpeg.org/download.html → Windows 选gyan.dev或BtbN构建的
ffmpeg-*-full_build包。 - 解压得
bin\:ffmpeg.exe(推流)、ffprobe.exe(探测)、ffplay.exe(播放)。本项目实际C:\tools\ffmpeg\bin\,文档示例D:\tools\ffmpeg\bin\。 - 加 PATH(推荐):把
bin加入系统Path,之后任意命令行直接ffmpeg/ffprobe;或脚本写绝对路径。 - 验证:
ffmpeg -version输出版本即成功。 - 系统要求:Windows 任意版本;
-c copy不转码时几乎零 CPU。准备测试片test.mp4(几秒短片便于观察循环,H264+AAC 最稳)。
3.3 配置
FFmpeg无配置文件,行为全由命令行参数决定。本项目推流命令逐参数说明:
ffmpeg -re -stream_loop -1 -i test.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/cam1| 参数 | 含义 |
|---|---|
-re | 按文件原始速率读取(实时推流;不加会瞬间推完导致流中断) |
-stream_loop -1 | 输入循环次数,-1= 无限循环(模拟持续监控) |
-i test.mp4 | 输入文件 |
-c copy | 不转码直接拷贝流(最省 CPU;要求源封装兼容 RTSP) |
-f rtsp | 强制输出封装为 RTSP |
rtsp://127.0.0.1:8554/cam1 | 推流目标(MediaMTX 地址 + 流名) |
变体:-c copy因封装不兼容失败时改转码:-c:v libx264 -c:a aac。常用附加:-an(去音频)、-vf scale=1280:720(缩放)、-b:v 1M(限码率)、-rtsp_transport tcp(探测时用)。
排障辅助:
ffprobe -rtsp_transport tcp -hide_banner rtsp://127.0.0.1:8554/cam1 :: 期望看到 Stream #0:0: Video: h264 ... 和 Stream #0:1: Audio: aac ...3.4 常见问题
| 现象 | 解决 |
|---|---|
| 画面卡住 / 不循环 | 确认带-stream_loop -1;确认test.mp4可解码 |
| “Protocol not found” | 构建不含 RTSP muxer,换 gyan.dev 完整构建 |
| CPU 占用高 | 用-c copy避免转码;转码时降分辨率/帧率 |
3.5 使用场景示例
- 假摄像头:
ffmpeg -re -stream_loop -1 -i test.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/cam1→ ZLMediaKit 拉到稳定源,前端预览出现循环画面。
四、三者协作的端到端示例(本地模拟)
:: 1) 启动 MediaMTX(RTSP 源服务器) start mediamtx.exe :: 2) 启动 ZLMediaKit(HTTP-FLV,端口80) start MediaServer.exe -c config.ini :: 3) FFmpeg 把测试片循环推成 cam1 源 start ffmpeg -re -stream_loop -1 -i test.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/cam1 :: 4) 设备 videoUrl 设为:rtsp://127.0.0.1:8554/cam1 :: 5) 前端点"视频预览" → 看到循环画面 :: 验证 ZLM 接口(不依赖前端): curl "http://127.0.0.1:80/index/api/addStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=dev_1&url=rtsp://127.0.0.1:8554/cam1&rtp_type=0" :: 浏览器打开 http://127.0.0.1/live/dev_1.live.flv 应能看到流 curl "http://127.0.0.1:80/index/api/delStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&streamKey=live/dev_1"五、排障总览(三件套联动)
- 先确认源(最底层):
ffprobe rtsp://127.0.0.1:8554/cam1能否看到 h264 轨 → 验证 FFmpeg 推流 + MediaMTX。 - 再确认转换层:ZLM 进程在不在、80 端口是否监听、
getServerConfig是否返回 JSON → 验证 ZLMediaKit。 - 最后确认播放层:浏览器 F12 看
*.flv请求是否 200、flv.js 是否报错 → 验证前端。 - 端口冲突优先查 80(IIS)和8554(多个 MediaMTX 实例)。
- secret 必须全链路一致:
config.ini [api].secret=application.yml zlm.secret= 后端调 API 携带值。
六、三件套“介绍 / 安装 / 配置”对照表
| 维度 | ZLMediaKit | MediaMTX | FFmpeg |
|---|---|---|---|
| 一句话 | RTSP→HTTP-FLV 转换核心 | 轻量 RTSP 源服务器(模拟用) | 视频转码/推流工具(模拟用) |
| 安装复杂度 | 中(解压+配 ini+服务化) | 低(单 exe 即跑) | 低(解压+加 PATH) |
| 配置文件 | config.ini(必须仔细配) | mediamtx.yml(默认即可) | 无(纯命令行参数) |
| 关键配置点 | secret、http.port、streamNoneReaderDelayMS | rtspAddress、流路径 cam1 | -re -stream_loop -1 -c copy -f rtsp |
| 真实环境是否需要 | 必须 | 不需要 | 不需要 |
| 本地模拟是否需要 | 必须 | 必须 | 必须 |