视频预览链路三件套: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 服务(生产必做,开机自启)
bat
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 也可跑几路)。
防火墙放行:
bat
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=1935
1.3 配置(config.ini)
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 Boot application.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.js stashBuffer、改子码流、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,默认即可用)
yaml
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 无配置文件,行为全由命令行参数决定。本项目推流命令逐参数说明:
bat
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(探测时用)。
排障辅助:
bat
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 拉到稳定源,前端预览出现循环画面。
四、三者协作的端到端示例(本地模拟)
bat
:: 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 |
| 真实环境是否需要 | 必须 | 不需要 | 不需要 |
| 本地模拟是否需要 | 必须 | 必须 | 必须 |