使用 FFmpeg 实现 RTMP 推流:从入门到精通

在实时音视频传输领域,RTMP(Real-Time Messaging Protocol)协议曾经是流媒体领域的绝对霸主。虽然在新兴的低延迟协议(如 WebRTC、SRT)面前,其地位有所动摇,但 RTMP 凭借其成熟、稳定和广泛的兼容性,至今仍然是直播推流中最常用、最通用的协议之一。无论是推流到各大直播平台(如 Bilibili、抖音、Twitch、YouTube),还是使用 Adobe Media Server、Nginx-rtmp-module 等自建流媒体服务器,RTMP 都是核心选择。

FFmpeg,作为功能强大的多媒体处理开源软件,不仅能进行视频转码、剪辑,更是命令行下进行流媒体推流的利器。本文将详细讲解如何利用 FFmpeg 的命令行工具,高效、稳定地将本地视频文件或实时屏幕/摄像头画面通过 RTMP 协议推送出去。

目录#

  1. 环境准备
  2. 基础推流概念
  3. 推流实战:从本地文件推流
  4. 推流实战:实时采集推流
  5. 常见问题与最佳实践
  6. 总结
  7. 参考资料

环境准备#

在开始之前,请确保你的系统已经安装了 FFmpeg。

  • Windows: 从 FFmpeg 官网 下载可执行文件,并将其所在目录添加到系统的 PATH 环境变量中。
  • macOS: 使用 Homebrew 安装:brew install ffmpeg
  • Linux (Ubuntu/Debian): 使用 apt 安装:sudo apt update && sudo apt install ffmpeg

安装完成后,在终端或命令提示符中输入 ffmpeg -version,如果显示版本信息,则说明安装成功。

基础推流概念#

一个典型的 RTMP 推流命令可以简化为以下结构:

ffmpeg [全局参数] [输入参数] -i [输入源] [输出参数] [输出地址]
  • 输入源(-i): 可以是本地视频文件、设备(如摄像头 video=设备名)、屏幕(如 desktop)或者网络流。
  • 输出地址: 你的 RTMP 服务器地址,通常格式为 rtmp://server-ip-or-domain/app-name/stream-key
    • app-name: 应用名称,服务器上配置的应用程序标识。
    • stream-key: 流密钥,用于唯一标识一个直播流。
  • 编码参数: 决定推流视频和音频的质量、码率、帧率等。例如 -c:v libx264 指定视频编码器为 H.264。

推流实战:从本地文件推流#

这是最常见的场景,常用于视频回放或定时直播。

3.1 最简单的推流命令#

ffmpeg -re -i input.mp4 -c copy -f flv "rtmp://your-rtmp-server/live/streamkey"
  • -re: 非常重要! 以原始帧率读取输入文件。如果不加此参数,FFmpeg 会以最快速度处理并推流,导致服务器端在极短时间内接收完整个视频。
  • -c copy: 直接流复制,不进行重新编码。这意味着视频和音频流将从输入文件原封不动地复制到输出。这是最节省 CPU 资源的方式,但要求输入文件的编码格式(通常是 H.264/AAC)必须符合 RTMP/FLV 的标准。
  • -f flv: 强制指定输出格式为 FLV。虽然 RTMP 通常承载 FLV 格式的数据,但显式指定是一个好习惯。

3.2 指定音视频编码参数#

如果输入文件的格式不符合要求,或者你需要调整视频质量,就需要进行重新编码。

ffmpeg -re -i input.mov \
-c:v libx264 -preset veryfast -tune zerolatency \
-c:a aac -b:a 128k \
-f flv "rtmp://your-rtmp-server/live/streamkey"
  • -c:v libx264: 使用软件编码器 libx264 将视频编码为 H.264 格式。
  • -preset veryfast: 指定编码速度与压缩率的平衡。veryfast 编码速度快,但压缩率稍低(文件稍大)。对于直播,通常使用 veryfast, superfast, ultrafast 以保证低延迟。
  • -tune zerolatency: 优化编码设置以实现最小延迟,这对直播至关重要。
  • -c:a aac: 将音频编码为 AAC 格式。
  • -b:a 128k: 设置音频码率为 128 kbps。

3.3 控制输出质量和大小#

通过指定视频码率、分辨率、帧率来控制直播流的体积和质量。

ffmpeg -re -i input.mp4 \
-c:v libx264 -preset veryfast -tune zerolatency \
-b:v 2500k -maxrate 2500k -bufsize 5000k \
-vf "scale=1280:720" -r 30 \
-c:a aac -b:a 128k \
-f flv "rtmp://your-rtmp-server/live/streamkey"
  • -b:v 2500k: 设置视频的目标平均码率为 2500 kbps。
  • -maxrate 2500k: 设置最大码率。
  • -bufsize 5000k: 设置码率控制缓冲器的大小,通常为 -b:v 的两倍。这三个参数共同作用,实现 VBR(动态码率)控制。
  • -vf "scale=1280:720": 使用视频滤镜(video filter)将视频缩放至 1280x720 分辨率。
  • -r 30: 强制设置输出帧率为 30 FPS。

