1. 内容整体设计与思路拆解
先说说我为什么会在 Windows 上折腾这么一套东西。做流媒体的人基本都遇到过这种尴尬:手里拿的摄像头、采集卡、或者老旧的监控设备,推流协议清一色是 RTSP,后端播放平台或者CDN却只认 RTMP。两边鸡同鸭讲,直接对接根本推不上去。平时在 Linux 上干这活很顺手,可一旦项目临时落在 Windows 环境,或者现场只有一台 Windows 工控机,你就得想办法在 Windows 上把这套链路搭起来。这篇文章就是我实际在 Windows 上搭建 nginx-rtmp 服务器,把 RTSP 摄像头流拉下来再转成 RTMP 推流的完整记录,包括原理、配置、踩坑和排查方法。
先说清楚这套方案解决的核心问题:它不是一个播放器,也不是一个转码软件,而是一个“协议中转站”。RTSP 源产生 H.264/H.265 编码的视频流,通过 nginx-rtmp 模块接收后,重新封装成 RTMP 协议,再推给下游的流媒体服务或播放器。这里的重点在“转封装”,不是“转码”——音视频编码格式基本保持不变,只是把传送协议从 RTSP 换成 RTMP,所以对 CPU 的消耗很小,延迟也能控制在比较低的水平。
适用人群很明确:需要快速在 Windows 本机或服务器上搭一个临时的、轻量的 RTMP 分发节点的人,包括嵌入式开发者、监控系统集成工程师、直播推流调试人员,也包括刚刚接触流媒体协议栈的学生。整个方案只依赖开源软件,不需要购买商业授权,配置起来也不像某些重型流媒体服务那样动辄几百行配置。如果你已经对 RTSP、RTMP 这两个协议有一定印象,但还没亲手搭过服务端,这篇文章可以直接照着抄。
为什么偏偏选 nginx-rtmp,而不是其他方案?我自己对比过几个主流选择:用 FFmpeg 单独做转推,虽然能实现 RTSP 拉流再推 RTMP,但它只解决“一路转一路”的问题,没有服务端的分发能力,多个播放端同时拉取同一路流时,每个端都要独立占用一次转推进程,资源浪费明显。而 nginx-rtmp 具备服务端的流接收、回源、分发功能,一个入口进来,下游所有播放端都能从同一个流名拉流。另一方面,Windows 上也有商业的流媒体服务,但架设成本和授权限制往往比开源方案高出一截。综合对比下来,nginx-rtmp 在轻量、可控、免费这三个维度上最适合作为中转节点。
注意:这个方案的核心是“协议转换”而非“转码”,如果源流编码格式是 H.265,而你下游的播放器不支持硬解 H.265,那么即使 RTMP 链路通了,画面也可能黑屏。这个问题在后面会专门讨论。
2. 环境准备与工具选型解析
2.1 Windows 下的 Nginx 与 RTMP 模块
Nginx 本身是跨平台的,官方提供 Windows 版本,但官方 Windows 版本默认不包含 RTMP 模块。所以我们要用的是社区维护的、已经编译好了 RTMP 模块的 Windows 版本。这里需要注意,不要跑到官网下载二进制包就完事,必须找到带rtmp模块的编译版本。我用的是某开源社区维护的 Windows 编译包,版本号跟随 Nginx 主线更新,解压后目录里就能看到nginx.exe,同时conf目录下带有完整的示例配置。
判断一个 Nginx 编译包是否包含 RTMP 模块,有一个特别简单的方法:打开命令行,进入解压后的目录,执行:
nginx.exe -V输出的编译参数里面,如果能看到--with-http_rtmp_module这一行,就说明这个版本自带 RTMP 支持。我见过有人下载了官方原版 Nginx,折腾半天写了 RTMP 配置,启动后直接报unknown directive "rtmp",其实就是这个原因。这一步是基础中的基础,一定先确认。
2.2 RTSP 拉流工具的选择:FFmpeg 还是专用工具
把 RTSP 流转成 RTMP,需要在服务器上有一个“拉流器”。最通用、最不容易出问题的方案就是 FFmpeg。它的 RTSP 解封装能力非常成熟,支持 TCP/UDP 传输模式切换,也支持各种 RTSP 鉴权方式。而且 FFmpeg 是纯命令行工具,在 Windows 上不需要安装,解压之后直接用ffmpeg.exe就行。
也有人问,能不能让 nginx-rtmp 自己直接拉 RTSP 流?很遗憾,nginx-rtmp 模块本身只做 RTMP 协议的接收和分发,它没有内置 RTSP client 的能力。你可以在它的配置里写pull指令,但pull的语法只支持从另一个 RTMP 服务器拉流,不支持rtsp://这样的 URL。换句话说,拉流这步必须借助外部工具。FFmpeg 是最顺手的选择,因为我们可以用一条命令行完成“读 RTSP、输出 RTMP”两个动作,中间还可以顺手做编码参数微调。如果你习惯用 OBS 或者 VLC 来做拉流也不是不行,但这两个都偏向交互式操作,不适合做无人值守的服务端。
如果现场有多个摄像头,也可以一次性在 FFmpeg 命令里用循环方式逐个处理,但更稳的做法是每个摄像头单独启一个 FFmpeg 进程,这样一路流出问题不会拖累其他路。具体的进程管理方式我后面会讲。
2.3 目录结构与基础准备
我建议把整个工具包放在一个固定的、无空格的路径下,比如D:\StreamServer,里面分子目录:nginx、ffmpeg、conf、logs。虽然理论上配置文件和工具放哪里都能运行,但 Windows 下路径有空格时,在命令行里折腾转义特别容易出错,尤其是脚本化启动的时候。无空格的路径能减少非常多不必要的麻烦。
需要准备的软件清单如下:
| 组件 | 用途 | 获取方式 |
|---|---|---|
| nginx(含 rtmp 模块) | RTMP 服务端 | 社区预编译包 |
| FFmpeg | RTSP 拉流、转封装、推 RTMP | 官方编译版本 |
| VLC 或其他播放器 | 验证 RTMP 流可播放 | 常规安装 |
| 命令行工具 | 测试 RTSP 源连通性 | Windows 自带 |
把 FFmpeg 解压后,最好把它所在的bin目录加到系统环境变量 Path 里,这样后续写脚本可以直接调用ffmpeg,不用每次拼完整路径。不需要把 Nginx 加入系统服务,保持手动启动就好,方便调试。
3. 核心配置与实操步骤拆解
3.1 Nginx RTMP 配置文件的完整示例
RTMP 模块的配置和 HTTP 配置是独立的两个块。Nginx 默认读取conf/nginx.conf,我们在里面同时配置http块和rtmp块。下面是我实测可用的最小化配置:
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { root html; } } } rtmp { server { listen 1935; chunk_size 4096; application live { live on; record off; } } }这里需要解释几个关键点。listen 1935是 RTMP 协议的默认端口,下游播放器在拉流时如果不带端口,默认就是 1935。chunk_size这个参数控制 RTMP 分块的大小,设成 4096 是比较稳妥的值,太大可能在某些播放器出现延迟抖动,太小又会增加 CPU 开销。application live定义了一个挂载点,名字可以随便起,但客户端推流和拉流的地址都会包含这个名字。live on表示开启实时流模式;record off很重要,如果不关掉,默认情况下 nginx-rtmp 会把收到的流录制成 flv 文件存到硬盘上,一段时间下来磁盘会被写满。
HTTP 块里的/stat页面是 nginx-rtmp 提供的在线状态监控,通过浏览器访问http://localhost/stat可以看到当前有几路流、每路流的带宽、连接数等信息,调试时非常有用。这个缺失不影响功能,但强烈建议保留。
3.2 FFmpeg 拉取 RTSP 并推送到 RTMP 的命令解析
配置好 Nginx 后,启动它:
cd D:\StreamServer\nginx nginx.exe然后在任务管理器里确认有nginx.exe进程在跑。接着调用 FFmpeg 拉取 RTSP 流。我的典型命令长这样:
ffmpeg -rtsp_transport tcp -i "rtsp://your_camera_ip:554/stream" -c copy -f flv "rtmp://127.0.0.1:1935/live/stream1"逐项说明一下参数的含义。-rtsp_transport tcp强制 RTSP 走 TCP 传输,而不是默认的 UDP。这个选择很有讲究:UDP 延迟更低,但在网络质量不稳定的情况下丢包严重,画面会出现马赛克、绿屏;TCP 虽然有重传机制,延迟稍微增加,但稳定性好得多。在局域网环境里,我基本都建议用 TCP。-i后面是 RTSP 源地址,注意不同摄像头厂商的 RTSP 路径格式不同,这个要按实际设备去查。-c copy的意思是直接复制编码流,不做转码,这是保证低 CPU 占用的关键。-f flv是输出封装格式,因为 RTMP 协议承载的封装格式就是 FLV。最后的rtmp://127.0.0.1:1935/live/stream1是推流目标地址,路径里的live对应 nginx 配置里的 application 名字,stream1是自定义的流名,后面拉流也需要用到这个名字。
执行这条命令后,如果一切正常,FFmpeg 会持续输出日志,显示帧率、码率、时间戳等信息。这时在另一台机器上用 VLC 打开rtmp://127.0.0.1:1935/live/stream1,就能看到实时画面了。
3.3 多种 RTSP 源适配思路
并不是所有 RTSP 源都长一个样。有些源需要用户名密码认证,那就在 URL 里带进去:
ffmpeg -rtsp_transport tcp -i "rtsp://username:password@192.168.1.100:554/h264/ch1/main/av_stream" -c copy -f flv "rtmp://127.0.0.1:1935/live/camera1"有些源是 H.265 编码,直接用-c copy推过去,如果下游播放器能解码就没问题,但部分 Flash 播放器或者老版本播放器往往不行。这时候就需要在服务器端转码,把 H.265 解码再编码成 H.264。命令改成:
ffmpeg -rtsp_transport tcp -i "rtsp://your_camera_ip:554/stream" -c:v libx264 -preset veryfast -tune zerolatency -c:a aac -f flv "rtmp://127.0.0.1:1935/live/stream2"这里-c:v libx264表示用 x264 编码器重新编码视频,-preset veryfast是编码速度和画质的取舍,-tune zerolatency特别适合直播场景,它会降低编码器的延迟。但这方案的代价是 CPU 占用明显上升。转码一个 1080p 的 H.265 流到 H.264,即使veryfast预设,也需要一个不错的 CPU 核心才能跑流畅。所以我的建议是:能copy就copy,只有下游明确不支持 H.265 时才转码。
4. 实操过程与核心环节实现
4.1 启动前的网络检查
真正开始推流之前,有几个网络层面的坑值得先排查。RTSP 源如果不是本机模拟的,而是来自网络摄像头,首先用 ping 命令确认能通。然后测试 RTSP 端口的可访问性:
telnet 192.168.1.100 554Windows 10 以上版本自带 telnet 客户端,如果没有启用,可以在“启用或关闭 Windows 功能”里打开。如果端口不通,后面的 FFmpeg 拉流必然失败,而且可能不是立刻报错,而是反复重试后超时,浪费时间。还有一种常见情况是摄像头默认关闭了 RTSP 鉴权或者设置了 IP 白名单,需要在设备管理页调整。
同样需要检查防火墙。Nginx 监听 1935 端口,Windows 防火墙默认会拦截。第一次启动 Nginx 时,系统会弹出防火墙提示,记得勾选允许访问。如果没有弹出,到“Windows Defender 防火墙-允许应用通过防火墙”里手动添加nginx.exe。如果是物理服务器,注意别在公网敞开 1935 端口,毕竟 Nginx-RTMP 没有内建鉴权,任何人都能推流,暴露到公网等于裸奔。如果确实需要公网访问,建议加一层 Token 校验或者在前面套一个网关。
4.2 FFmpeg 拉流推流全流程实录
我拿一个局域网内的模拟 RTSP 源来演示完整过程。假设摄像头的 RTSP 地址是rtsp://192.168.1.64:554/ch01,Nginx 服务在本机。
第一步,确认服务端监听起来。命令行执行:
netstat -an | findstr 1935看到TCP 0.0.0.0:1935处于LISTENING状态,说明 Nginx 已经妥了。
第二步,执行 FFmpeg 推流。我推荐把日志级别调整一下,否则默认输出太啰嗦:
ffmpeg -hide_banner -loglevel warning -rtsp_transport tcp -i "rtsp://192.168.1.64:554/ch01" -c copy -f flv "rtmp://127.0.0.1:1935/live/demo"-hide_banner隐藏版本信息,-loglevel warning只输出警告级别以上的日志。这样屏幕干净很多,如果出现错误,也仍然会显示。正常的情况下,这条命令会一直挂在那里,没有报错就是成功了。你可以在浏览器打开http://127.0.0.1/stat查看状态页面,能看到demo这个流名,点击后面的“观看”可以测试播放。
第三步,用 VLC 验证。打开 VLC,按 Ctrl+N,输入:
rtmp://127.0.0.1:1935/live/demo如果画面正常出来,说明整条链路是通的。到这里,核心功能已经完全实现了。
4.3 进程守护与开机自动拉起
FFmpeg 属于前台进程,命令窗口关了,流就断了。在实际项目中肯定不能要求人一直盯着窗口。我在 Windows 上做无人值守的经验是写一个批处理脚本,用start加隐藏窗口的方式来运行,再配合计划任务让它在开机时自动启动。
批处理脚本示例:
@echo off set RTSP_URL=rtsp://192.168.1.64:554/ch01 set RTMP_URL=rtmp://127.0.0.1:1935/live/demo :loop ffmpeg -hide_banner -loglevel warning -rtsp_transport tcp -i "%RTSP_URL%" -c copy -f flv "%RTMP_URL%" echo %date% %time% ffmpeg exited, restarting... >> restart.log timeout /t 5 /nobreak goto loop这个脚本的思路是:FFmpeg 进程一旦异常退出,脚本会在 5 秒后重新拉起它,同时把重启记录写进日志,方便排查。配合 Windows 计划任务,在“系统启动时”触发这个批处理,就能做到开机自启。注意批处理窗口会一直存在,如果想要隐藏窗口,可以把脚本存成.vbs或者用其他方式启动,但对于调试期来说,保留窗口反而方便观察。
再说一个容易忽略的地方:如果在一台机器上要推多路不同源,绝对不要把所有源塞进同一个 FFmpeg 进程里用-map处理,除非你精通 filter 图。更稳妥的做法是每路一个批处理子脚本,或者写一个循环结构为每个摄像头启动独立进程。这样某一路源断线重启时,不会影响其他路。
5. 常见问题与排查技巧实录
5.1 推流失败:Nginx 报错 unknown directive “rtmp”
这个问题我在前面提到过,属于安装包不带模块。排查手段很简单,执行nginx.exe -V看编译参数。如果确认没有--with-http_rtmp_module,那就要重新找一个带 RTMP 的版本。社区常用的编译版本一般会明确标注“include rtmp module”,下载前一定要看清楚。还有一种情况是 Nginx 正在运行,你替换了 nginx.exe 但没重启进程,这时候可以在任务管理器结束所有 Nginx 进程,再重新启动,避免新旧版本混乱。
5.2 推流地址写对了但 VLC 拉不到流
这种问题多半不是 Nginx 本身的问题,而是 FFmpeg 推流进程其实已经退出了。先用nginx-rtmp的状态页确认有没有流在推。如果没有,再回头看 FFmpeg 日志。最常见原因是 RTSP 源连接超时,而且是 UDP 模式导致的。默认情况下 FFmpeg 的 RTSP 传输模式是 UDP,但如果设备或者网络环境屏蔽了 UDP 端口,FFmpeg 可能一直卡在Connection Timeout。解决办法就是显式加-rtsp_transport tcp。另一个原因是 RTSP URL 路径不对,不同品牌摄像头的路径差异很大,甚至同一个品牌不同型号都不同。拿到的地址最好先在 VLC 里验证一下能不能直接播放,确认源没问题再往 Nginx 上推。
5.3 画面上有花屏或者绿屏
花屏一般发生在 UDP 传输、网络抖动的情况下。解决办法优先改成 TCP 传输。如果已经是 TCP 模式还有花屏,那要考虑是不是源端本身输出就不稳定,或者 FFmpeg 在-c copy模式下遇到时间戳断裂。可以尝试加:
-fflags +genpts这个参数强制生成缺失的 PTS 时间戳,能解决一部分时间戳异常导致的画面毛病。如果是音频出现爆音或者音画不同步,可以试试在输出端加-flvflags no_duration_filesize,这个参数用来消除 FLV 封装中某些错误的 duration 信息,在一些特殊源上有效。
5.4 延迟越来越高,画面长时间卡住
RTMP 本身是低延迟协议,但 Nginx 默认配置可能因为缓冲因素导致延迟累积。检查chunk_size不要设置得过大;另外,如果 TTL 设置存在问题,可以考虑调整 FFmpeg 输出端的-rw_timeout参数,限制写超时时间,避免进程假死。更彻底的办法是开启 Nginx 的实时模式,在 application 配置中加上:
application live { live on; record off; gop_cache on; }gop_cache on的作用是缓存最新的一个关键帧,这样当新播放器接入时,可以立刻拿到关键帧开始解码,而不是等到下一个关键帧到来,这就大大缩短了播放器首屏等待时间。启用了这个参数后,新播放器基本能在 1 秒内出画面,代价是内存中会保留一个关键帧的数据,内存占用很小,可以忽略。
5.5 RTSP 源是 H.265,播放端黑屏
这是最容易让人迷惑的问题:FFmpeg 日志显示推流正常,Nginx 状态页显示流存在,VLC 可能也能播放,但换到某些网页播放器就黑屏。原因就是 H.265 编码通过 RTMP 分发后,FLV 封装中的 H.265 支持取决于播放器本身。FLV 规范最早只定义了 H.264,后来各家才扩展支持 H.265。所以对于兼容性要求高的场景,我建议在服务端直接用libx264转码。如果你的下游播放器确实不支持 H.265,不要犹豫,代价就是占用 CPU,这是最省心的方案。
5.6 端口被占用或者无法绑定 1935
Windows 下比较容易出现端口被占用,比如某些软件默认也监听 1935。排查命令:
netstat -ano | findstr 1935查到占用进程的 PID,再到任务管理器里找到对应程序。如果确实不想换 Nginx 的端口,可以先把占用端口进程停掉。如果希望改用其他端口,比如 19350,直接修改 Nginx 配置中listen 19350,那么拉流地址也要对应修改为rtmp://127.0.0.1:19350/live/demo。
6. 进阶玩法与实际项目经验
6.1 加一层接入鉴权,防止别人乱推流
Nginx-rtmp 本身不带用户鉴权,但可以用 on_publish 回调来做一个简单的 Token 校验。原理是:当客户端推流时,Nginx 会向配置的 HTTP 地址发一个 POST 请求,带上传入的流名和参数,如果接口返回 2xx,才允许推流。配置如下:
application live { live on; record off; on_publish http://127.0.0.1:8080/auth; }这时候 FFmpeg 推流地址需要带上 token 参数:
ffmpeg -rtsp_transport tcp -i "rtsp://..." -c copy -f flv "rtmp://127.0.0.1:1935/live/demo?token=123456"后端用任意语言写一个接口,校验token=123456则返回200,否则返回非2xx状态码。我实际常用的做法是用一个极简的 Python HTTP 服务来做这个校验。这个方案虽然谈不上足够强,但对于内部网络的项目来说,已经能挡住绝大多数误推流的情况。
6.2 多路输入统一入口到 RTMP
实际项目中经常有这样的场景:一个厂房里有十个摄像头,希望全部接入同一台 Windows 机器,再统一推到平台。这种需求可以每路一个 FFmpeg 进程,推流名分别为camera1、camera2……这样可以做到独立管理,某一路断线重启不影响其他路。Nginx 配置里不需要写死流名,任意流名都会自动创建一路流。管理脚本可以用一个简单的循环:
for %%i in (1 2 3 4) do ( start /b ffmpeg -rtsp_transport tcp -i "rtsp://192.168.1.%%i:554/ch01" -c copy -f flv "rtmp://127.0.0.1:1935/live/cam%%i" )如果你想要在断线时自动重连,每个进程都套上 4.3 中的循环结构即可。
6.3 监控流状态:从状态页到简单 API
http://127.0.0.1/stat这个页面能看到所有流的实时信息,但它是一个 HTML 页面,不适合程序读取。Nginx-rtmp 还提供了一个 XML 格式状态接口,可以通过配置/stat时返回 XML 数据。如果只想快速写一个巡检脚本,检查流是否存在,可以用下面的命令行:
curl http://127.0.0.1/statWindows 10 自带 curl,直接输出 HTML,如果看到stream1表示流在。稍加解析,就能做成简单的告警脚本:如果状态页里找不到指定流名,就自动重启 FFmpeg 进程,并将告警信息发送到钉钉或者企业微信。这算是这个方案里性价比很高的小扩展。
6.4 为什么我不建议用 VLC 做推流
有人可能会想,既然 VLC 既能拉 RTSP 又能推 RTMP,为什么还专门用 FFmpeg?VLC 的图形界面操作简单,但作为服务端组件有两个硬伤:一是异常退出后无人值守重启不方便,二是它对多路流的资源控制不如 FFmpeg 精细。FFmpeg 是纯命令行,能非常方便地被批处理和计划任务调度,日志也更利于排查。所以我劝所有打算长期跑这套服务的人,老老实实用 FFmpeg 拉流。
7. 性能开销与稳定性心得
很多初学者会担心在 Windows 上跑这套方案会不会性能不行。以我的实测经验来说,-c copy模式下,FFmpeg 只做解封装和再封装,CPU 占用极低。一路 1080p 的 H.264 流,在普通 i5 处理器上 FFmpeg 进程 CPU 占比通常在 3%-5% 左右;Nginx 就更低了,毕竟它只做协议转发。真正吃 CPU 的是转码,也就是 H.265 转 H.264 的操作,这个场景下 CPU 占用会直接飙到 30% 以上。所以部署前先确认源编码格式,能 copy 就不要转码。
内存占用方面,Nginx 默认配置跑几十路流都没什么压力,每路流的缓冲、密钥帧缓存加在一起也就几十兆。只要你的 Windows 机器不是那种 2GB 内存的老古董,完全不用担心。磁盘方面,只要record off,Nginx 本身不写盘。FFmpeg 推流时默认没有落盘操作,所以对磁盘的读写基本可以忽略。这意味着你可以把整套服务跑在一台小 SSD 的迷你主机上,非常轻量。
稳定性上,我已经用这套方案跑过 7x24 小时的连续推流。最大的敌人不是服务器本身,而是上游 RTSP 源不稳定。摄像头偶尔会重启、断流,导致 FFmpeg 进程退出。因此,守护脚本比什么都重要。建议在批处理里记录重启日志,并把日志定期清理,防止文件无限增长。还有一个细节:批量处理时注意timeout命令的语法,旧系统可能需要写成timeout /t 5 /nobreak >nul,避免把鼠标点击动作误传进窗口。
8. 从单机到小集群的扩展思路
如果你不止一台 Windows 机器,或者前端有负载均衡的需求,这套 Nginx-rtmp 方案也可以平滑扩展。最简单的方式是部署多台 Nginx-rtmp 服务器,在前端用加权轮询的方式分发推流地址,每台服务器的 Nginx 配置里再配置pull从另外的源拉取同一路流,实现简单的冗余。比如服务器 A 和 B 都检测到主服务器 C 上有流,A 和 B 各自通过pull rtmp://C/live/demo;来拉取,这样即使 C 宕机,A 和 B 上还存留着最近一段时间内拉取到的流,下游播放端可以继续从 A 或 B 拉流,完成一个基础的主备容灾。当然,这只能缩短中断时间,并不能做到零切换,但对于内部监控项目来说已经完全够用。
如果在更复杂的场景中,希望动态管理流,可以引入更重的流媒体服务来替换 Nginx-rtmp,但那样整套系统的部署复杂度会高一个档次。我个人看法是:技术选型要从实际规模出发。10 路以内的流,Nginx-rtmp 加 FFmpeg 是性价比最高的组合;超过 50 路,就应该考虑专门的流媒体网关或者集群方案了。窗口从单机走到集群,核心的思路是可替换、可观测、可恢复,这正是这套轻量方案在真实项目里带给我的经验。
最后再分享一个我在现场调试时经常用的小技巧:在 RTSP 源不稳定、摄像头暂时不在线的时候,可以先启动 Nginx,再用 FFmpeg 测试本机生成的一路测试源,也就是用 FFmpeg 的 lavi 虚拟设备推流,验证下游链路是否通畅:
ffmpeg -re -f lavfi -i testsrc2=size=1280x720:rate=30 -c:v libx264 -preset veryfast -f flv "rtmp://127.0.0.1:1935/live/test"VLC 能播放这路测试流,说明服务器、端口、Nginx 配置都没有问题,接着就可以安心排查摄像头那一侧。这个办法帮我省下了很多在机房里跟摄像头厂商扯皮的时间。
这个内容后续还可以扩展的方向是:接入 WebRTC 低延迟播放、把 RTMP 流转成 HLS 做回看、或者用 FFmpeg 对视频流叠加文字水印和动态时间戳。只要把“RTSP 进、RTMP 出”这套基础链路跑明白了,后面这些都是在上面增加 filter 链的事情,边界清晰,改造成本很低。