3. 推流基础命令:FFmpeg推流命令结构、常用参数解析、推流到RTMP服务器
推流这件事,说白了就是把本地视频数据打包成网络能传的格式,然后扔给服务器。很多新手一上来就复制网上的命令,跑通了就以为完事了。等真遇到卡顿、花屏、延迟高的时候,完全不知道从哪下手。
我个人习惯是,先搞懂命令的骨架,再往里填参数。这样出了问题,你至少知道是哪个环节的锅。
3.1 推流命令的基本骨架
FFmpeg 的推流命令,结构其实很固定。我把它拆成四个部分:
ffmpeg [输入参数] -i [输入源] [滤镜参数] [编码参数] [输出参数] [推流地址]
嗯,就这么简单。但每个部分都能玩出花来。我们看一个最基础的例子:
ffmpeg -re -i input.mp4 -c:v libx264 -b:v 2000k -c:a aac -b:a 128k -f flv rtmp://live.example.com/live/streamkey
这条命令做了什么事?
- -re:以原始帧率读取。不加这个,FFmpeg 会以最快速度推完,几秒钟就把视频全推出去,服务器直接懵掉。
- -i input.mp4:指定输入文件。
- -c:v libx264:视频编码器用 H.264。RTMP 推流基本都用这个。
- -b:v 2000k:视频码率 2Mbps。
- -c:a aac:音频编码器用 AAC。
- -b:a 128k:音频码率 128kbps。
- -f flv:输出封装格式为 FLV。RTMP 协议只认 FLV 封装。
- rtmp://...:推流目标地址。
核心要点:RTMP 推流必须用 FLV 封装,这是协议规定的。你用 MP4 封装推 RTMP,FFmpeg 会直接报错。
3.2 常用参数深度解析
参数这东西,光背没用。你得知道每个参数在真实场景里会带来什么影响。我挑几个最容易出问题的讲讲。
3.2.1 -re:推流的"节流阀"
这个参数太容易被忽略了。不加 -re,FFmpeg 会以解码速度推流。你想想看,一个 10 分钟的视频,可能 10 秒就推完了。服务器收到的数据是突发的,客户端播放器根本来不及缓冲。
我曾经在调试一个直播项目时,发现推流端 CPU 占用率极低,但播放端卡得不行。查了半天,就是忘了加 -re。加上之后,一切正常。
小技巧:如果你推的是摄像头或桌面采集等实时源,不需要加 -re。因为实时源本身就是按真实时间产生数据的。
3.2.2 -b:v 与 -maxrate/-bufsize:码率控制的铁三角
很多人只设 -b:v,觉得码率就稳了。其实不然。VBR(可变码率)模式下,码率会剧烈波动。对于 RTMP 这种对带宽敏感的场景,波动大了就容易卡顿。
我建议你这样配:
-b:v 2000k -maxrate 2200k -bufsize 4000k
这样码率会被限制在 2000k 附近,峰值不超过 2200k。bufsize 设成两倍码率,给编码器一点缓冲空间。
| 参数 | 作用 | 我常用的值 |
|---|---|---|
| -b:v | 目标码率 | 根据分辨率定,1080p 一般 2000-4000k |
| -maxrate | 最大码率 | 目标码率的 1.1~1.2 倍 |
| -bufsize | 编码器缓冲区大小 | 目标码率的 2 倍 |
3.2.3 -g:关键帧间隔
这个参数直接影响播放端的起播速度和卡顿恢复速度。关键帧(I帧)是播放器解码的起点。如果关键帧间隔太长,播放器切换画面或网络波动后,要等很久才能恢复。
对于直播场景,我一般设 -g 60,也就是 2 秒一个关键帧(假设帧率 30fps)。太短了会浪费码率,太长了影响体验。
注意:有些 RTMP 服务器会强制覆盖关键帧间隔。比如某些 CDN 要求 -g 不能超过 120。推流前最好确认一下服务端的限制。
3.3 推流到 RTMP 服务器的完整示例
光说不练假把式。我们来看几个真实场景的命令。
3.3.1 推流本地文件
ffmpeg -re -i /path/to/video.mp4 \
-c:v libx264 -preset veryfast -tune zerolatency \
-b:v 2500k -maxrate 2750k -bufsize 5000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 128k -ar 44100 \
-f flv rtmp://your-server.com/live/streamkey
这里我加了 -preset veryfast 和 -tune zerolatency。preset 控制编码速度和压缩率的平衡。直播场景用 veryfast 或 faster 就够了,没必要用 slow,CPU 扛不住。tune zerolatency 是专门为低延迟场景优化的。
3.3.2 推流摄像头或桌面
ffmpeg -f v4l2 -i /dev/video0 \
-f alsa -i hw:0,0 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-b:v 1500k -maxrate 1650k -bufsize 3000k \
-g 30 -keyint_min 30 \
-c:a aac -b:a 96k \
-f flv rtmp://your-server.com/live/streamkey
注意这里没有 -re,因为摄像头是实时源。preset 我用了 ultrafast,因为实时编码对延迟要求更高。关键帧间隔也缩短到 1 秒(30帧),方便播放器快速切换。
3.4 推流命令的完整流程
为了让你更直观地理解整个推流过程,我画了一张流程图。
从这张图可以清楚看到,推流不是简单的"读文件-发出去"。中间经历了解封装、解码、滤镜、编码、再封装,最后才通过 RTMP 协议发送。每一步都可能成为瓶颈。
3.5 避坑指南:我踩过的那些坑
做流媒体这些年,我在推流命令上栽过不少跟头。分享几个典型的:
- 忘记加 -re:这个前面说过了。我曾经在给客户做演示时,视频 3 秒就推完了,播放端黑屏。场面一度非常尴尬。
- 码率设得太高:有一次推 4K 视频,码率设了 20Mbps。结果推流端 CPU 跑满,网络也扛不住,播放端卡成幻灯片。后来老老实实降到 8Mbps,配合 -preset fast,才稳定下来。
- 音频采样率不匹配:RTMP 服务器一般只支持 44100Hz 或 48000Hz。我试过推 22050Hz 的音频,服务器直接拒绝连接。加个 -ar 44100 就解决了。
- 关键帧间隔设成 250:默认值。直播场景下,播放器要等 8 秒才能出画面。用户早跑了。
我的调试习惯:每次改参数后,先用 ffprobe 检查输出流的码率、帧率、关键帧间隔。确认没问题再正式推流。这个习惯帮我省了不少排查时间。
3.6 推流命令的调试技巧
命令写好了,怎么知道它跑得对不对?我一般用这几个方法:
- 看日志:FFmpeg 默认会输出编码进度和错误信息。重点关注
speed=字段。如果是实时推流,speed 应该接近 1x。如果远大于 1,说明没加 -re 或者输入源有问题。 - 用 ffprobe 验证:推流过程中,另开一个终端用
ffprobe rtmp://your-server.com/live/streamkey查看实际输出流的参数。 - 抓包分析:如果怀疑网络问题,用 tcpdump 或 Wireshark 抓 RTMP 包,看是否有丢包或重传。
嗯,推流基础命令就讲到这里。这些参数和技巧,你在后面的章节里会反复用到。尤其是卡顿排查时,很多问题都能追溯到命令参数设置不当。先把基础打牢,后面遇到问题才能快速定位。