4、实战推流:使用FFmpeg推流本地文件、使用FFmpeg推流摄像头、使用FFmpeg推流桌面
好,到了真正动手的时候了。
前面几章我们把RTSP协议、FFmpeg基础、SDP格式都过了一遍。说实话,光看理论容易犯困。我自己学的时候也是这样——看文档看得眼皮打架,一打开终端敲命令反而精神了。
这一章我们就来点实在的。三种最常见的推流场景:本地文件、摄像头、桌面。我会把每个命令拆开讲,告诉你每个参数是干嘛的,踩过哪些坑。
本章核心目标:用FFmpeg把三种不同来源的媒体数据,通过RTSP协议推送到流媒体服务器。
4.1 推流前的准备工作
在开始之前,你得确认几件事。嗯,都是我在项目里吃过亏才养成的习惯。
- FFmpeg已安装:终端输入
ffmpeg -version,能看到版本号就行。我建议用4.4以上版本,对RTSP支持更稳定。 - RTSP服务器已启动:我们用的是EasyDarwin或ZLMediaKit。确保服务端监听端口(默认554)是通的。
- 网络连通性:推流端和服务器之间不要有防火墙拦着。我曾经在客户现场排查了俩小时,最后发现是安全组没开端口。
小技巧:先用 telnet 服务器IP 554 测试一下端口通不通。不通的话,后面所有操作都是白费力气。
4.2 使用FFmpeg推流本地文件
这是最基础、也最常用的场景。比如你想把一个录好的视频文件,模拟成实时直播流。
4.2.1 基本命令
ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://192.168.1.100:554/live/test
来,我们拆开看看每个参数的意思:
| 参数 | 含义 | 为什么重要 |
|---|---|---|
-re |
以原始帧率读取 | 不加这个,文件会以最快速度推完,根本不像直播 |
-i input.mp4 |
指定输入文件 | 支持mp4、flv、ts等常见格式 |
-c copy |
直接复制编码数据 | 不重新编码,CPU占用极低 |
-f rtsp |
指定输出格式为RTSP | 告诉FFmpeg我们要走RTSP协议 |
rtsp://... |
推流目标地址 | 路径可以自定义,方便区分不同流 |
注意:-c copy 虽然快,但要求源文件的编码格式能被RTSP容器支持。如果遇到花屏或无法播放,试试换成 -c:v libx264 -c:a aac 重新编码。
4.2.2 循环推流
有时候你想让一个短视频循环播放,模拟24小时不间断直播。加个 -stream_loop -1 就行:
ffmpeg -re -stream_loop -1 -i short_clip.mp4 -c copy -f rtsp rtsp://192.168.1.100:554/live/loop
这里 -1 表示无限循环。我做过一个数字标牌项目,就是用这个方式让广告视频循环推流的。跑了三个月没出过问题。
4.2.3 推流时叠加时间戳
做监控回放或测试时,我习惯在画面上叠加时间戳,方便定位问题:
ffmpeg -re -i input.mp4 -vf "drawtext=text='%{localtime}':fontsize=24:fontcolor=white:x=10:y=10" -c:v libx264 -c:a aac -f rtsp rtsp://192.168.1.100:554/live/timestamp
这个命令会重新编码视频(因为加了滤镜),CPU会高一些。但调试时很有用。
4.3 使用FFmpeg推流摄像头
摄像头推流是安防、直播、远程监控的核心场景。说实话,这里坑最多。
4.3.1 查看可用设备
先看看系统认不认你的摄像头:
- Linux:
v4l2-ctl --list-devices或ls /dev/video* - Windows:
ffmpeg -list_devices true -f dshow -i dummy - macOS:
ffmpeg -f avfoundation -list_devices true -i ""
我记得第一次在Linux上搞摄像头,忘了加载 v4l2 驱动,折腾了半天才发现设备节点都没出来。
4.3.2 Linux下推流USB摄像头
ffmpeg -f v4l2 -i /dev/video0 -f alsa -i hw:0,0 -c:v libx264 -c:a aac -f rtsp rtsp://192.168.1.100:554/live/cam
参数说明:
-f v4l2:指定视频输入格式为V4L2-i /dev/video0:摄像头设备节点-f alsa -i hw:0,0:音频设备(如果摄像头不带麦克风可以去掉)
经验之谈:USB摄像头默认分辨率可能很高,推流会卡。建议加 -s 640x480 或 -s 1280x720 限制分辨率。帧率用 -r 15 或 -r 25。
4.3.3 Windows下推流摄像头
ffmpeg -f dshow -i video="USB Camera" -f dshow -i audio="Microphone" -c:v libx264 -c:a aac -f rtsp rtsp://192.168.1.100:554/live/cam
Windows用dshow(DirectShow)驱动。设备名要用引号括起来,名字可以从 -list_devices 的输出里复制。
4.3.4 摄像头推流的常见问题
| 问题 | 原因 | 解决办法 |
|---|---|---|
| 画面卡顿 | 分辨率太高或帧率太大 | 降低 -s 和 -r,或者加 -preset ultrafast |
| 没有画面 | 设备被占用或驱动不对 | 检查 ls /dev/video*,关闭其他摄像头应用 |
| 延迟很大 | 编码缓冲太大 | 加 -tune zerolatency 参数 |
| 音频视频不同步 | 采样率或时间基不一致 | 显式指定 -ar 44100 -ac 2 |
4.4 使用FFmpeg推流桌面
桌面推流常用于游戏直播、远程培训、软件演示。说白了就是把屏幕上的内容实时编码推出去。
4.4.1 Linux下推流桌面(X11)
ffmpeg -f x11grab -s 1920x1080 -i :0.0 -f alsa -i hw:0,0 -c:v libx264 -c:a aac -f rtsp rtsp://192.168.1.100:554/live/desktop
关键参数:
-f x11grab:抓取X11桌面-s 1920x1080:抓取区域大小-i :0.0:显示器编号,:0.0是主显示器
注意:如果是在SSH远程会话里,x11grab 抓不到画面。必须在本机或VNC会话中运行。我曾经在服务器上远程执行这个命令,等了半天发现推出去的是黑屏。
4.4.2 Windows下推流桌面(gdigrab)
ffmpeg -f gdigrab -i desktop -f dshow -i audio="Microphone" -c:v libx264 -c:a aac -f rtsp rtsp://192.168.1.100:554/live/desktop
Windows用 gdigrab 抓屏。如果想只抓某个窗口,把 -i desktop 换成 -i title="窗口标题" 就行。
4.4.3 macOS下推流桌面(avfoundation)
ffmpeg -f avfoundation -i "1" -f avfoundation -i ":0" -c:v libx264 -c:a aac -f rtsp rtsp://192.168.1.100:554/live/desktop
macOS用avfoundation。数字 1 代表屏幕(0是摄像头),:0 代表麦克风。
4.4.4 桌面推流的性能优化
桌面推流最吃CPU。你想想看,每秒要抓取、编码1920x1080的画面,还要保证流畅。我建议:
- 降低帧率:
-r 10或-r 15,非游戏场景足够了 - 使用硬件编码:加
-c:v h264_nvenc(NVIDIA)或-c:v h264_amf(AMD) - 限制码率:
-b:v 2M,避免网络波动 - 开启 ultrafast preset:
-preset ultrafast,牺牲压缩率换速度
ffmpeg -f x11grab -s 1920x1080 -i :0.0 -c:v h264_nvenc -preset p1 -b:v 2M -r 15 -f rtsp rtsp://192.168.1.100:554/live/desktop
这个命令用了NVIDIA硬件编码,CPU占用从90%降到了20%左右。效果很明显。
4.5 三种推流场景对比
| 场景 | 输入方式 | 典型用途 | CPU负载 | 延迟 |
|---|---|---|---|---|
| 本地文件 | -i file.mp4 |
视频点播转直播、循环播放 | 低(-c copy) |
低 |
| 摄像头 | -f v4l2 / -f dshow |
安防监控、视频会议 | 中 | 中 |
| 桌面 | -f x11grab / -f gdigrab |
游戏直播、远程培训 | 高 | 较高 |
4.6 本章知识体系
下面这张图把三种推流场景的流程和关键参数串起来了。你可以把它当作速查手册。
4.7 避坑指南
最后,分享几个我踩过的坑。嗯,都是真金白银换来的教训。
- 路径不要有中文:FFmpeg对中文路径支持不好,有时候会莫名其妙报错。我习惯全部用英文路径。
- 推流地址要唯一:同一个RTSP路径只能有一个推流端。如果第二个推流端用相同路径,第一个会被踢掉。我在一次线上直播中犯过这个错,画面突然断了,观众全在刷问号。
- 网络断开后不会自动重连:FFmpeg推流时如果网络断了,它不会自动重试。需要自己写脚本监控进程,或者用
-reconnect参数(部分版本支持)。 - 音频设备别搞错:推摄像头时如果音频设备选错了,推出去只有画面没有声音。先用
-list_devices确认设备名。
我的习惯:每次推流前,先用 ffplay 测试一下输入源是否正常。比如 ffplay -f v4l2 -i /dev/video0,能看到画面再推。这一步能省下大量排查时间。