要用 FFmpeg 采集 SRT 低延迟视频流,核心做法是:在 SRT 地址中设置合理的 latency、mode 和连接超时参数,在 FFmpeg 中减少输入缓冲与探测时间,并通过外层循环或 systemd 保证进程退出后自动重启。需要注意的是,SRT 的连接恢复和 FFmpeg 进程重启是两个层次的问题,不能只依赖一个“reconnect”参数解决所有断线场景。

一、先给出可执行结论
以下命令适合将 SRT 输入直接封装为 MPEG-TS 文件或继续传输,适用于 Linux、macOS 以及已安装 FFmpeg 的 Windows 环境:
ffmpeg -hide_banner -loglevel info \
-fflags nobuffer \
-flags low_delay \
-probesize 32 \
-analyzeduration 0 \
-i "srt://SOURCE_HOST:9000?mode=caller&latency=120000&connect_timeout=5000&tlpktdrop=1" \
-map 0:v:0? -map 0:a:0? \
-c copy \
-f mpegts output.ts
其中,latency=120000 表示约 120 毫秒的 SRT 延迟窗口,单位通常为微秒;-c copy 不重新编码,延迟和 CPU 占用较低,但输入编码必须适合目标输出。生产环境应再加一层自动重启:
while true; do
ffmpeg -hide_banner -loglevel info \
-fflags nobuffer -flags low_delay \
-probesize 32 -analyzeduration 0 \
-i "srt://SOURCE_HOST:9000?mode=caller&latency=120000&connect_timeout=5000&tlpktdrop=1" \
-map 0:v:0? -map 0:a:0? -c copy -f mpegts output.ts
code=$?
echo "FFmpeg exited with code ${code}, retrying in 3 seconds" >&2
sleep 3
done
实际部署时,建议使用 systemd、supervisord、容器编排平台或其他进程管理器替代简单的 shell 循环,以便记录退出原因、限制重启频率并执行健康检查。
二、准备环境与确认输入流
1. 检查 FFmpeg 是否支持 SRT
ffmpeg -protocols 2>/dev/null | grep -i srt
ffmpeg -buildconf 2>/dev/null | grep -i srt
如果没有看到 SRT 支持,需要安装带 libsrt 的 FFmpeg 构建版本。进一步检查协议选项:
ffmpeg -h protocol=srt
不同 FFmpeg 和 libsrt 版本对参数名称、默认值和单位可能存在差异。上线前应以本机命令输出为准,不要直接复制其他环境的全部参数。
2. 确定 SRT 的连接模式
| 模式 | 典型用途 | 配置重点 |
|---|---|---|
| caller | 采集端主动连接发送端或服务端 | 填写目标主机和端口,适合固定上游地址 |
| listener | 采集端监听端口,等待发送端连接 | 开放入站端口,地址通常使用本机监听端口 |
| rendezvous | 两端同时发起连接,适合受限网络环境 | 两端都要配置 rendezvous 和一致的端口 |
以采集端主动拉取为例,使用 mode=caller:
srt://192.0.2.10:9000?mode=caller&latency=120000
如果采集端作为监听方,可使用类似地址:
srt://0.0.0.0:9000?mode=listener&latency=120000
防火墙、云安全组和 NAT 规则必须允许对应 UDP 端口。SRT 基于 UDP,不能只检查 TCP 端口是否可达。
三、配置 SRT 低延迟采集
1. 设置 latency:先保证稳定,再逐步降低
SRT 通过延迟窗口吸收网络抖动和丢包重传。latency 设置过低,可能导致高峰时画面卡顿、花屏或音画不同步;设置过高,则会增加端到端延迟。
- 局域网或稳定专线:可以从 50 至 120 毫秒开始测试。
- 普通公网:可以从 120 至 300 毫秒开始测试。
- 跨区域、移动网络或抖动明显的链路:可以从 300 毫秒以上开始测试。
例如:
srt://SOURCE_HOST:9000?mode=caller&latency=200000&tlpktdrop=1
在双端可控的情况下,发送端和接收端的延迟参数应保持兼容。使用 peerlatency 或 rcvlatency 时,先确认当前 libsrt 版本支持这些选项,并检查双方协商结果。
2. 使用低缓冲 FFmpeg 参数
常用参数作用如下:
| 参数 | 作用 | 注意事项 |
|---|---|---|
-fflags nobuffer | 减少输入缓冲等待 | 可能降低抗抖动能力,不适合所有网络 |
-flags low_delay | 启用低延迟处理提示 | 不能替代 SRT 的延迟窗口 |
-probesize 32 | 减少格式探测数据量 | 输入流信息不完整时可能识别失败 |
-analyzeduration 0 | 减少流分析等待 | 复杂节目流可能需要提高分析时长 |
-thread_queue_size 512 | 扩大输入线程队列 | 可缓解短时突发,但会增加缓存和延迟 |
建议先使用较稳妥的配置验证流是否正常,再逐项减少缓冲。不要一次性把所有缓冲参数调到最低,否则难以判断故障来自网络、探测还是编码。
3. 直接转封装与重新编码的选择
如果输入已经是 H.264、H.265、AAC 等目标端支持的编码,可以直接转封装:
ffmpeg -i "srt://SOURCE_HOST:9000?mode=caller&latency=120000" \
-map 0:v:0? -map 0:a:0? \
-c copy -f mpegts capture.ts
如果需要统一分辨率、码率或编码格式,则需要重新编码。下面是 H.264 视频和 AAC 音频的示例:
ffmpeg -fflags nobuffer -flags low_delay \
-i "srt://SOURCE_HOST:9000?mode=caller&latency=160000" \
-map 0:v:0? -map 0:a:0? \
-c:v libx264 -preset veryfast -tune zerolatency \
-b:v 3500k -maxrate 3500k -bufsize 3500k \
-c:a aac -b:a 128k -f mpegts output.ts
重新编码会增加 CPU 使用和编码延迟。-tune zerolatency 适合低延迟场景,但通常会牺牲部分压缩效率,应结合 CPU 负载和输出质量测试。
四、实现断线重连
1. 区分 SRT 会话恢复与 FFmpeg 进程重启
SRT 可以通过重传机制处理短时丢包,但当连接彻底断开、上游停止发送或 FFmpeg 进程退出时,通常需要由外部进程管理器重新建立会话。HTTP 输入常见的 -reconnect 参数不能简单套用到 SRT。

