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
注意:RTMP 推流地址中的 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 的参数很多,但这两个是起步必调的。

协议选择口诀:互动直播用 RTMP,网页分发用 HLS,网络差或跨洋用 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 超高清直播
注意:码率不是越高越好。我曾经帮一个客户调 1080p 推流,他坚持设 10 Mbps,结果观众端疯狂缓冲。测了一下他的上行带宽只有 8 Mbps,码率设 6 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 推流核心要素 输入源 解码 / 解封装 编码参数(核心) -b:v 码率 -g 关键帧 -bufsize 缓冲 -re 实时 推流协议 RTMP (低延迟) HLS (高兼容) SRT (抗丢包) 推流输出

从输入源到输出,中间经过解码、编码参数调整、协议封装三个关键环节。每个环节的参数选择,都直接影响最终的推流质量。搞懂这张图,你就掌握了 FFmpeg 推流的骨架。