3.4 使用硬件加速#

软件编码(libx264)对 CPU 消耗较大。如果你的设备有硬件编码器(如 NVIDIA NVENC, Intel QSV, AMD AMF),可以极大降低 CPU 负载。

NVIDIA GPU (NVENC) 示例:

ffmpeg -re -i input.mp4 \
-c:v h264_nvenc -preset p4 -b:v 2500k \
-c:a aac -b:a 128k \
-f flv "rtmp://your-rtmp-server/live/streamkey"
  • -c:v h264_nvenc: 使用 NVIDIA 硬件 H.264 编码器。
  • -preset p4: NVENC 的预设,p4 是平衡速度和质量的常用选择(可选 p1p7, p1 最快)。

Intel Quick Sync Video (QSV) 示例:

ffmpeg -re -i input.mp4 \
-c:v h264_qsv -b:v 2500k \
-c:a aac -b:a 128k \
-f flv "rtmp://your-rtmp-server/live/streamkey"

推流实战:实时采集推流#

4.1 屏幕录制推流#

macOS 示例:

ffmpeg -f avfoundation -i "1:0" \
-c:v libx264 -preset veryfast -tune zerolatency \
-b:v 2500k -vf "scale=1280:720" -r 30 \
-c:a aac -b:a 128k \
-f flv "rtmp://your-rtmp-server/live/streamkey"
  • -f avfoundation: macOS 下的采集格式。
  • -i "1:0": 1 通常代表显示器(可通过 ffmpeg -f avfoundation -list_devices true -i "" 查看设备列表),0 代表音频设备(如麦克风)。

Windows 示例 (使用 gdigrab):

ffmpeg -f gdigrab -i desktop \
-c:v libx264 -preset veryfast -tune zerolatency \
-b:v 2500k -vf "scale=1280:720" -r 30 \
-c:a aac -b:a 128k \
-f flv "rtmp://your-rtmp-server/live/streamkey"
  • -f gdigrab: Windows 下的桌面捕获设备。
  • -i desktop: 捕获整个桌面。

4.2 摄像头推流#

Linux 示例 (使用 v4l2):

ffmpeg -f v4l2 -i /dev/video0 \
-c:v libx264 -preset veryfast -tune zerolatency \
-b:v 2500k -vf "scale=1280:720" -r 30 \
-c:a aac -b:a 128k \
-f flv "rtmp://your-rtmp-server/live/streamkey"
  • -f v4l2: Linux 下的视频采集框架。
  • -i /dev/video0: 摄像头设备文件。

常见问题与最佳实践#

5.1 推流地址与流密钥#

  • 安全第一: 流密钥相当于直播的密码,切勿泄露。不要在版本控制(如 Git)中提交包含真实流密钥的脚本。
  • 环境变量: 推荐将推流地址设置为环境变量。
    # 在终端中设置
    export RTMP_URL="rtmp://your-server/live/your-secret-key"
    # 在命令中使用
    ffmpeg ... -f flv "$RTMP_URL"

5.2 保持长连接与重连#

网络不稳定时,推流可能会中断。可以编写一个简单的 Shell 脚本来实现自动重连。

#!/bin/bash
RTMP_URL="rtmp://your-server/live/streamkey"
while true
do
    ffmpeg -re -i input.mp4 -c copy -f flv "$RTMP_URL"
    echo "Stream disconnected. Retrying in 5 seconds..."
    sleep 5
done

5.3 日志输出与调试#

  • -loglevel warning: 减少日志输出,只显示警告和错误,使输出更清晰。
  • -loglevel debug: 输出最详细的调试信息,用于排查复杂问题。
  • 如果推流失败,首先检查日志中的错误信息,通常是地址错误、编码器不支持或网络不通。

5.4 常用滤镜(Filter)应用#

FFmpeg 的滤镜功能强大,可以在推流前对画面进行处理。

  • 添加水印:
    -vf "movie=watermark.png [watermark]; [in][watermark] overlay=10:10 [out]"
    # 或者更简单的语法(如果水印是PNG带透明度)
    -i watermark.png -filter_complex "overlay=10:10"
  • 绘制文字 (例如显示当前时间):
    -vf "drawtext=text='%{localtime}': fontcolor=white: fontsize=24: box=1: [email protected]: boxborderw=5: x=10: y=10"

总结#

FFmpeg 是命令行下进行 RTMP 推流的瑞士军刀,通过灵活的参数组合,可以满足从文件推流到实时采集的各种需求。掌握其核心参数(如 -re, -c, -b:v, -vf)和编码器选择(软编 vs 硬编),是构建稳定、高效直播推流流程的关键。

希望本篇博客能帮助你深入理解并熟练使用 FFmpeg 进行 RTMP 推流。


参考资料#

  1. FFmpeg 官方文档
  2. FFmpeg Wiki: Encoding for streaming sites
  3. FFmpeg Wiki: Capture/Desktop
  4. X264 Encoding Guide
  5. NVIDIA FFmpeg Transcoding Guide