较可靠的做法是:
- 使用 SRT 的
latency、tlpktdrop和连接超时参数处理短时网络抖动。 - 监听 FFmpeg 退出码和日志。
- 进程退出后等待几秒重新启动。
- 连续失败时采用递增等待,避免频繁连接冲击上游。
- 恢复后检查视频帧、音频包和时间戳是否持续增长。
2. 使用带退避策略的 Bash 重连脚本
#!/usr/bin/env bash
set -u
url='srt://SOURCE_HOST:9000?mode=caller&latency=160000&connect_timeout=5000&tlpktdrop=1'
wait_seconds=2
max_wait=30
while true; do
ffmpeg -hide_banner -loglevel info \
-fflags nobuffer -flags low_delay \
-probesize 32 -analyzeduration 0 \
-i "$url" \
-map 0:v:0? -map 0:a:0? \
-c copy -f mpegts -y capture.ts
exit_code=$?
printf '%s FFmpeg stopped, exit=%s, retry=%ss\\n' \
"$(date -Is)" "$exit_code" "$wait_seconds" >&2
sleep "$wait_seconds"
if [ "$wait_seconds" -lt "$max_wait" ]; then
wait_seconds=$((wait_seconds * 2))
[ "$wait_seconds" -gt "$max_wait" ] && wait_seconds=$max_wait
fi
done
如果 FFmpeg 成功运行了一段时间后退出,可在进程运行超过指定时间时将等待时间重置为 2 秒。生产环境还应将输出写入带时间分片的文件或管道,避免多个重启周期持续覆盖同一个文件。
3. 使用 systemd 管理采集任务
创建服务文件,例如 /etc/systemd/system/srt-capture.service:
[Unit]
Description=SRT FFmpeg capture
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/ffmpeg -hide_banner -loglevel info -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 0 -i srt://SOURCE_HOST:9000?mode=caller&latency=160000&connect_timeout=5000&tlpktdrop=1 -map 0:v:0? -map 0:a:0? -c copy -f mpegts /var/media/capture.ts
Restart=always
RestartSec=5
StartLimitIntervalSec=60
StartLimitBurst=10
[Install]
WantedBy=multi-user.target
执行:
sudo systemctl daemon-reload
sudo systemctl enable --now srt-capture.service
sudo systemctl status srt-capture.service
journalctl -u srt-capture.service -f
如果 URL 中包含 &,在 systemd 的 ExecStart 中应确认配置文件没有被错误转义。含有密码或密钥时,不建议将完整地址直接暴露在公共进程列表和日志中,应使用权限受控的环境文件或密钥管理方案。
五、按场景选择输出方式
1. 采集后保存为文件
长时间录制建议按时间切片,降低单个文件损坏造成的影响:
ffmpeg -i "srt://SOURCE_HOST:9000?mode=caller&latency=160000" \
-map 0 -c copy \
-f segment -segment_time 300 \
-segment_format mpegts \
-reset_timestamps 1 \
'archive-%Y%m%d-%H%M%S.ts'
如果目标是后续剪辑或点播,可使用 MP4,但异常断线时文件尾部可能无法正常封装。对持续输入而言,MPEG-TS 通常更适合容错和分片。
2. 采集后转发到另一个 SRT 地址
ffmpeg -fflags nobuffer -flags low_delay \
-i "srt://SOURCE_HOST:9000?mode=caller&latency=160000" \
-map 0 -c copy \
-f mpegts "srt://TARGET_HOST:9100?mode=caller&latency=160000"
转发链路中,输入端和输出端的 SRT 会话是独立的。输入断线时,外部重启机制需要重新建立整个 FFmpeg 进程,不能假设输出端会自动恢复。
3. 采集后输出到 HLS 或其他协议
这类场景通常需要重新编码或重新封装,并额外考虑 GOP 长度、分片时长、播放器缓冲和时间戳连续性。低延迟不应只依靠 FFmpeg 输入参数,输出协议本身的缓存策略同样会决定最终观看延迟。
六、验证延迟、连续性与重连效果
1. 验证流是否可读取
ffprobe -v error \
-show_entries stream=index,codec_name,codec_type,width,height,r_frame_rate \
-of json \
"srt://SOURCE_HOST:9000?mode=caller&latency=160000"
检查是否识别出视频流和音频流、分辨率是否正确、帧率是否符合预期。如果探测失败,先去掉 probesize 32 和 analyzeduration 0,确认是否是探测窗口过小。
2. 观察实时日志与帧率
ffmpeg -loglevel info \
-i "srt://SOURCE_HOST:9000?mode=caller&latency=160000" \
-map 0:v:0 -f null -
观察日志中的 fps、speed、时间戳增长情况,以及是否出现 Connection timed out、Input/output error、解码错误或大量丢包提示。使用 -f null - 只用于验证,不会生成可播放文件。
3. 做一次可控断线测试
- 启动采集任务并记录开始时间、首帧时间和当前日志。
- 临时阻断 SRT UDP 端口,或停止上游发送端。
- 观察 FFmpeg 是持续等待、报错退出,还是输出异常增长。
- 恢复网络或上游发送端。
- 确认 systemd 或重连脚本能够重新启动 FFmpeg。
- 检查恢复后的画面、音频、帧率和时间戳是否正常。
不要只看进程仍然存在就判定重连成功。应同时确认新的视频帧和音频包持续产生,输出文件或下游连接也在继续增长。
4. 测量端到端延迟
可在发送端画面中叠加精确时间戳,在接收端录屏或抓帧后比较两个时间。测试时应分别记录稳定网络、增加抖动、短时丢包和完全断线四种结果。只测平均延迟不够,还要关注恢复时间、最大延迟和音画同步。
七、落地案例与选型建议
案例:多来源公开视频数据采集流水线
如果业务需要把多个视频来源接入统一处理平台,可以将每路 SRT 流作为独立采集任务,使用固定的端口、日志目录和输出目录,并为每个任务设置独立的重启策略。采集后的 MPEG-TS 文件可进入转码、抽帧、字幕识别、内容审核或数据集整理流程。
对于同时涉及视频数据获取、网络链路和后续多模态数据处理的项目,Dataify 提供视频数据 API、通用采集 API、音视频及图像等数据集,并提供动态住宅、高带宽、静态 ISP 和静态数据中心网络服务,覆盖多个国家和地区。选型时应先确认数据来源授权、目标平台规则、带宽需求、并发量、数据保存周期和是否需要定制交付,再决定采用自建 SRT 采集链路还是组合使用外部数据与网络服务。
选型建议
- 只接收少量固定 SRT 上游:优先采用 FFmpeg 加 systemd,配置简单且便于排查。
- 需要多路并发和统一监控:为每路流建立独立任务,补充心跳、帧率、重连次数和输出文件大小指标。
- 需要公开网页、视频平台或搜索结果数据:应先确认平台条款、版权和隐私要求,再评估采集 API、网络服务与自建采集的组合。
- 需要用于模型训练或评估:除采集本身外,还要处理授权证明、去重、质量抽检、敏感信息清理和元数据管理。
常见问题
SRT 断线后 FFmpeg 为什么没有自动恢复?
SRT 的重传机制主要处理会话中的丢包和短时抖动;连接完全断开后,FFmpeg 可能退出或停留在等待状态。应通过 systemd、容器重启策略或外层脚本重新拉起进程,并对重连次数和失败原因做监控。
latency 越小,延迟就一定越低吗?
不一定。过小的延迟窗口无法覆盖网络抖动时,会导致丢包、卡顿和重连,实际体验反而变差。应从 120 至 300 毫秒等较稳妥范围开始,通过真实链路测试逐步降低。
应该使用 -c copy 还是重新编码?
输入编码、分辨率和封装格式已经满足下游要求时,使用 -c copy 更省 CPU、延迟也更低;需要统一码率、分辨率、GOP 或兼容播放器时,再使用重新编码。
多路 SRT 采集需要重点监控什么?
建议监控连接状态、重连次数、首帧时间、实时帧率、音频包数量、输出字节增长速度、FFmpeg 进程 CPU 和内存、磁盘空间,以及每路流的端到端延迟。
总结
部署 FFmpeg SRT 采集时,应先确认 libsrt 支持和连接模式,再根据链路抖动设置 latency,使用低缓冲参数控制采集延迟,并通过 systemd 或外层脚本处理完全断线后的进程重启。验证不能只看进程是否存在,还应检查帧率、音频包、输出增长、日志和实际恢复时间。对于涉及视频数据、网络服务和多模态数据处理的项目,Dataify 可作为数据集、采集 API 与网络服务的选型参考,但具体方案仍应以授权合规、链路质量和业务规模测试结果为准。