4、RTSP 推流实战:从本地文件到桌面屏幕
推流这件事,说白了就是把一路视频信号打包成 RTSP 流,扔给网络上的客户端去消费。我做了这么多年流媒体,发现很多新手上来就对着摄像头推流,结果花屏、卡顿、延迟全来了。其实从本地文件开始练手,是最稳妥的路径。
这一章咱们就按「文件 → 摄像头 → 桌面」的顺序,把三种推流场景都跑一遍。最后我会分享几个调优参数,都是我在线上环境踩坑换来的经验。
本章核心脉络:先掌握基础推流命令,再理解参数背后的原理,最后能根据场景自主调优。
4.1 推送本地视频文件
这是最基础的场景,也是我建议初学者第一个练手的命令。你不需要摄像头,不需要屏幕采集,只要一个 MP4 文件就能跑通全流程。
先看一个最简命令:
ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://192.168.1.100:8554/live/test
这里 -re 是关键。它的作用是「按原始帧率读取」。不加这个参数,FFmpeg 会以最快速度把文件读完然后推出去,客户端看到的画面就像开了 100 倍速。我见过有人调试半天,最后发现只是忘了加 -re,画面一闪而过。
但 -c copy 有个限制——它直接复用文件里的编码格式。如果文件是 H.264,推出去就是 H.264;如果是 MPEG-2,推出去就是 MPEG-2。很多 RTSP 客户端只认 H.264,所以更稳妥的做法是显式转码:
ffmpeg -re -i input.mp4 -c:v libx264 -preset ultrafast -tune zerolatency -c:a aac -f rtsp rtsp://192.168.1.100:8554/live/test
我的习惯:调试阶段先用 -c copy 验证网络和 RTSP 服务是否正常,确认通了再换成转码参数。这样能快速定位问题出在编码还是网络。
4.2 推送摄像头实时流
摄像头推流是生产环境最常用的场景。不同操作系统下的设备名不一样,我列个表方便你对照:
| 操作系统 | 输入格式 | 典型设备名 | 示例命令片段 |
|---|---|---|---|
| Linux | v4l2 | /dev/video0 | -f v4l2 -i /dev/video0 |
| Windows | dshow | 视频: USB Camera | -f dshow -i video="USB Camera" |
| macOS | avfoundation | 0 (内置摄像头) | -f avfoundation -i 0 |
以 Linux 为例,完整的推流命令:
ffmpeg -f v4l2 -framerate 30 -video_size 1280x720 -i /dev/video0 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-f rtsp rtsp://192.168.1.100:8554/live/cam
这里我加了 -framerate 和 -video_size,目的是让 FFmpeg 明确知道摄像头的采集参数。如果不指定,有些摄像头会以默认最低分辨率输出,画面糊得没法看。
我曾经踩过的坑:在 Windows 上用 dshow 推流时,如果摄像头被其他应用(比如、Zoom)占用,FFmpeg 会直接报错退出。解决方案是推流前先检查设备占用,或者用 -list_options true 列出所有可用设备。
4.3 推送桌面屏幕
屏幕推流常用于直播教学、游戏直播或远程演示。不同平台的采集方式差异很大:
- Windows:使用
gdigrab,可以抓取整个桌面或指定窗口 - macOS:使用
avfoundation,配合capture_screen参数 - Linux (X11):使用
x11grab,指定屏幕坐标和尺寸
Windows 下抓取全屏的典型命令:
ffmpeg -f gdigrab -framerate 30 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop \
-c:v libx264 -preset ultrafast -tune zerolatency \
-f rtsp rtsp://192.168.1.100:8554/live/screen
如果只想抓取某个窗口,把 -i desktop 换成 -i title "窗口标题" 即可。我经常用这个功能做软件演示,只推应用窗口,不暴露桌面上的其他内容。
macOS 下的命令稍有不同:
ffmpeg -f avfoundation -framerate 30 -capture_cursor 1 -i 1:0 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-f rtsp rtsp://192.168.1.100:8554/live/screen
注意 -i 1:0 的含义:第一个数字是屏幕索引,第二个是麦克风索引。如果不需要音频,写成 -i 1 就行。
性能提示:屏幕推流对 CPU 压力很大,尤其是 4K 分辨率。我建议先用 -framerate 15 或 -video_size 1280x720 降低采集负载,等确认流程没问题再逐步提高。
4.4 推流参数调优技巧
参数调优是推流质量的分水岭。同样的摄像头,参数调好了延迟 200ms,调不好延迟 2 秒。下面这几个参数是我每次必调的:
| 参数 | 作用 | 推荐值 | 我的经验 |
|---|---|---|---|
-rtsp_transport tcp |
强制使用 TCP 传输 | tcp | UDP 在公网环境下丢包严重,TCP 虽然增加延迟但稳定得多 |
-g |
设置 GOP 大小(关键帧间隔) | 30-60 | 值越小延迟越低,但码率会上升。直播场景我一般设 30 |
-bufsize |
编码器缓冲区大小 | 与 bitrate 相同或 2 倍 | 设太大导致延迟飙升,设太小画面频繁波动 |
-preset |
编码速度与压缩率权衡 | ultrafast / veryfast | 实时推流别用 slow,CPU 扛不住 |
-tune zerolatency |
针对低延迟场景优化 | zerolatency | 这个参数能显著减少编码缓存,我几乎每个推流命令都加 |
一个综合调优后的完整命令示例:
ffmpeg -f v4l2 -framerate 30 -video_size 1280x720 -i /dev/video0 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-b:v 2000k -bufsize 2000k -g 30 \
-rtsp_transport tcp \
-f rtsp rtsp://192.168.1.100:8554/live/cam
注意:-rtsp_transport tcp 必须放在输出参数位置(-f rtsp 之前),放在输入参数位置不会生效。这个顺序问题我至少帮三个同事排查过。
最后说一个容易被忽略的点——网络带宽。你推 4K 流,但上行带宽只有 5Mbps,那再怎么调参数也没用。我一般会在推流前用 iperf3 测一下端到端的可用带宽,确保编码码率不超过带宽的 70%。留点余量,网络抖动时不会直接断流。
嗯,推流实战的核心就这些。从文件到摄像头再到桌面,命令结构其实是一样的,区别只在于输入源的采集方式。参数调优也不是玄学,理解每个参数在做什么,你就能根据场景灵活组合。