2. FFmpeg 环境搭建:工欲善其事,必先利其器

做流媒体开发,环境搭建是第一道坎。我记得刚入行那会儿,光编译 FFmpeg 就折腾了两天,各种依赖报错看得人头皮发麻。这一章我把 Windows 和 Linux 两种环境下的安装方法都捋一遍,再附上我平时最常用的命令速查表,最后聊聊 FFmpeg 的组件架构——搞懂这些,后面推流拉流才不会抓瞎。

2.1 Windows 下 FFmpeg 安装

Windows 用户图省事,直接下载编译好的二进制包就行。我个人习惯用 gyan.dev 的构建版本,更新及时,稳定性也不错。

安装步骤

  1. 打开浏览器,访问 https://www.gyan.dev/ffmpeg/builds/
  2. 下载 ffmpeg-release-full.7z 或 ffmpeg-release-essentials.7z(full 版包含更多编码器)
  3. 解压到 C:\ffmpeg 目录
  4. 将 C:\ffmpeg\bin 添加到系统环境变量 Path 中
  5. 打开 cmd,输入 ffmpeg -version 验证
我的小技巧: 解压后我会把 ffmpeg.exe、ffprobe.exe、ffplay.exe 这三个文件单独复制到 C:\Windows\System32 里。这样不用配环境变量也能直接用,省事。

验证安装

C:\Users\dev> ffmpeg -version
ffmpeg version 6.1.1-full_build-www.gyan.dev
Copyright (c) 2000-2023 the FFmpeg developers
built with gcc 13.2.0 (Rev5, Built by MSYS2 project)

看到版本信息就说明装好了。如果提示 不是内部或外部命令,多半是环境变量没生效,重启 cmd 或者重启电脑试试。

2.2 Linux 下 FFmpeg 编译安装

Linux 环境我强烈建议源码编译。为什么?因为发行版自带的 FFmpeg 通常阉割了太多功能——比如不支持 libx264、libx265,甚至没有 RTSP 协议支持。你想想看,做流媒体开发连这些都没有,那还玩什么?

编译前的依赖准备

以 Ubuntu/Debian 为例,先把依赖装齐:

sudo apt update
sudo apt install -y \
  autoconf automake build-essential cmake git \
  libass-dev libfreetype6-dev libsdl2-dev libtool \
  libva-dev libvdpau-dev libvorbis-dev libxcb1-dev \
  libxcb-shm0-dev libxcb-xfixes0-dev \
  pkg-config texinfo wget zlib1g-dev \
  nasm yasm libx264-dev libx265-dev libvpx-dev \
  libfdk-aac-dev libmp3lame-dev libopus-dev
注意: 我曾经在 CentOS 上编译 FFmpeg,结果发现 nasm 版本太旧,导致 x264 编码器编译失败。后来我改用 yum install nasm 升级到 2.14 以上才解决。所以编译前一定检查一下汇编器版本。

编译 FFmpeg

# 下载源码
wget https://ffmpeg.org/releases/ffmpeg-6.1.1.tar.bz2
tar -xjf ffmpeg-6.1.1.tar.bz2
cd ffmpeg-6.1.1

# 配置编译选项
./configure \
  --prefix=/usr/local/ffmpeg \
  --enable-gpl \
  --enable-nonfree \
  --enable-libx264 \
  --enable-libx265 \
  --enable-libfdk-aac \
  --enable-libmp3lame \
  --enable-libopus \
  --enable-libvpx \
  --enable-libass \
  --enable-libfreetype \
  --enable-libvorbis \
  --enable-pthreads \
  --enable-version3 \
  --extra-cflags="-I/usr/local/include" \
  --extra-ldflags="-L/usr/local/lib"

# 编译(建议用多核加速)
make -j$(nproc)

# 安装
sudo make install

编译过程大概 10-20 分钟,取决于机器性能。我习惯把 --prefix 指定到 /usr/local/ffmpeg,这样不会污染系统自带的 ffmpeg。

配置环境变量

echo 'export PATH=/usr/local/ffmpeg/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
ffmpeg -version

验证关键编码器:

ffmpeg -encoders | grep -E "libx264|libx265|libfdk_aac"
ffmpeg -protocols | grep rtsp

如果能看到 libx264、libx265、rtsp 等输出,说明编译成功。

2.3 FFmpeg 常用命令速查

下面这张表是我平时用得最多的命令,做流媒体开发基本够用。我把它贴在工位上,省得每次都要翻文档。

