1. 为什么在 CentOS 7 上装 FFmpeg 值得单独写一篇
在 CentOS 7 上折腾 FFmpeg,看起来是个老生常谈的话题,但真正动手过的人都知道,这件事的坑远比想象中多。系统自带的软件源里根本没有 FFmpeg 的官方包,EPEL 和 RPM Fusion 虽然能提供,但版本往往停留在三年前,编解码器支持也残缺不全。你要是做视频转码、直播推流、音频提取、监控录像合成这类活儿,版本落后和功能缺失会直接卡住整个项目进度。
我自己第一次在 CentOS 7 上装 FFmpeg 是为了给一个批量视频处理服务做底层依赖。当时图省事直接yum install ffmpeg,结果装完发现连 H.264 编码都不支持,libx264压根没编进去,转出来的 MP4 文件体积大得离谱,画质还糊。后来换成源码编译,又踩了一堆依赖缺失、路径冲突、动态库找不到的坑。前后折腾了差不多两天,才把一套稳定可用的环境跑通。
这篇文章就是把我这些年反复在 CentOS 7 上部署 FFmpeg 的经验整理出来。不管你是刚接触 Linux 的新手,还是需要给生产环境搭一套可靠转码服务的老手,都能从里面找到可以直接抄的步骤和避坑指南。我会从方案选型讲到源码编译的每一个参数,再讲到装完之后怎么验证、怎么排查问题,尽量把每个"为什么"都说清楚。
2. 安装方案怎么选:三种路线的取舍分析
在 CentOS 7 上装 FFmpeg,主流就三条路:包管理器直接装、用第三方预编译包、源码编译。这三条路没有绝对的好坏,关键看你拿来干什么。我先把三种方案的差异摆出来,你再根据自己的场景对号入座。
2.1 三种安装方式对比
| 对比维度 | 包管理器安装 | 第三方预编译包 | 源码编译 |
|---|---|---|---|
| 操作难度 | 极低,一条命令 | 较低,加源即可 | 较高,需处理依赖 |
| 版本新旧 | 很旧,通常 2.x/3.x | 中等,看维护者 | 最新,自己控制 |
| 编解码器支持 | 残缺,缺 H.264/AAC | 较全 | 完全可控 |
| 硬件加速支持 | 基本没有 | 部分支持 | 可开启 NVENC/QSV |
| 升级维护 | 方便 | 方便 | 需重新编译 |
| 适合场景 | 临时测试 | 快速上线 | 生产环境、定制需求 |
包管理器安装最大的问题是版本和功能。CentOS 7 的 EPEL 源里 FFmpeg 版本长期停留在 2.8 或 3.4 附近,这个版本对现在的很多新编码格式支持很差。比如你想用libx265做 HEVC 编码,或者用libvpx-vp9做 WebM,大概率是找不到的。而且这些包在编译时为了规避专利问题,往往把 H.264 编码器直接砍掉了,只能解码不能编码,这对做转码服务的人来说是致命的。
第三方预编译包是个折中方案。有些社区维护的静态编译版本,把常用编解码器都打包进去了,解压就能用,省去了编译的麻烦。但问题在于你无法控制编译参数,硬件加速、特定滤镜、自定义模块这些需求满足不了,而且版本更新依赖维护者的节奏,万一哪天不维护了,你就被卡住了。
源码编译是最麻烦但最自由的路。你可以精确控制每一个编解码器的开关,可以针对 CPU 指令集做优化,可以开启 GPU 硬件加速,可以只编译你需要的模块来减小体积。生产环境我强烈建议走这条路,虽然前期投入时间多,但后面省心。
2.2 我的选型建议
如果你只是临时用一下,比如转个格式看看效果,那直接yum install ffmpeg配合 RPM Fusion 源就够了,别折腾。但如果你是要做长期运行的服务,比如视频网站的后台转码、直播平台的推流处理、安防系统的录像合成,那必须源码编译。
我自己的标准是:只要这个 FFmpeg 要跑超过一周,或者要处理超过 1000 个文件,就源码编译。因为一旦出问题,源码编译的环境你能完全掌控,日志、路径、依赖都清清楚楚,排查起来快得多。而包管理器装的版本,出了问题你连编译参数都看不到,只能干瞪眼。
还有一个容易被忽略的点:CentOS 7 的 glibc 版本是 2.17,这个版本比较老。有些第三方预编译包是在更新的系统上编译的,拿到 CentOS 7 上跑会报GLIBC_2.xx not found的错误。源码编译就没这个问题,因为是在本机编译的,链接的就是本机的库。
3. 源码编译前的环境准备与依赖梳理
源码编译 FFmpeg 最耗时的不是编译本身,而是依赖处理。FFmpeg 的依赖分两类:一类是编译工具链,一类是编解码库。工具链缺了直接编译失败,编解码库缺了不会报错,但编译出来的 FFmpeg 会缺少对应功能,这个更坑,因为你可能装完很久才发现某个格式不支持。
3.1 基础编译工具链安装
先把编译需要的基础工具装齐。这些包在 CentOS 7 的 base 源和 EPEL 源里都有,直接 yum 装就行。
# 先装 EPEL 源,很多依赖包在这里 yum install -y epel-release # 基础编译工具 yum install -y gcc gcc-c++ make cmake nasm yasm # 版本控制和解压工具 yum install -y git wget curl tar bzip2 xz # 开发库和头文件 yum install -y glibc-devel zlib-devel bzip2-devel这里有几个点要说明。nasm和yasm是汇编器,FFmpeg 里大量使用了汇编优化来提升性能,没有这两个,编译出来的 FFmpeg 性能会差一大截,尤其是视频编码这种计算密集型的活儿。cmake不是 FFmpeg 本身需要的,但很多第三方编解码库用它做构建系统,提前装上省事。
注意:CentOS 7 默认的 gcc 版本是 4.8.5,这个版本编译新版 FFmpeg 可能会遇到 C11 特性支持不全的问题。如果编译时报语法错误,考虑升级到 devtoolset 里的新版 gcc,具体方法后面会讲。
3.2 编解码库依赖清单
这部分是重点。FFmpeg 支持的编解码器非常多,但常用的就那么几个。我列一个生产环境必备的清单,以及每个库的作用和安装方式。
| 库名称 | 作用 | 是否必装 | 安装方式 |
|---|---|---|---|
| libx264 | H.264 视频编码 | 必装 | 源码编译 |
| libx265 | H.265/HEVC 视频编码 | 强烈建议 | 源码编译 |
| libvpx | VP8/VP9 视频编码 | 建议 | 源码编译 |
| libfdk-aac | AAC 音频编码 | 建议 | 源码编译 |
| libmp3lame | MP3 音频编码 | 建议 | 源码编译 |
| libopus | Opus 音频编码 | 建议 | 源码编译 |
| libass | 字幕渲染 | 按需 | yum 安装 |
| libfreetype | 字体渲染 | 按需 | yum 安装 |
为什么这些库大多要源码编译?因为 CentOS 7 的源里要么没有,要么版本太老。比如libx264,源里根本没有开发包,只能自己编。libfdk-aac因为授权问题,更不可能出现在官方源里。
这里我要特别说一下libfdk-aac。FFmpeg 自带的 AAC 编码器叫aac,质量一般,而libfdk-aac是公认质量最好的 AAC 编码器。如果你做音频转码,这个库值得单独编一下。但要注意它的授权协议比较特殊,商用需要留意。
3.3 依赖库的编译顺序
这些库之间有依赖关系,编译顺序不能乱。正确的顺序是:先编nasm/yasm(已经 yum 装了),然后libx264、libx265、libvpx、libfdk-aac、libmp3lame、libopus,最后编 FFmpeg。
每个库的编译套路都差不多:下载源码、configure、make、make install。我以libx264为例,把完整流程走一遍,其他库照葫芦画瓢。
# 下载 libx264 源码 cd /usr/local/src git clone https://code.videolan.org/videolan/x264.git cd x264 # 配置,开启共享库和位置无关代码 ./configure --enable-shared --enable-pic --prefix=/usr/local # 编译,-j 后面跟 CPU 核心数,加快速度 make -j$(nproc) # 安装 make install--enable-shared生成动态库,--enable-pic生成位置无关代码,这两个参数在 64 位系统上编译共享库时基本是必须的,不加的话后面链接 FFmpeg 会报错。--prefix=/usr/local指定安装路径,装到/usr/local下,这样系统默认的库搜索路径能找到。
装完之后还要让系统知道新库的位置:
# 把 /usr/local/lib 加入动态库搜索路径 echo "/usr/local/lib" > /etc/ld.so.conf.d/ffmpeg-deps.conf ldconfigldconfig这个命令很关键,它刷新系统的动态库缓存。很多人编译完 FFmpeg 运行时报error while loading shared libraries,就是因为忘了执行这一步。
4. FFmpeg 源码编译的完整实操流程
依赖都装好之后,就可以编 FFmpeg 本体了。这一步的 configure 参数最多,也最容易出错。我会把每个关键参数都解释清楚,你根据自己的需求增减。
4.1 下载与解压源码
FFmpeg 的官方源码发布在官网,也可以从代码托管平台克隆。生产环境建议用官方发布的稳定版压缩包,比直接克隆主分支稳定。
cd /usr/local/src wget https://ffmpeg.org/releases/ffmpeg-6.1.tar.xz tar -xf ffmpeg-6.1.tar.xz cd ffmpeg-6.1版本选择上,我一般选最新的稳定版。FFmpeg 的版本号是主版本.次版本的形式,比如 6.1、7.0。不建议用 git 主分支,因为主分支随时在变,可能引入未测试的改动。如果你需要某个特定功能只在主分支有,那再考虑克隆。
4.2 configure 参数逐项解析
configure 是编译 FFmpeg 最关键的一步,参数决定了最终产物的能力。我把生产环境常用的一套参数拆开讲。
./configure \ --prefix=/usr/local/ffmpeg \ --enable-shared \ --enable-pic \ --enable-gpl \ --enable-nonfree \ --enable-libx264 \ --enable-libx265 \ --enable-libvpx \ --enable-libfdk-aac \ --enable-libmp3lame \ --enable-libopus \ --enable-libass \ --enable-libfreetype \ --enable-postproc \ --enable-swscale \ --enable-avfilter \ --enable-pthreads \ --enable-runtime-cpudetect \ --disable-static \ --disable-debug \ --extra-cflags="-I/usr/local/include" \ --extra-ldflags="-L/usr/local/lib"逐个说这些参数的含义和取舍逻辑。
--prefix=/usr/local/ffmpeg指定安装路径。我习惯把 FFmpeg 单独装到一个目录,而不是混在/usr/local里,这样卸载和版本管理都方便。装完之后把/usr/local/ffmpeg/bin加到 PATH 里就行。
--enable-shared和--disable-static配合使用,生成动态库而不是静态库。动态库的好处是多个程序可以共享,节省内存,升级也方便。但如果你要做一个独立分发的工具,希望不依赖系统库,那就反过来用静态库。
--enable-gpl开启 GPL 协议下的功能,主要是libx264和libx265这些。不开这个,H.264 编码就用不了。--enable-nonfree开启非自由协议的功能,主要是libfdk-aac。这两个参数涉及授权问题,商用前要确认合规性。
--enable-libx264这一串就是开启对应的外部库支持。你装了哪个库就开哪个,没装的别开,否则 configure 会报错找不到库。
--enable-runtime-cpudetect让 FFmpeg 在运行时检测 CPU 支持的指令集,自动选择最优的代码路径。这个参数对性能影响很大,一定要开。
--extra-cflags和--extra-ldflags告诉编译器去哪里找我们装在/usr/local下的头文件和库。如果依赖装在别的路径,这里要相应修改。
4.3 编译与安装
configure 通过之后,就可以编译了。这一步比较耗时,取决于机器性能,一般十几分钟到半小时。
# 编译,-j 后面跟核心数 make -j$(nproc) # 安装 make install编译过程中如果报错,通常是某个依赖没装好或者路径不对。错误信息里会指明是哪个库找不到,回去检查那个库的安装。
装完之后配置环境变量:
# 把 FFmpeg 的 bin 目录加入 PATH echo 'export PATH=/usr/local/ffmpeg/bin:$PATH' >> /etc/profile.d/ffmpeg.sh source /etc/profile.d/ffmpeg.sh # 把 FFmpeg 的库目录加入动态库搜索路径 echo "/usr/local/ffmpeg/lib" > /etc/ld.so.conf.d/ffmpeg.conf ldconfig这里用/etc/profile.d/下的脚本而不是直接改/etc/profile,是为了保持配置的模块化,以后要卸载或者改路径,删掉这个文件就行,不会污染主配置文件。
4.4 验证安装结果
装完必须验证,不然你可能带着一个残缺的 FFmpeg 跑很久才发现问题。
# 查看版本 ffmpeg -version # 查看支持的编解码器 ffmpeg -codecs | grep -E "libx264|libx265|libvpx|libfdk" # 查看支持的封装格式 ffmpeg -formats | head -30ffmpeg -version的输出里会列出编译时开启的所有配置项,你可以对照 configure 参数检查有没有遗漏。ffmpeg -codecs会列出所有支持的编解码器,前面有E表示能编码,D表示能解码。确认libx264前面有E,说明 H.264 编码可用。
5. 装完之后的常见问题与排查实录
FFmpeg 装完不代表万事大吉,实际使用中会遇到各种问题。我把这些年踩过的坑整理成速查表,遇到问题先对照排查。
5.1 动态库找不到问题
这是最常见的问题,报错信息长这样:
ffmpeg: error while loading shared libraries: libavcodec.so.60: cannot open shared object file原因就一个:系统不知道你的 FFmpeg 库装在哪里。解决方法前面提过,就是配置ld.so.conf然后ldconfig。如果配了还不行,用ldd命令看看具体缺哪个库:
ldd $(which ffmpeg) | grep "not found"哪个库显示 not found,就去确认那个库有没有装、装在哪、有没有加入搜索路径。
5.2 编码器不可用问题
configure 时开了--enable-libx264,但用的时候报Unknown encoder 'libx264'。这种情况通常是编译时库没找到,但 configure 没报错。原因是 FFmpeg 的 configure 对某些库的检测比较宽松,找不到就静默跳过。
排查方法是看 configure 的输出日志,搜索libx264,看是enabled还是not found。如果是 not found,检查libx264的开发文件有没有装到正确位置,--extra-cflags路径对不对。
5.3 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 找不到共享库 | 库路径未配置 | 配 ld.so.conf 并 ldconfig |
| 编码器不存在 | 编译时库未找到 | 检查 configure 日志和库路径 |
| 编译报语法错误 | gcc 版本太老 | 升级 devtoolset |
| configure 报库找不到 | pkg-config 路径问题 | 设置 PKG_CONFIG_PATH |
| 运行报 GLIBC 版本错 | 系统 glibc 太老 | 源码编译而非用预编译包 |
| 转码速度极慢 | 未开汇编优化 | 确认 nasm/yasm 已装 |
5.4 升级 gcc 的实操方法
CentOS 7 的 gcc 4.8.5 编译新版 FFmpeg 有时会报错,比如不支持某些 C11 语法。解决办法是用 devtoolset 装新版 gcc。
# 安装 Software Collections 源 yum install -y centos-release-scl # 安装 devtoolset-9(包含 gcc 9) yum install -y devtoolset-9-gcc devtoolset-9-gcc-c++ # 启用新版 gcc scl enable devtoolset-9 bashscl enable只在当前 shell 生效,要永久生效就把它加到启动脚本里。启用后gcc --version会显示 9.x,这时候再编译 FFmpeg 就不会有语法问题了。
注意:用 devtoolset 编译出来的二进制,运行时可能依赖新版 libstdc++。如果要在其他机器上跑,记得把对应的库一起带上,或者用静态链接。
6. 生产环境的优化与维护经验
装好只是第一步,要让 FFmpeg 在生产环境稳定跑起来,还有一些优化和维护的细节要注意。
6.1 硬件加速的开启
如果你的服务器有 NVIDIA 显卡,可以开启 NVENC 硬件编码,转码速度能提升几倍到十几倍。这需要在 configure 时加--enable-nvenc和--enable-cuda-llvm,并且系统里要装好显卡驱动和 CUDA 工具包。
开启之后,编码时用-c:v h264_nvenc代替-c:v libx264,CPU 占用会大幅下降。但硬件编码的画质在同码率下通常不如软件编码,所以对画质要求高的场景要权衡。我的经验是,直播推流这种对延迟敏感、对画质要求相对宽松的场景用硬件编码,离线转码这种追求画质的场景用软件编码。
6.2 编译参数的性能调优
除了--enable-runtime-cpudetect,还可以针对特定 CPU 做优化。如果你的服务器 CPU 型号固定,可以在 configure 时加--cpu=haswell之类的参数,让编译器生成针对该架构优化的代码。但这会牺牲可移植性,换 CPU 就得重编。
另一个优化点是--disable-debug,去掉调试符号,能减小二进制体积,略微提升运行速度。生产环境建议加上。
6.3 版本管理与回滚
生产环境升级 FFmpeg 要谨慎,新版本可能引入行为变化。我的做法是保留多个版本,用软链接切换。
# 装到带版本号的目录 ./configure --prefix=/usr/local/ffmpeg-6.1 # ... 编译安装 ... # 用软链接指向当前版本 ln -sfn /usr/local/ffmpeg-6.1 /usr/local/ffmpeg这样升级时只要装新版本,然后改软链接指向,回滚就是改回去,几秒钟的事。PATH 和 ld.so.conf 里都配置指向/usr/local/ffmpeg这个软链接,不用改。
6.4 定期检查依赖库更新
FFmpeg 依赖的那些编解码库,偶尔会有安全更新或性能改进。建议每隔几个月检查一下,有重要更新就重新编译。特别是libx264和libvpx,这两个库的优化比较活跃。
检查方法就是去各库的代码仓库看提交记录,或者关注它们的发布页面。不用追得太勤,但重大版本更新值得跟进。
7. 我个人的几条实操心得
最后分享几条文档里不会写、但实际用起来很关键的经验。
第一条,编译前先确认磁盘空间。FFmpeg 源码加上编译中间文件,再加上各个依赖库,轻松占用几个 GB。/usr/local/src所在分区如果空间不够,编译到一半失败,清理起来很麻烦。我一般预留 10GB 以上。
第二条,make -j的核心数不是越多越好。核心数太多会导致内存不够,编译进程被系统杀掉,报一些莫名其妙的错误。经验值是核心数不超过内存 GB 数的一半。比如 8GB 内存的机器,-j4比较稳妥。
第三条,configure 的输出一定要仔细看。它会列出哪些功能 enabled、哪些 disabled、哪些 not found。很多人 configure 完直接 make,结果编出来缺功能。花两分钟扫一遍输出,能省后面几小时的排查。
第四条,测试要用真实素材。装完之后别只跑ffmpeg -version就完事,找几个实际的视频文件转一下,确认编码、解码、封装都正常。我遇到过版本信息正常但实际编码崩溃的情况,就是某个库链接有问题。
第五条,做好编译脚本。如果你要在多台机器上部署,把整个编译流程写成一个 shell 脚本,包括依赖安装、库编译、FFmpeg 编译、环境配置。这样新机器上跑一遍脚本就搞定,不用手动一步步来,也避免了遗漏。脚本里加上错误检查,哪一步失败就停下来报错,别让错误累积到最后才发现。