☰
Qt MinGW 32位下配置ffmpeg 3.4:从编译翻车到跑通
2026/10/31 11:19:40 网站建设 项目流程

简介:这份资源是面向32位Windows平台、基于MinGW32编译环境构建的FFmpeg 3.4版本,适合需要在Qt项目中集成音视频编解码能力的C/C++开发者,以及希望直接调用预编译库完成转码、封装、解封装等任务的终端用户。压缩包共170个文件,以h头文件与c示例源码为主,辅以def、a、lib、dll等导入库与动态库文件,另有pc配置、ffpreset预设及少量exe工具,整体约2.62MB,体积轻量便于嵌入工程。内容预览可见libavcodec、libavformat、libavfilter等模块的导入库,以及transcode_aac、muxing、demuxing_decoding等示例代码,可帮助读者快速理解各模块职责并对照编写调用逻辑。已有229人学习下载,适合作为Qt+MinGW32环境下音视频功能的集成参考。

1. 从一次 Qt 编译翻车说起:为什么我还在用 ffmpeg-3.4-mingw32

上周帮一个做桌面播放器的朋友收拾烂摊子。他在 Qt 5.9 的 MinGW 32 位环境里调视频解码,随手从网上拖了个 64 位的 ffmpeg 动态库塞进工程,结果ld直接报file format not recognized,换成静态库又冒出一堆undefined reference to av_register_all。折腾到半夜,最后发现根子不在代码,而在工具链位数和 ffmpeg 版本对不上。这类事我见得太多了:Qt mingw ffmpeg 32位 3.4 这套组合,看着老,但在不少存量项目、教学环境和老机器上仍然是刚需。装对了十分钟跑通,装错了能卡你一整天。这篇笔记就按我实际部署的顺序,把版本选择、目录摆放、.pro配置、验证和救火一条线写清楚,新手照着走,熟手看参数取舍。

2. 装前把环境钉死:Qt、MinGW 与 ffmpeg 3.4 的位数对齐

2.1 先确认你的 Qt 套件到底是哪一套 MinGW

很多人一上来就下载 ffmpeg,压根没看自己 Qt 用的是哪个编译器。Qt 安装器里带 MinGW 的套件通常长这样:Desktop Qt 5.9.8 MinGW 32bit、Desktop Qt 5.12.12 MinGW 64-bit。名字里那个32bit就是命门。打开 Qt Creator,进「工具 → 选项 → 构建和运行 → 构建套件」,看当前套件的「编译器」一栏,如果是MinGW 5.3.0 32bit之类,那你的整个工程就是 32 位目标,ffmpeg 必须给 32 位库。

我一般还会在命令行再核一遍,避免 Qt Creator 显示和实际不一致:

# 进入 Qt 自带的 MinGW 目录,确认 gcc 目标架构 gcc -dumpmachine # 32 位 MinGW 通常输出 i686-w64-mingw32 # 64 位则输出 x86_64-w64-mingw32

-dumpmachine输出里的i686就是 32 位铁证。这一步别省,我踩过「Qt Creator 套件写着 32bit、PATH 里却混进了另一个 64 位 gcc」的坑,编译时链接器悄悄用了错的,报错信息还特别玄学。确认完把 Qt 的 MinGWbin目录放到 PATH 最前面,后面所有命令都在这个 shell 里跑。

2.2 ffmpeg 3.4 的库文件构成,别只认一个 dll

ffmpeg 3.4 这套 mingw32 构建,核心是几组库:avcodec、avformat、avutil、swscale、swresample,外加可选的avfilter、avdevice、postproc。每个库都有静态.a和动态.dll+ 导入库.dll.a两种形态。Qt 工程里怎么选,直接决定你后面会不会被 dll 丢失搞疯。

文件类型典型文件名用途我的取舍
静态库libavcodec.a编进 exe,无运行时依赖小工具、单文件分发首选
导入库libavcodec.dll.a配合 dll 链接用动态方案必须
动态库avcodec-57.dll运行时加载多程序共用、体积敏感时用
头文件libavcodec/avcodec.h等编译期包含整个include目录都要

注意 ffmpeg 3.4 的主版本号是 57(avcodec)、57(avformat)、55(avutil),dll 名字里带这个数字,别拿 4.x 的avcodec-58.dll混进来,ABI 不兼容,运行时会直接崩在avcodec_open2。我一般把整套文件按「include / lib / bin」三目录摆好,后面配置路径时心里有数。

2.3 目录怎么摆,决定了 .pro 好不好写