功能 命令示例 说明
查看媒体信息 ffprobe input.mp4 显示视频/音频编码、码率、分辨率等
格式转换 ffmpeg -i input.avi output.mp4 自动选择编码器,最常用
提取音频 ffmpeg -i input.mp4 -vn -acodec copy output.aac -vn 表示不要视频
截取片段 ffmpeg -i input.mp4 -ss 00:01:00 -t 30 output.mp4 从第1分钟开始,截取30秒
缩放分辨率 ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4 -vf 是视频滤镜
RTSP 推流 ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://server/live/stream -re 按原始帧率读取
RTSP 拉流 ffmpeg -i rtsp://server/live/stream -c copy output.mp4 直接保存为本地文件
屏幕录制 ffmpeg -f gdigrab -i desktop output.mp4 Windows 下可用
推流到 RTMP ffmpeg -re -i input.mp4 -c copy -f flv rtmp://server/live/stream 直播平台常用
我的习惯: 调试 RTSP 推流时,我会先用 ffplay rtsp://... 拉流看看能不能正常播放。如果 ffplay 能播,那问题多半在推流端;如果 ffplay 也播不了,那就是网络或服务器的问题了。

2.4 FFmpeg 组件架构

FFmpeg 不是一个单体程序,而是一套库的集合。搞懂这些组件,你才能知道出了问题该查哪个模块。说白了,就像修车你得知道发动机、变速箱、刹车各管什么。

下面这张图是我自己画的 FFmpeg 组件架构图,把核心库和它们之间的关系理清楚了:

FFmpeg 核心组件架构 ffmpeg(命令行工具) ffprobe(媒体分析工具) ffplay(播放器工具) libavformat 封装/解封装(MP4、FLV、RTSP…) libavcodec 编解码(H.264、AAC、MP3…) libavutil 工具函数(内存、数学、日志…) libswscale 图像缩放/色彩空间转换 libswresample 音频重采样/格式转换 libavfilter 滤镜(缩放、裁剪、叠加…) 数据流方向:输入 → libavformat 解封装 → libavcodec 解码 → 滤镜处理 → libavcodec 编码 → libavformat 封装 → 输出 libavutil 为所有组件提供基础支持,libswscale/libswresample 处理格式转换

各组件详解

  • libavformat:负责封装和解封装。说白了就是处理容器格式——MP4、FLV、TS、RTSP 流这些。我遇到过一个问题:用 FFmpeg 推 RTSP 流时,客户端一直连不上,后来发现是 -f rtsp 参数没加,libavformat 默认用了 flv 格式,当然推不出去。
  • libavcodec:编解码核心。H.264、H.265、AAC、MP3 这些编码器都在这里。注意,有些编码器(如 libx264)是外部库,需要编译时开启 --enable-libx264。
  • libavutil:工具库。提供内存管理、数学运算、日志系统、CRC 校验等基础功能。其他所有组件都依赖它,相当于 FFmpeg 的“地基”。
  • libswscale:图像缩放和色彩空间转换。比如把 1920x1080 缩到 1280x720,或者把 YUV420P 转成 RGB24。
  • libswresample:音频重采样。比如把 44100Hz 的音频转成 48000Hz,或者把 16 位整型转成 32 位浮点。
  • libavfilter:滤镜系统。视频缩放、裁剪、加水印、画中画,音频混音、延迟、降噪,全在这里。

一句话总结:

你输入一个视频文件,libavformat 负责拆开包装,libavcodec 负责解码里面的内容,libswscale/libswresample 负责格式转换,libavfilter 负责加特效,最后 libavcodec 重新编码,libavformat 重新打包输出。整个流程就像一条流水线,每个组件各司其职。

组件依赖关系

组件 依赖 说明
libavformat libavcodec, libavutil 解封装时需要解码器信息
libavcodec libavutil 编解码需要工具函数支持
libavfilter libavutil, libswscale, libswresample 滤镜处理需要格式转换
libswscale libavutil 图像处理需要内存分配
libswresample libavutil 音频处理需要数学运算
避坑提醒: 我曾经在交叉编译 FFmpeg 到 ARM 平台时,发现 libavformat 无法解析 RTSP 流。查了半天,原来是编译时忘了加 --enable-network 和 --enable-protocol=rtsp。这两个选项默认是开启的,但如果你用了 --disable-everything 再手动开启某些功能,很容易漏掉网络协议支持。切记!

环境搭好了,组件也搞懂了,后面我们就可以正式开始 RTSP 推流和拉流的实战了。嗯,先把基础打牢,后面才走得稳。