32位Qt项目集成FFmpeg 3.4 MinGW动态库实战指南
发布时间:2026/10/24 19:22:48 锦皓数字建站

简介ffmpeg-3.4-mingw32 是面向 32 位 Windows 平台、基于 MinGW32 编译环境构建的 FFmpeg 3.4 版本资源包适合需要在 Qt 项目中集成音视频编解码能力的 C/C 开发者以及希望免编译直接调用命令行工具处理多媒体的终端用户。压缩包为 7z 格式共 170 个文件整体约 2.62MB其中 107 个 h 头文件与 21 个 c 源文件构成二次开发所需的接口与示例基础6 个 dll、6 个 lib 及 6 个 def 提供动态与静态链接支持6 个 a 与 6 个 pc 文件便于 MinGW 环境下链接与 pkg-config 配置另有 2 个 exe 命令行程序、ffpreset 预设及 makefile、readme 等辅助内容。资源内含 transcode_aac、transcoding、muxing、demuxing_decoding 等示例源码可帮助读者理解封装、解封装、转码与 AAC 编码流程并借助 libavutil、libavcodec、libavformat、libavfilter、libswscale、libswresample 等模块完成自定义功能集成。目前已有 227 人学习下载适合作为 QtMinGW32 音视频开发的入门与排错参考。1. 32 位 Qt 项目卡在音视频解码上为什么我最后翻出了 ffmpeg-3.4-mingw32前阵子帮一个做工业上位机的朋友排查问题他的 Qt 程序在 64 位机器上跑得好好的一放到现场那台老工控机上就崩日志里全是avcodec_open2返回负值。折腾半天才定位到根因现场系统是 32 位的而他链接的 FFmpeg 库是 64 位 MinGW 编译出来的ABI 对不上。这种场景其实不少见——老旧设备、嵌入式面板、某些只提供 32 位驱动的采集卡都会把你逼回 32 位工具链。ffmpeg-3.4-mingw32 这个资源包就是针对这类需求准备的一套用 MinGW 32 位工具链编译好的 FFmpeg 3.4 动态库、头文件和配套的 pkg-config 文件能直接塞进 Qt 的.pro里用。它适合谁适合那些被 32 位环境锁死、又不想自己从零交叉编译 FFmpeg 的 Qt 开发者。下面我按实际拆包和集成的顺序把这份资源怎么用、参数怎么配、哪里容易翻车讲清楚。2. 拆开这个包MinGW 32 位 FFmpeg 3.4 的目录结构与链接模型2.1 目录里到底放了什么拿到一个预编译的 FFmpeg 包第一件事不是急着往 Qt 里塞而是先看清楚它的布局。常见的 MinGW 32 位发行包一般会按下面这种结构组织ffmpeg-3.4-mingw32/ ├── bin/ │ ├── avcodec-57.dll │ ├── avformat-57.dll │ ├── avutil-55.dll │ ├── swresample-2.dll │ ├── swscale-4.dll │ └── ffmpeg.exe / ffprobe.exe ├── include/ │ ├── libavcodec/ │ ├── libavformat/ │ ├── libavutil/ │ ├── libswresample/ │ └── libswscale/ ├── lib/ │ ├── libavcodec.dll.a │ ├── libavformat.dll.a │ ├── libavutil.dll.a │ ├── libswresample.dll.a │ └── libswscale.dll.a └── pkgconfig/ (可选) ├── libavcodec.pc └── ...这里有几个关键点值得展开。bin下的.dll是运行时真正干活的动态库版本号后缀57、55、2、4是 FFmpeg 3.4 这一代固定的 soname 主版本不能随便换。lib下的.dll.a是导入库MinGW 链接器靠它找到 DLL 里的符号它本身不包含实现代码所以体积很小。include是编译期需要的头文件Qt 工程里INCLUDEPATH要指到这里。提示如果你拿到的包里lib目录只有.a静态库而没有.dll.a那说明它是静态编译版本链接方式完全不同别混用。2.2 动态链接和静态链接32 位下怎么选在 32 位 MinGW 环境里动态链接和静态链接的取舍比 64 位更敏感。动态链接的优点是主程序体积小、多个模块可以共享同一份 DLL缺点是部署时必须把一堆 DLL 跟 exe 放在一起漏一个就启动失败。静态链接把代码全打进 exe部署干净但 32 位地址空间有限FFmpeg 全静态链接后 exe 动辄几十兆加载时内存压力明显。我一般建议如果是桌面工具类 Qt 程序用动态链接把 DLL 放bin目录同级如果是给现场工控机做的小型采集程序且只用到解码和缩放可以考虑静态链接裁掉不用的组件。ffmpeg-3.4-mingw32 这个包提供的是动态链接所需的.dll.a和.dll所以下面的集成步骤都按动态链接走。2.3 版本号背后的兼容性约束FFmpeg 3.4 对应的库版本是 libavcodec 57、libavformat 57、libavutil 55、libswresample 2、libswscale 4。这个版本组合是锁死的你不能拿 3.4 的头文件去配 4.x 的 DLL反之亦然。常见做法是在.pro里显式写死库名不要用通配符去匹配libav*否则升级环境时容易链到错误的版本。另外MinGW 32 位工具链本身也有版本差异老版本的 MinGW比如 5.x 系列和新版8.x 以上在 C ABI 上有细微差别如果 DLL 是用老工具链编的你的 Qt 也得用同代工具链否则会出现符号找不到的玄学问题。3. 把 FFmpeg 3.4 接进 Qt.pro 配置、头文件包含与首个解码 Demo3.1 .pro 文件里怎么写才不出错Qt 的.pro文件是 qmake 的入口FFmpeg 的路径和库都要在这里声明。下面是一个经过验证的配置模板假设你把 ffmpeg-3.4-mingw32 解压到了D:/libs/ffmpeg-3.4-mingw32# 工程配置32 位 MinGW 下链接 FFmpeg 3.4 动态库 QT core gui TARGET VideoProbe TEMPLATE app CONFIG c11 # 根据构建类型选择 debug 或 release 目录如果包里有区分 FFMPEG_ROOT D:/libs/ffmpeg-3.4-mingw32 # 头文件路径 INCLUDEPATH $$FFMPEG_ROOT/include # 导入库路径 LIBS -L$$FFMPEG_ROOT/lib # 显式链接五个核心库顺序不能乱 LIBS -lavformat -lavcodec -lavutil -lswresample -lswscale # 如果 MinGW 链接时报 undefined reference补上系统库 LIBS -lws2_32 -lsecur32 -lbcrypt -luser32 -ladvapi32逻辑说明INCLUDEPATH让编译器找到libavcodec/avcodec.h这类头文件。LIBS里的-L指定库搜索路径后面跟的-lavformat等会去找libavformat.dll.a。链接顺序很重要avformat依赖avcodecavcodec依赖avutil所以avformat要写在前面否则 MinGW 链接器可能报符号未定义。最后那串系统库是 FFmpeg 在 Windows 下用到的网络和加密相关依赖缺了会在链接阶段报错。参数说明FFMPEG_ROOT建议用绝对路径相对路径在 shadow build 下容易失效。如果你的包放在工程目录内可以用$$PWD/third_party/ffmpeg这种写法。3.2 第一个能跑的解码流程打开文件、找流、解码一帧配置好.pro之后写一段最小可运行代码验证链接是否成功。下面这段代码打开一个视频文件找到视频流解码出第一帧的宽高信息// main.cpp验证 FFmpeg 3.4 链接与基本解码流程 extern C { #include libavformat/avformat.h #include libavcodec/avcodec.h } #include QDebug int main(int argc, char *argv[]) { // 1. 注册所有组件FFmpeg 3.x 仍需手动调用 av_register_all(); AVFormatContext *fmtCtx nullptr; // 2. 打开输入文件 if (avformat_open_input(fmtCtx, test.mp4, nullptr, nullptr) ! 0) { qDebug() 打开文件失败; return -1; } // 3. 探测流信息 if (avformat_find_stream_info(fmtCtx, nullptr) 0) { qDebug() 找不到流信息; avformat_close_input(fmtCtx); return -1; } // 4. 找视频流索引 int videoIdx -1; for (unsigned i 0; i fmtCtx-nb_streams; i) { if (fmtCtx-streams[i]-codecpar-codec_type AVMEDIA_TYPE_VIDEO) { videoIdx i; break; } } if (videoIdx -1) { qDebug() 没有视频流; avformat_close_input(fmtCtx); return -1; } // 5. 用 codecpar 找解码器3.x 推荐方式 AVCodecParameters *par fmtCtx-streams[videoIdx]-codecpar; AVCodec *codec avcodec_find_decoder(par-codec_id); if (!codec) { qDebug() 找不到解码器; avformat_close_input(fmtCtx); return -1; } // 6. 分配解码上下文并打开 AVCodecContext *codecCtx avcodec_alloc_context3(codec); avcodec_parameters_to_context(codecCtx, par); if (avcodec_open2(codecCtx, codec, nullptr) 0) { qDebug() 打开解码器失败; avcodec_free_context(codecCtx); avformat_close_input(fmtCtx); return -1; } qDebug() 视频尺寸 codecCtx-width x codecCtx-height; // 7. 清理 avcodec_free_context(codecCtx); avformat_close_input(fmtCtx); return 0; }逻辑说明这段代码走的是 FFmpeg 3.x 的标准解码准备流程。av_register_all在 3.x 里必须调用4.0 之后才废弃。avformat_open_input打开容器avformat_find_stream_info读取流参数。找流时用codecpar-codec_type判断类型这是 3.x 引入的分离式参数结构比老版本直接读codecCtx更安全。avcodec_parameters_to_context把流参数拷贝到解码上下文最后avcodec_open2真正初始化解码器。参数说明avformat_open_input第三个参数可以指定输入格式传nullptr让 FFmpeg 自动探测。avcodec_alloc_context3传入找到的codec指针它会预填一些默认值。如果avcodec_open2返回负值常见原因是 DLL 版本不匹配或缺少依赖库用 Dependency Walker 类工具查一下avcodec-57.dll的依赖是否齐全。3.3 部署时 DLL 怎么放编译通过只是第一步运行时报「找不到 avcodec-57.dll」是新手最常翻的车。Qt 的 shadow build 会把 exe 生成在单独的目录里你需要把 ffmpeg-3.4-mingw32 的bin目录下所有 DLL 复制到 exe 同级目录。如果用了 Qt 的动态库还要把 Qt 的windeployqt跑一遍。我一般会在.pro里加一条自定义命令构建后自动拷贝# 构建后自动拷贝 FFmpeg DLL 到输出目录 win32 { FFMPEG_BIN $$FFMPEG_ROOT/bin DESTDIR_WIN $$replace(OUT_PWD, /, \\) QMAKE_POST_LINK $$quote(cmd /c copy /y $$replace(FFMPEG_BIN, /, \\)\\*.dll $$DESTDIR_WIN) }这段 qmake 脚本在链接完成后执行把bin下所有 DLL 复制到构建输出目录。注意路径分隔符要转成 Windows 反斜杠否则copy命令会失败。4. 避坑排查32 位 FFmpeg 3.4 集成时最容易翻车的五个点4.1 链接报 undefined reference toavcodec_register_all现象编译阶段就报一堆未定义符号全是avcodec_、avformat_开头的。原因通常是.pro里库的顺序写反了或者-L路径没指对链接器根本没找到.dll.a文件。解决先确认lib目录下确实有libavcodec.dll.a然后把-lavformat放在-lavcodec前面-lavcodec放在-lavutil前面。如果还不行在LIBS末尾加上-Wl,--enable-stdcall-fixup试试某些 MinGW 版本对符号修饰处理不一致。4.2 运行时报「无法定位程序输入点」于 avutil-55.dll现象exe 能启动但一调用 FFmpeg 函数就弹窗说找不到某个输入点。原因是你链接时用的头文件版本和运行时 DLL 版本不一致比如头文件是 3.4 的但 PATH 里混进了另一个版本的avutil-55.dll。解决把 ffmpeg-3.4-mingw32 的bin目录放在系统 PATH 最前面或者干脆把 DLL 拷到 exe 同级确保加载的是配套的那一份。用where avutil-55.dll命令可以查当前生效的是哪个。4.3 Qt 的 minGW 版本和 FFmpeg 编译工具链不匹配现象链接通过但运行时崩溃在avcodec_open2内部堆栈显示异常。原因FFmpeg 的 DLL 是用某个特定版本的 MinGW 编译的而你的 Qt 用的是另一个版本的 MinGW两者 C 运行时库msvcrt 或 ucrt不一致。解决查清楚 Qt 安装目录下Tools/mingwXX_32的版本号尽量找同代工具链编译的 FFmpeg 包。如果找不到用objdump -p avcodec-57.dll | findstr DLL Name看它依赖哪个运行时再决定是否换 Qt 工具链。4.4 32 位地址空间不足导致大文件解码失败现象解码小文件正常一上 1080p 长视频就报内存分配失败。原因32 位进程用户态地址空间只有 2GB 左右FFmpeg 解码时内部缓冲、帧队列加上 Qt 自身的开销很容易触顶。解决在avcodec_open2之前设置codecCtx-thread_count 1减少线程栈开销或者用av_dict_set传threads1。另外及时调用av_frame_free释放不再用的帧别攒着。如果还是不够只能考虑换 64 位方案32 位是硬上限。4.5 pkg-config 文件路径写死导致换机器就失效现象在自己机器上编译好好的换一台机器就报找不到 libavcodec。原因.pc文件里的prefix是绝对路径指向你本地的解压目录。解决要么不用 pkg-config直接在.pro里写路径要么在换机器后重新生成.pc文件把prefix改成新路径。我一般倾向于前者Qt 工程里显式写路径虽然土但可移植性反而更好。5. 进阶技巧用 ffprobe 快速验证包完整性以及一个我常备的检测脚本拿到任何一个预编译 FFmpeg 包在往工程里集成之前我习惯先用它自带的ffprobe.exe跑一遍确认这个包本身是完整可用的。这一步能省掉后面很多扯皮时间。具体做法是进入bin目录执行ffprobe -version看输出的configuration行里有没有--enable-shared有的话说明是动态库版本跟你手里的.dll.a对得上。然后随便找个视频文件跑ffprobe -show_streams test.mp4能正常输出 JSON 就说明解码组件没问题。下面这个 bash 脚本是我常备的放在包根目录跑一遍能快速检查关键文件是否齐全#!/bin/bash # check_ffmpeg_pkg.sh检查 ffmpeg-3.4-mingw32 包完整性 PKG_ROOT$(cd $(dirname $0) pwd) REQUIRED_DLLS(avcodec-57.dll avformat-57.dll avutil-55.dll swresample-2.dll swscale-4.dll) REQUIRED_LIBS(libavcodec.dll.a libavformat.dll.a libavutil.dll.a libswresample.dll.a libswscale.dll.a) echo 检查 bin 目录... for dll in ${REQUIRED_DLLS[]}; do if [ -f $PKG_ROOT/bin/$dll ]; then echo [OK] $dll else echo [缺失] $dll fi done echo 检查 lib 目录... for lib in ${REQUIRED_LIBS[]}; do if [ -f $PKG_ROOT/lib/$lib ]; then echo [OK] $lib else echo [缺失] $lib fi done echo 检查头文件... for header in libavcodec/avcodec.h libavformat/avformat.h libavutil/avutil.h; do if [ -f $PKG_ROOT/include/$header ]; then echo [OK] $header else echo [缺失] $header fi done逻辑说明脚本先定位自身所在目录作为包根目录然后分三组检查 DLL、导入库和头文件。每组用数组存文件名循环判断文件是否存在。输出里[OK]和[缺失]一目了然。参数说明如果你把包解压后改了目录名脚本不受影响因为它用的是dirname $0动态获取路径。在 Windows 的 Git Bash 里也能跑。跑完这个脚本如果全绿基本可以放心往 Qt 里集成如果有缺失先补文件再往下走别硬上。从那以后我每次拿到新的预编译包都强制走一遍这个检查省得在链接阶段浪费时间猜来猜去。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。