我习惯在工程根目录下建一个third_party/ffmpeg,里面分三层:

your_project/ ├── third_party/ │ └── ffmpeg/ │ ├── include/ # 所有 .h,保持 avcodec/ avformat/ 等子目录结构 │ ├── lib/ # .a 或 .dll.a 导入库 │ └── bin/ # 运行时 dll(动态方案才需要) ├── your_project.pro └── main.cpp

这么摆的好处是.pro里路径短、可移植,换台机器把third_party整个拷过去就行。常见做法是把 ffmpeg 装到系统某个固定目录再配环境变量,但 Qt 工程我更倾向工程内自带,避免「这台机器能编、那台机器找不到头文件」的经典翻车。头文件目录一定要保留libavcodec/这一层,因为源码里写的是#include <libavcodec/avcodec.h>,你把 .h 全平铺到 include 根下反而编不过。

3. 落地安装与 .pro 配置:让 qmake 正确找到 32 位 ffmpeg 3.4

3.1 解压、校验、放位,三步别跳

拿到 ffmpeg-3.4-mingw32 的包之后,先别急着往工程里塞。我一般先解压到一个临时目录,核对位数和版本,再往third_party里搬:

# 解压到临时目录 unzip ffmpeg-3.4-mingw32.zip -d /tmp/ffcheck # 看 dll 的架构,32 位会显示 80386 或 i386 file /tmp/ffcheck/bin/avcodec-57.dll # 看静态库架构 file /tmp/ffcheck/lib/libavcodec.a

file输出里出现PE32 executable (DLL) (GUI) Intel 80386就是 32 位,出现PE32+或x86-64就是 64 位,直接换包。这一步花十秒,能省掉后面半小时的链接报错。校验通过后,把include、lib、bin分别拷进third_party/ffmpeg对应目录。动态方案记得把bin下的 dll 也拷到构建输出目录,或者后面在.pro里加拷贝规则。

3.2 .pro 里写对 INCLUDEPATH 和 LIBS 的顺序

Qt 工程链接 ffmpeg,核心就三行:头文件路径、库路径、库列表。但顺序和写法有讲究,写错了就是一堆 undefined reference。

# 头文件目录,指向 include 的上一层 INCLUDEPATH += $$PWD/third_party/ffmpeg/include # 库目录,静态库和导入库都放这 LIBS += -L$$PWD/third_party/ffmpeg/lib # 静态链接:按依赖顺序,avformat 依赖 avcodec,avcodec 依赖 avutil LIBS += -lavformat -lavcodec -lswscale -lswresample -lavutil # 如果用到滤镜和设备,再补 # LIBS += -lavfilter -lavdevice -lpostproc

$$PWD是 .pro 所在目录,用它拼相对路径,工程挪位置也不断。-L指定库搜索目录,-l后面跟库名去掉lib前缀和扩展名,比如libavformat.a写成-lavformat。顺序上,被依赖的库放后面:avformat用到avcodec,avcodec用到avutil,所以-lavutil压轴。GNU ld 对静态库是单遍扫描,顺序反了就会报undefined reference to av_malloc这类看着莫名其妙的错。

3.3 动态方案:导入库 + dll 拷贝规则

如果你选动态链接,LIBS里链接的是.dll.a导入库,运行时还得让 exe 找得到 dll。qmake 里加一段拷贝,省得每次手动拖:

# 动态方案:链接导入库(.dll.a 会被 -l 自动识别) LIBS += -lavformat -lavcodec -lswscale -lswresample -lavutil # 构建后把 dll 拷到输出目录 FFMPEG_BIN = $$PWD/third_party/ffmpeg/bin DESTDIR_WIN = $$replace(OUT_PWD, /, \\) QMAKE_POST_LINK += $$quote(cmd /c copy /y \"$$replace(FFMPEG_BIN, /, \\)\\*.dll\" \"$$DESTDIR_WIN\")

QMAKE_POST_LINK在链接完成后执行,copy /y覆盖已有文件。$$replace(..., /, \\)是把 qmake 的正斜杠路径转成 Windows 反斜杠,不转的话cmd有时认不出。这段在 MinGW 的 make 下能跑,因为最终调的是系统cmd。动态方案的好处是多个程序共用一套 dll,坏处是分发时漏一个 dll 就启动失败,所以后面验证环节我会专门查依赖。

3.4 编译前先跑一个最小验证程序

别等整个工程编完才发现库没链上。我习惯先写个十几行的main.cpp,只调一个 ffmpeg 函数,确认工具链通了再往上堆业务代码:

