srt在ffmpeg中不能直接用ffmpeg -i拉流实现低延迟,因其默认启用加密与重传、未显式配置-srt_latency(如100ms)、-srt_mode及-srt_pkt_size等关键参数,且需强制指定-f mpegts封装、禁用缓冲(-fflags nobuffer+fastseek)并配合解码器低延迟选项,否则端到端延迟常超800ms。

为什么 SRT 在 FFmpeg 里不能直接用 ffmpeg -i 拉流就自动低延迟
SRT 默认启用加密和重传机制,FFmpeg 的 libsrt 封装层若未显式关闭冗余保护、禁用加密、调小缓冲窗口,实际端到端延迟常卡在 800ms 以上——这不是网络问题,是协议栈默认行为。关键参数不在 URL 里,而在 AVDictionary 或命令行的 -srt_* 选项中。
-
-srt_latency 100:设为 100ms(单位毫秒),这是接收端最大允许的抖动缓冲,必须显式指定,否则走默认 120ms + 内部重传等待,叠加后远超预期 -
-srt_mode caller(推流)或-srt_mode listener(拉流):不设会 fallback 到rendezvous,触发双向握手+心跳,增加首次连接耗时 -
-srt_pkt_size 1316:匹配 UDP MTU(1500 - 20IP - 8UDP - 12SRT = 1460,但实测 1316 更稳),过大易丢包,过小则帧碎片化抬高开销
推流端如何避免 FFmpeg 把 H.264 编码器塞进 SRT 包导致花屏
FFmpeg 默认对 SRT 输出使用 flv muxer 封装,但 SRT 协议本身只传裸 AVPacket,不认 FLV header。若没强制指定 -f mpegts 或 -f mpegts -mpegts_m2ts_mode 1,接收端 ffplay 或自研解码器会因找不到 PAT/PMT 直接失败,报错类似 Invalid data found when processing input。
- 正确推流命令示例:
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 2M -g 30 -keyint_min 30 -sc_threshold 0 -c:a aac -f mpegts "srt://127.0.0.1:6000?mode=caller&latency=100&pkt_size=1316"
- 务必加
-f mpegts:SRT 不自带复用逻辑,必须靠 muxer 打包成 TS 流再送入 SRT socket - 不要用
-f flv或-f mp4:这些格式依赖文件头/索引,SRT 是纯 packet 流,无法承载 - 若用硬件编码(如
h264_nvenc),需确认驱动支持 low-latency mode:-rc vbr_hq -rc-lookahead 0 -spatial-aq 0
拉流端 ffplay 为什么连上但画面卡住不动
常见原因是 SRT 接收窗口与解码器缓冲冲突。ffplay 默认启用音视频同步和内部队列(-autoexit 之外还有隐式 -probesize 和 -analyzeduration),而 SRT 的低延迟要求 packet 到达即解,不能等“足够数据”。错误现象是日志出现 Estimating duration from bitrate, this may be inaccurate 后静止。
- 必须加
-fflags nobuffer+fastseek:禁用读缓冲,跳过格式探测阶段 - 加
-flags low_delay和-framedrop:让解码器优先保实时性而非完整性 - 完整拉流命令:
ffplay -fflags nobuffer+fastseek -flags low_delay -framedrop -rtsp_transport tcp "srt://127.0.0.1:6000?mode=listener&latency=100"
- 注意:URL 中的
latency=100是 query 参数,对应 C API 的srt_latency字段,不是所有 FFmpeg 版本都支持;4.4+ 更稳定,低于 4.2 建议升级
C++ 调用 libavformat 推 SRT 流时,avformat_open_input 失败返回 -5
错误码 -5 是 AVERROR_IO,表面是 IO 错误,实际多因 SRT URL 解析失败或 libsrt 初始化异常。FFmpeg 4.3+ 对 SRT 的 error reporting 仍较弱,容易掩盖真实原因。
- 先检查是否链接了
libsrt:pkg-config --modversion libsrt应输出 ≥ 1.4.1;若未启用,configure需加--enable-libsrt - URL 必须带完整 scheme:
"srt://192.168.1.100:6000?mode=caller&latency=100",缺mode=或拼错会静默失败 - 设置字典前,确保
AVDictionary *opts = nullptr;,然后:av_dict_set(&opts, "mode", "caller", 0); av_dict_set(&opts, "latency", "100", 0); av_dict_set(&opts, "pkt_size", "1316", 0); avformat_open_input(&fmt_ctx, url, nullptr, &opts);
- 别漏掉
av_dict_free(&opts):内存泄漏会导致后续连接失败,且错误表现和首次一样
真正难调的是网络路径上的中间设备——有些企业防火墙会重置 SRT 的 keepalive 包,表现为偶发断连且无错误日志。这种问题只能靠 srt-live-transmit 工具抓包比对 timestamp 字段,没法靠 FFmpeg 参数解决。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











