目录
[一、RTMP 在 FFmpeg 里的两层模型](#一、RTMP 在 FFmpeg 里的两层模型)
[二、URL 解析规则(先搞清 app / playpath)](#二、URL 解析规则(先搞清 app / playpath))
[三、Native RTMP 协议参数(FFmpeg 内置,非 librtmp)](#三、Native RTMP 协议参数(FFmpeg 内置,非 librtmp))
[FFmpeg 6 新增](#FFmpeg 6 新增)
[四、FLV 封装层参数(和 RTMP 强绑定)](#四、FLV 封装层参数(和 RTMP 强绑定))
[RTSP → RTMP 转推](#RTSP → RTMP 转推)
[拉 RTMP 存本地](#拉 RTMP 存本地)
[带 token 的 CDN 推流](#带 token 的 CDN 推流)
[七、Native RTMP vs librtmp(编译期二选一)](#七、Native RTMP vs librtmp(编译期二选一))
[九、最常见 5 个坑(按出现频率)](#九、最常见 5 个坑(按出现频率))
觉得有用,就请您帮忙点赞转发收藏吧,您的鼓励是我创作的动力,多谢看官。
由于能力水平有限,文中的错误或不严谨的地方在所难免,还请批评指正。
在FFmpeg中使用RTMP协议进行视频直播时,你需要了解一些基本的参数设置,以确保你的视频流可以顺利传输到目标服务器。RTMP(Real Time Messaging Protocol)是一种网络协议,用于实现流媒体数据的传输。在FFmpeg中,使用RTMP协议进行视频直播通常涉及到以下几个关键步骤和参数。
一、RTMP 在 FFmpeg 里的两层模型
输入/输出 URL: rtmp://host:port/app/playpath
│
├── 协议层 (rtmpproto.c / 或 librtmp)
│ └── rtmp_app / rtmp_playpath / rtmp_live / rtmp_buffer ...
│
└── 封装层 (flvenc.c / flvdec.c)
└── -f flv / -flvflags no_duration_filesize
推流必须显式 -f flv (或代码里 avformat_alloc_output_context2(&ctx, NULL, "flv", url)),否则 FFmpeg 会猜格式,直播场景必炸。
二、URL 解析规则(先搞清 app / playpath)
rtmp://user:pass@host:1935/app/playpath
| 段 | 含义 | 备注 |
|---|---|---|
| user:pass | 推流鉴权 | 部分服务器用?token=xxx 也行 |
| host:port | 默认 1935 | |
| app | 应用名(live / vod / ingest) | 可用 rtmp_app覆盖 |
| playpath | 流名(streamKey) | 可带 mp4:前缀;可用 rtmp_playpath覆盖 |
等价写法:
rtmp://srv/live/room1
# =
-rtmp_app live -rtmp_playpath room1 rtmp://srv
三、Native RTMP 协议参数(FFmpeg 内置,非 librtmp)
通过 -option value或 AVDictionary设置,重点记这些:
连接与握手类
-
rtmp_app
覆盖 URL 里的 app 名。服务器有"隐式 app"时必用。
-
rtmp_playpath
覆盖流名。SRS 常配合
?vhost=使用。 -
rtmp_tcurl
Connect 时发的 tcUrl,默认
rtmp://host:port/app。某些 CDN(旧版 FMS)校验严格,必须手动设。
-
rtmp_pageurl / rtmp_swfurl / rtmp_swfverify / rtmp_swfhash / rtmp_swfsize
SWF 防盗链验证三件套。
rtmp_swfverify最省事(给 URL 自动算 hash)。 -
rtmp_flashver
模拟 Flash 版本串。拉流默认
LNX 9,0,124,2,推流默认FMLE/3.0 (compatible; )。老 FMS 拒连时改这个。
-
rtmp_conn
往 Connect AMF 里塞自定义字段:
-rtmp_conn "S:token=abc O:1 NS:info:ok O:0"B=bool / N=number / S=string / O=object / Z=null
直播语义类(最重要)
-
rtmp_live
-
any(默认):先找直播,没有就播录制 -
live:只播直播,找不到直接失败(拉直播必设) -
recorded:只播点播
拉流命令等价旧写法
rtmp://... live=1 -
-
rtml_buffer
客户端缓冲(ms),默认 3000。
低延迟场景调到
0~500;弱网回源可加到6000。 -
rtmp_subscribe
订阅名,默认等于 playpath。
rtmp_live=live时才发。 -
rtmp_flush_interval
仅 RTMPT(HTTP 隧道)生效,默认 10。
传输层
-
tcp_nodelay=1
关 Nagle,降延迟。配合
-fflags +nobuffer使用。 -
listen / timeout
FFmpeg 自己当 RTMP 服务端:
rtmp://127.0.0.1:1935/live/foo?listen=1
FFmpeg 6 新增
-
rtmp_enhanced_codecs
Enhanced RTMP(RTMP over H265/AV1/VP9)广告用:
-rtmp_enhanced_codecs hvc1,av01写进 Connect 的
fourCcLive字段。
四、FLV 封装层参数(和 RTMP 强绑定)
RTMP 线格式 = FLV tag 流,所以这些 muxer 参数直接影响直播兼容性:
-
-f flv
强制 FLV。RTMP 输出不写这个,90% 情况会失败。
-
-flvflags no_duration_filesize
直播推流必加。
不写 filesize/duration 到 metadata(直播没有"文件尾"),防止播放器等待 EOS 卡首帧。
-
-flvflags aac_seq_header_detect
老播放器兼容 AAC 音频头。
五、输入/输出通用鲁棒性参数
推流端
-re # 按输入帧率读(文件转直播必加,否则瞬间发完)
-reconnect 1
-reconnect_at_eof 1
-reconnect_streamed 1
-reconnect_delay_max 5 # 源断自动重连
-max_interleave_delta 0 # 防止音视频交错超时断流
-bufsize 1M
拉流端
-fflags +nobuffer
-flags low_delay
-rtbufsize 1M
六、标准命令模板
文件推直播(H264/AAC)
ffmpeg -re -i in.mp4 \
-c:v h264 -b:v 2000k -g 50 -keyint_min 25 -sc_threshold 0 \
-c:a aac -b:a 128k -ar 44100 \
-f flv -flvflags no_duration_filesize \
rtmp://srv:1935/live/room1
RTSP → RTMP 转推
ffmpeg -rtsp_transport tcp -reconnect 1 -reconnect_delay_max 5 \
-i rtsp://cam/live \
-c:v libx264 -preset veryfast -tune zerolatency -fps_mode cfr -r 25 \
-c:a aac \
-f flv -flvflags no_duration_filesize \
rtmp://srv/live/cam1
拉 RTMP 存本地
ffplay rtmp://srv/live/room1
# 或
ffmpeg -rtmp_live live -i rtmp://srv/live/room1 -c copy out.flv
带 token 的 CDN 推流
ffmpeg -re -i in.flv \
-f flv -flvflags no_duration_filesize \
-rtmp_app live \
-rtmp_playpath room1?token=xxxx \
-rtmp_tcurl rtmp://cdn.example.com/live \
rtmp://cdn.example.com
七、Native RTMP vs librtmp(编译期二选一)
| 维度 | FFmpeg native (rtmpproto) |
librtmp (--enable-librtmp) |
|---|---|---|
| 维护状态 | 主线默认 | 旧,部分发行版仍带 |
| 参数前缀 | rtmp_ |
同名,但解析器不同 |
| Enhanced RTMP | 6.x 支持 | 不支持 |
| SWF verify | 支持 | 支持 |
| RTMPS 加密 | 依赖系统 TLS | 自带 |
| 推荐 | 新项目用 native | 老 FMS 兼容才用 |
两者不能同时存在,编译时谁先配谁生效。
八、代码层(libavformat)设置要点
AVDictionary *opts = NULL;
av_dict_set(&opts, "rtmp_live", "live", 0);
av_dict_set(&opts, "rtmp_buffer", "500", 0);
av_dict_set(&opts, "flvflags", "no_duration_filesize", 0);
av_dict_set(&opts, "reconnect", "1", 0);
av_dict_set(&opts, "reconnect_delay_max", "5", 0);
avformat_alloc_output_context2(&oc, NULL, "flv", url);
avio_open2(&oc->pb, url, AVIO_FLAG_WRITE, NULL, &opts);
avformat_write_header(oc, &opts);
flvflags是 muxer 私有选项,必须走 avformat_write_header的 options 或全局 AVOption,不能当协议选项塞错层。
九、最常见 5 个坑(按出现频率)
-
不写
-f flv →Unknown format或服务器收不到音视频 -
**拉直播没设
rtmp_live live** → 播一会卡住等点播 -
filesize 写进 metadata → 浏览器 flv.js 首帧等 EOS
-
buffer 默认 3000ms → 延迟肉眼可见,低延迟忘了改
-
用 librtmp 却传 Enhanced RTMP 参数 → 直接忽略
十、一句话总结
RTMP 参数分三层:**URL 定路由 → rtmp_定握手/直播语义 → flv/flvflags 定封装兼容。
直播推流铁三角:
-f flv -flvflags no_duration_filesize -rtmp_live live