#include <libavcodec/avcodec.h> #include <libavutil/avutil.h> #include <cstdio> int main() { // 打印 ffmpeg 版本,确认链接的是 3.4 这套 printf("avcodec version: %u\n", avcodec_version()); printf("avutil version: %u\n", avutil_version()); // 3.4 对应 avcodec 57.x,avutil 55.x return 0; }

avcodec_version()返回的是major<<16 | minor<<8 | micro拼出来的整数,3.4 系列 avcodec 主版本 57,打印出来高位应该是 57。跑通这个再写解码逻辑,出问题范围小、好定位。这一步我强烈建议保留在工程里当冒烟测试,换机器、换库版本时先跑它。

4. 避坑与排查:ffmpeg 3.4 + MinGW 32 位最常见的五处翻车

4.1 现象:链接报undefined reference to av_register_all

原因多半是库顺序写反,或者只链了avcodec没链avformat。av_register_all在 3.4 里属于avformat,而avformat又依赖avcodec、avutil。解决:把LIBS改成-lavformat -lavcodec -lavutil这个从高到低的顺序,-lavutil放最后。如果还报,检查是不是混进了 64 位库,file libavformat.a看一眼架构。

4.2 现象:编译过、运行崩,提示找不到avcodec-57.dll

原因:动态方案下 dll 没跟 exe 放一起,或者放的是 64 位 dll。解决:把third_party/ffmpeg/bin下所有*-57.dll、*-55.dll拷到 exe 同目录;用file确认每个 dll 都是 32 位。我一般还会用objdump -p your.exe | grep "DLL Name"列出 exe 依赖的所有 dll,逐个核对是否存在,比盲猜快。

4.3 现象:#include <libavcodec/avcodec.h>报 No such file

原因:INCLUDEPATH指到了include/libavcodec这一层,而不是include。源码里的路径是带libavcodec/前缀的,所以INCLUDEPATH必须指到它的上一层。解决:改成INCLUDEPATH += $$PWD/third_party/ffmpeg/include,并确认include下确实有libavcodec子目录。

4.4 现象:qmake 生成 Makefile 后,链接器仍去系统路径找库

原因:PATH 或系统环境里存在另一套 ffmpeg,-L的优先级被盖过,或者LIBS里混了绝对路径的旧库。解决:在.pro里把-L$$PWD/third_party/ffmpeg/lib放在所有-L最前面;执行qmake后打开生成的Makefile,搜LIBS看实际展开的路径对不对。这一步是排查链接问题的黑匣子,别嫌麻烦。

4.5 现象:静态链接后 exe 体积暴涨、或报重复符号

原因:静态库把整个avformat拉进来,体积自然大;重复符号通常是同时链了静态库和导入库。解决:二选一,静态方案只留.a,动态方案只留.dll.a,别把两种都放lib目录让-l自己猜。体积敏感的话,ffmpeg 3.4 支持编译期裁剪,但现成 mingw32 包一般没裁,接受现实或者自己重编。

5. 装完怎么验证跑通:三步确认这套 32 位 ffmpeg 3.4 真的能用

第一步,跑 3.4 节那个版本打印程序,确认avcodec_version()高位是 57、avutil_version()高位是 55。数字对不上,说明链的不是这套库,回去查LIBS和-L顺序。第二步,写个最小解封装验证:用avformat_open_input打开一个本地 mp4,打印nb_streams和第一条视频流的codec_id,能正常输出就说明avformat+avcodec的运行时链路是通的。第三步,动态方案下把 exe 单独拷到一个干净目录(不带 Qt 的 bin),双击运行,能起来且不报 dll 缺失,才算真正可分发。

我一般还会留一张对照表在工程 README 里,换机器时逐项打勾:

检查项期望值命令/位置
编译器架构i686-w64-mingw32gcc -dumpmachine
avcodec 主版本57版本打印程序
avutil 主版本55版本打印程序
dll 架构PE32 / 80386file *.dll
exe 依赖 dll全部存在于同目录`objdump -p exe

这套流程走下来,Qt mingw ffmpeg 32位 3.4 的环境基本就钉死了。说个血泪经验:我有次图省事,直接把 64 位 ffmpeg 的 include 和 32 位 lib 混着用,编译期一点不报,运行到avcodec_alloc_context3才崩,查了大半天。从那以后我每次配这套环境,都强制先跑file核架构、再跑版本打印程序,两步不过绝不往下写业务代码。希望帮到你,少走我走过的弯路。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询