源码包里是七个库加三个程序,不是一个程序。 七个库的版本号各走各的,看见 codec 62 配 filter 11 不是配错了。
这是全课第一篇,先把「要编的东西到底是什么」定下来。 1.2 开始才动手装工具链;这一节只认结构,不敲命令。
一、源码包里有什么:七个库加三个程序
下载页上那个 ffmpeg-5.0.tar.xz,解开是一堆目录,不是安装包。 打开看,顶层目录名字就是库名:libavcodec、libavformat、libavutil、libavfilter、libavdevice、 libswscale、libswresample,再加 libpostproc、compat、doc、tests 这几个。 编译的产物是「七个库 + 三个 exe」,不是一个大程序。 目录 编出什么 谁在用
libavutil libavutil-60.dll 所有库的地基,内存与数学 libavcodec libavcodec-62.dll 编解码器,五百多个 libavformat libavformat-62.dll 封装解封装,认容器 libavfilter libavfilter-11.dll 滤镜,四百多个 libavdevice libavdevice-62.dll 摄像头、声卡、屏幕 libswscale libswscale-9.dll 像素格式与缩放 libswresample libswresample-6.dll 音频重采样
三个程序是 ffmpeg、ffprobe、ffplay:前者转码,中间那个看信息,后者是播放器。 它们只是调用这七个库的外壳,加起来几千行,而七个库加起来上百万行。 所以「我要用 FFmpeg」这句话有歧义。 想敲命令,装三个 exe 就够; 想写程序,要的是七个库的头文件与导入库——这正是本书的主题。
二、版本号为什么不齐步走
本机这套号可以直接当尺子用: 库 版本 主版本
libavcodec 62.28.102 62 libavformat 62.12.102 62 libavutil 60.26.102 60 libavfilter 11.14.102 11 libavdevice 62.3.102 62 libswscale 9.5.102 9 libswresample 6.3.102 6
三段号各有含义:主版本在接口不兼容时涨,次版本在加新接口时涨,末位是补丁。 所以「主版本一样就能对上」这句话只对同一代构建成立。 七个库互不等待。 libavfilter 接口稳定,二十来年才到 11;libavcodec 天天加新编码器,已经 62。 这不是版本错乱,是各记各的账。 看见别人的教程写「我用的是 4.4」,你手里是 8.0,先别看版本号,先看那篇教程里的函数还在不在。 函数签名才是硬约束,版本号只是线索。
三、许可证:为什么一开 x264 就变成 GPL
FFmpeg 核心是 LGPL,可它一旦接上 GPL 的零件,整个产物就变 GPL。 开关 含义 后果
默认 LGPL 2.1+ 可以动态链接闭源程序 --enable-gpl 启用 GPL 零件 整个产物变 GPL --enable-nonfree 启用不可再分发零件 产物不可分发 --enable-libx264 用 x264(GPL) 必须同时开 gpl
x264 是 GPL 的,所以 --enable-libx264 与 --enable-gpl 必须成对出现。
只开前者,configure 直接报错;两个都开,你的整个 DLL 就成了 GPL 产物,闭源商用要另买授权。
这条不是道德问题,是工程问题。 做内部工具随便编;做卖给客户的产品,签合同前先把这条查清楚。
2026 现状:教材写的 5.0 里 libavresample 还在,这个库在 5.0 被删了,
重采样只剩 libswresample 一条路。
照老教程写 --enable-avresample 会得到一个「不认识这个选项」的警告。
四、从源码到可用,中间有四道工序
configure → make → make install → 写代码链接。 四步,一步都省不掉。 步 干的事 失败的典型症状
configure 探环境、生成 Makefile 报某个库没找到 make 真编译 报某个 .c 语法错或链接错 make install 拷到 --prefix 目录 报权限不足 链接 用头文件 + 导入库编自己的程序 报未定义符号
这四步对应四种完全不同的报错,分不清就会在错的层里找原因。configure 找不到库,是路径问题; make 报语法错,是编译器版本问题;链接报未定义符号,是头文件与库对不上。 本课后面每条命令都标它属于哪一步,就是为了让你看见报错时知道该往哪看。
五、动手 Demo:源码里到底有几个库——本机七个版本的实测
沙箱里没有 ffmpeg.exe,但有 PyAV 绑定的同一套 libav*。 所以下面这些版本号是真的,只是通过 Python 拿到的。
import av
duty = {
"libavutil": "内存、数学、像素格式,所有库的地基",
"libavcodec": "编解码器总库",
"libavfilter": "滤镜",
}
for k, v in sorted(av.library_versions.items()):
print("%-14s %d.%d.%d" % (k, v[0], v[1], v[2]), duty.get(k, ""))
实跑输出:
--------------------------------------------------------------------
源码包里到底有几个库——本机七个版本的实测
--------------------------------------------------------------------
**① 教材说的「八大金刚」,本机能点出名字的只有七个**
库 版本 主版本 管什么
---------------------------------------------------------------------------------
libavcodec 62.28.102 62 编解码器总库,五百多个都在这层
libavdevice 62.3.102 62 采集设备,摄像头与声卡
libavfilter 11.14.102 11 滤镜,四百多个都在这层
libavformat 62.12.102 62 封装与解封装,认得出 mp4、flv、ts
libavutil 60.26.102 60 内存、数学、像素格式,所有库的地基
libswresample 6.3.102 6 音频重采样
libswscale 9.5.102 9 像素格式转换与缩放
**本机没有 libpostproc。** 它负责后处理(去块效应那类),新版 FFmpeg 里已经很少有人编它,
PyAV 的构建也没带。
**② 七个版本号不齐步走**
codec 是 **62**,filter 只有 **11**,swscale 才 **9**。
每个库自己记自己接口改过多少次,改得多涨得快,谁也不等谁。
所以看见版本表里「codec 62 却配 filter 11」不是配错了,本来就该这样。
**③ 这套号对应 FFmpeg 8.0 系**(教材成书时是 5.0,codec 是 59),差三个大版本。
后面凡是讲接口,都按本机这套号核过再写。
**④ 源码包就是这七八个目录**:libavcodec、libavformat、libavutil、libavfilter、libavdevice、
libswscale、libswresample,加上 libpostproc 与 compat、tests、doc。编出来的就是这些。
**所以「编译 FFmpeg」不是编一个程序,是编七个库加三个 exe。**
记住这一点,后面看到 `--disable-everything` 之类的开关才不会懵——那些开关关的是某些库里的某些零件,
不是关整个东西。
七行版本号,本机只点得出七项,没有 libpostproc。 这不是装漏了,是 PyAV 的构建根本没编它。
30 秒实验
python -c "import av; print(av.library_versions)"把七行号打出来,对照本节表格,看主版本对不对得上。- 找一个网上的 FFmpeg 教程,看它写的
av_register_all()还在不在本文的 API 表里——这个函数在 5.0 被删了,老教程遍地都是它。 ls一遍 FFmpeg 源码顶层目录,数出几个以 lib 开头的目录名。
常见误区
- 以为「装 FFmpeg」就是装一个程序。 装 exe 只能敲命令;要写代码,得装七个库的头文件与导入库。
- 看见版本号不一致就以为装坏了。 七个库各走各的版本,codec 62 配 filter 11 是正常状态。
- 开了 --enable-gpl 还打算闭源发布。 产物已经是 GPL,要么开源,要么换零件,要么买授权。
自测三问(点开对答案)
1. 七个库的版本号里,哪一个最可能先涨? —— libavcodec。它天天加新编码器与解码器,接口变更最频繁,本机已经到了 62。 2. 为什么本机点不出 libpostproc? —— 它负责后处理,新版里编的人少,PyAV 这套构建没带。缺它不影响转码与滤镜,只影响去块效应那类后处理。 3. 教材写的 5.0 与本机的 8.0 差三个大版本,学的时候要注意什么? —— 注意函数是否还在。5.0 删掉了 av_register_all 与 libavresample,8.0 又删了一批老接口,照老教程抄会直接编译不过。- ☐ (本节完,下一节 1.2.1 MinGW 简介)