FFmpeg 推流基础:命令、协议与核心参数
推流这件事,说白了就是把本地视频数据「喂」给网络上的服务器。FFmpeg 就是那个负责投喂的管道工。我最早接触推流时,以为只要把文件路径换成 RTMP 地址就行,结果画面卡成幻灯片。后来才明白——推流不是拷贝,是实时投喂。
这一章,我们先把 FFmpeg 推流的基本功打扎实。命令怎么写?协议怎么选?参数怎么调?搞懂这些,后面修卡顿才有底气。
推流命令的基本格式
FFmpeg 推流的命令结构,其实就一句话:
ffmpeg [输入选项] -i 输入源 [输出选项] 输出URL
举个例子,把本地 MP4 推到 RTMP 服务器:
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 2M -f flv rtmp://live.example.com/stream
这里 -re 是「读文件速度模拟实时」,-c:v libx264 指定视频编码器,-b:v 2M 限制码率,-f flv 指定封装格式。RTMP 协议强制要求 FLV 封装,所以 -f flv 不能省。
-re 跑一遍,确认输入源能正常解码。加上 -re 后如果出问题,至少知道不是源文件的问题。
常用推流协议对比
协议选不对,推流再努力也白费。我见过太多人拿着 RTMP 去推 HLS 的地址,结果折腾半天连不上。下面这三个协议,是实战中最常用的。
| 协议 | 延迟 | 适用场景 | 封装格式 | 防火墙友好度 |
|---|---|---|---|---|
| RTMP | 1-3 秒 | 直播推流、互动直播 | FLV | 一般(需 1935 端口) |
| HLS | 6-30 秒 | 点播、大规模直播分发 | TS/MP4 切片 | 好(走 HTTP 80/443) |
| SRT | 0.5-2 秒 | 不稳定网络下的高质量推流 | MPEG-TS | 好(可自定义端口) |
RTMP:老牌直播协议
RTMP 是 Adobe 搞出来的,虽然年头久,但至今仍是国内直播平台的主流推流协议。它的延迟低,1-3 秒就能到观众端。缺点是对网络抖动敏感,丢包多了画面直接花掉。
推流示例:
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 3M -c:a aac -b:a 128k -f flv rtmp://push.example.com/live/streamkey
streamkey 是鉴权密钥,不要泄露。我曾经在调试时不小心把 key 贴到了公开论坛,结果被人盗推了一晚上猫片。
HLS:苹果的切片方案
HLS 把视频切成 2-10 秒的小段,生成一个 m3u8 索引文件。观众端逐段下载播放。延迟比 RTMP 高,但胜在兼容性好——所有现代浏览器都支持。
推流示例:
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 2M -c:a aac -b:a 128k -f hls -hls_time 4 -hls_list_size 6 output.m3u8
-hls_time 4 表示每 4 秒切一个段,-hls_list_size 6 表示播放列表保留最近 6 个段。这两个参数直接影响延迟和存储开销。
SRT:新时代的可靠传输
SRT 是 Haivision 开源的协议,基于 UDP 但自带丢包重传和加密。我在海外项目里用过一次就回不去了——跨洋推流,RTMP 丢包 5% 就卡死,SRT 丢包 20% 还能看。
推流示例:
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 2M -c:a aac -b:a 128k -f mpegts 'srt://push.example.com:10080?mode=caller&latency=200'
latency=200 设置延迟 200ms,mode=caller 表示主动连接。SRT 的参数很多,但这两个是起步必调的。
推流核心参数详解
参数是推流的灵魂。同样的源文件,参数调好了流畅清晰,调不好就是马赛克+卡顿。下面这四个参数,是我每次推流必调的。
-re:让文件按真实时间播放
不加 -re,FFmpeg 会以最快速度读取文件——一个 10 秒的视频可能 0.1 秒就读完了。推流时服务器收到的数据瞬间爆发,然后断流。加上 -re,FFmpeg 会按文件的帧率匀速读取,模拟摄像头实时采集。
但要注意:-re 只对本地文件有效。如果输入源是摄像头或桌面采集,不需要加 -re,因为设备本身就是实时输出。
-re,结果画面延迟越来越大。后来发现 -re 强制限制了读取速度,而摄像头采集速度跟不上,导致缓冲区堆积。摄像头推流千万别加 -re。
-g:关键帧间隔
-g 设置两个关键帧(I 帧)之间的帧数。关键帧是完整的画面,后面的 P 帧和 B 帧只记录变化部分。关键帧间隔越大,压缩率越高,但 seek 和切换流的响应越慢。
推流时,-g 的值直接影响延迟和卡顿恢复速度。我一般这样设:
| 场景 | 推荐 -g 值 | 说明 |
|---|---|---|
| 互动直播 | 30-60 | 1-2 秒一个关键帧,延迟低 |
| 普通直播 | 60-120 | 2-4 秒一个关键帧,画质好 |
| 点播转推流 | 120-250 | 4-10 秒一个关键帧,压缩率高 |
# 互动直播:1 秒一个关键帧(假设 30fps)
ffmpeg -re -i input.mp4 -c:v libx264 -g 30 -f flv rtmp://...
# 普通直播:2 秒一个关键帧
ffmpeg -re -i input.mp4 -c:v libx264 -g 60 -f flv rtmp://...
-b:v:视频码率
-b:v 是视频的平均码率,单位是 bit/s。码率越高,画质越好,但带宽占用也越大。推流时,码率不能超过上行带宽的 70%,否则会卡顿。
我常用的码率参考:
| 分辨率 | 推荐码率 | 适用场景 |
|---|---|---|
| 480p | 500-800 Kbps | 移动端、低带宽 |
| 720p | 1.5-3 Mbps | 主流直播 |
| 1080p | 3-6 Mbps | 高清直播 |
| 4K | 15-30 Mbps | 超高清直播 |
-bufsize:码率控制缓冲区
-bufsize 是编码器的码率控制缓冲区大小。它和 -b:v 配合使用,决定码率的波动范围。简单说,-bufsize 越大,码率越平稳,但延迟越高;-bufsize 越小,码率波动大,但响应快。
我一般这样配:
# 平稳推流:bufsize 设为码率的 2 倍
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 2M -bufsize 4M -f flv rtmp://...
# 低延迟推流:bufsize 设为码率的 1 倍
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 2M -bufsize 2M -f flv rtmp://...
为什么 -bufsize 会影响延迟?你想想看,编码器先把数据攒到缓冲区,攒够了再发出去。缓冲区越大,攒的时间越长,延迟自然就高了。但缓冲区太小,码率波动大,画面会忽好忽坏。
-bufsize 设为 -b:v 的 1-2 倍。互动直播取 1 倍,普通直播取 2 倍。别超过 2 倍,否则延迟会明显增加。
参数组合实战
光讲单个参数没意思,我们来看几个完整的推流命令,感受一下参数怎么搭配。
场景一:互动直播(低延迟)
ffmpeg -re -i input.mp4 \
-c:v libx264 -b:v 2M -bufsize 2M -g 30 \
-c:a aac -b:a 128k \
-f flv rtmp://push.example.com/live/stream
关键帧间隔 1 秒(30fps),缓冲区等于码率,延迟控制在 1-2 秒。
场景二:高清直播(高画质)
ffmpeg -re -i input.mp4 \
-c:v libx264 -b:v 4M -bufsize 8M -g 120 \
-c:a aac -b:a 192k \
-f flv rtmp://push.example.com/live/stream
关键帧间隔 4 秒,缓冲区是码率的 2 倍,画质稳定,延迟 3-5 秒。
场景三:SRT 跨洋推流
ffmpeg -re -i input.mp4 \
-c:v libx264 -b:v 2M -bufsize 4M -g 60 \
-c:a aac -b:a 128k \
-f mpegts 'srt://push.example.com:10080?mode=caller&latency=500'
SRT 的 latency 设 500ms,给丢包重传留足时间。跨洋推流,延迟可以适当放宽。
-progress pipe: 可以实时查看推流状态,包括帧率、码率、丢包率。调试卡顿问题时,这个参数比看日志直观多了。
本章知识体系
下面这张图,把 FFmpeg 推流的核心要素串起来了。从输入源到输出协议,再到核心参数,每一步都影响最终的推流质量。
从输入源到输出,中间经过解码、编码参数调整、协议封装三个关键环节。每个环节的参数选择,都直接影响最终的推流质量。搞懂这张图,你就掌握了 FFmpeg 推流的骨架。