FFmpeg 3.4 + MinGW-w32 静态编译与CLion集成实践 简介面向32位Windows与Qt/Mingw开发者的FFmpeg 3.4轻量编译包采用MinGW32构建适合在资源受限环境中完成音视频解码、转码与播放集成。压缩包共170个文件大小仅2.62MB以C/C头文件h、库文件dll、a、lib、def、示例源码c及ffpreset配置为主并附带ffmpeg、ffplay可执行文件和编译配置便于直接调用或二次开发。已有225人学习下载。该版本在保留H.264/H.265/AAC等主流格式支持的基础上针对解码链路做了优化占用更小同时提供libavcodec、libavformat等核心库的导入库与头文件配合Qt工程可快速搭建多媒体播放器或格式转换工具。内含transcode_aac、muxing、demuxing_decoding等经典示例适合入门者理解FFmpeg调用逻辑也适合开发者作为裁剪定制的基础。 手里有个老项目要用 FFmpeg 做视频处理翻出旧压缩包一看版本是 ffmpeg-3.4-mingw32这个“老版本 MinGW-w32 工具链”的组合老玩家应该都不陌生。如果你正好也在 Windows 上折腾 FFmpeg或者想在 CLion 里集成一套干净的 C 语言视频处理库又或者只是想把 m3u8 转成 mp4、修复一个破损的 AVI 文件那这篇笔记应该能帮你少走不少弯路。FFmpeg 3.4 是 2017 年发布的版本放在今天肯定不是最新但它稳定、API 相对保守很多嵌入式项目、老旧系统和商业化软件至今还在用。而 MinGW-w32 环境编出来的静态库非常干净不依赖一堆运行时 DLL适合直接塞进自己的工程。这篇文章我会从环境搭建、完整编译命令到高频命令行实操再到 CLion 工程集成一次性讲清楚顺便把编译前后容易踩的坑也列出来。1. 项目背景与整体设计思路1.1 为什么坚持用 FFmpeg 3.4 MinGW-w32 组合很多人一看到 3.4 就摇头觉得不如直接用 6.x、7.x。但实际做项目的时候“最新”不等于“最好”。FFmpeg 3.4 的公共 API 变化不大但很多旧代码是基于 3.x 的接口写的换到新版本就得改一堆函数签名比如avcodec_register_all、av_register_all这些老接口在 4.0 之后被移除。如果你的项目代码还依赖这些接口直接编译新版本 FFmpeg 会报错只能顺着编译错误一行行改。这个时候把一个 3.4 版本重新编出来反而是最快、最省事的方式。MinGW-w32 的核心价值则体现在“静态链接”上。用 MSVC 编译 FFmpeg 也能用但产生的库文件在格式、链接选项、依赖的 C 运行时上都有很多琐碎问题。MinGW-w32 是 GCC 工具链编出来的是 PE 格式目标文件配合 CMake 和 CLion 非常顺手。更关键的是静态链接后生成的 exe 可以直接丢到没装 FFmpeg 的机器上跑不用到处拷贝 avcodec-57.dll、avformat-57.dll 这类动态库。这一点在交付工具给同事或客户时特别重要。1.2 这套方案适合解决什么问题我整理了一下手头的需求发现“ffmpeg-3.4-mingw32”这个组合适合以下几类场景需要维护老项目用 CMake/CLion 在 Windows 上编译代码还在用 FFmpeg 3.x API。需要一个体积小、依赖少的命令行工具用来做 m3u8 转 mp4、音频压缩、破损视频修复。需要在离线环境中安装 FFmpeg没有互联网去拉第三方预编译包。需要把 FFmpeg 作为子项目源码编进自己的工具链比如配合 Windows 上的 MinGW-w32 环境。如果你是做新项目我仍然建议优先考虑新版 FFmpegAPI 更规范编码器也更完善。但如果预算有限、时间紧或者只是内部工具使用3.4 完全够用而且文档多、踩坑经验丰富出问题好查。1.3 整体流程概览我的操作流程分为四步先搭好 MinGW-w32 环境然后配置 FFmpeg 源码并编译安装接着用编出来的 ffmpeg.exe 处理几个实际任务最后在 CLion 里建立工程链接静态库写一个简单的调用示例。整个过程不复杂但每一步都有容易忽略的细节下面逐步展开。2. 编译环境准备与完整构建过程2.1 MinGW-w32 工具链准备如果你已经装了 CLion并且用的是 MinGW 工具链那环境基本已经就位。如果没有建议直接下载 MinGW-w64 项目提供的 32 位 GCC 工具链。注意“w32”指的是目标平台是 32 位 Windows工具链本身可以运行在 64 位系统上也可以用 32 位版本。我的习惯是装 32 位工具链来编 32 位 FFmpeg这样生成的静态库和程序都能在旧电脑上跑。安装后需要把bin目录加入系统的 PATH 环境变量比如C:\mingw32\bin同时要确保gcc、make、ar、strip这些命令都能在命令行里直接调用。验证方法很简单gcc --version make --version能正常输出版本号说明基本环境没问题。FFmpeg 3.4 的源码可以去官网下载也可以从 ffmpeg.org 的 release 列表里找文件名类似ffmpeg-3.4.tar.xz。建议把源码解压到一个没有中文和空格的路径比如C:\ffmpeg\src\ffmpeg-3.4不然 configure 脚本有时候会出幺蛾子。2.2 configure 与 make 命令实操进入源码目录后我使用的 configure 命令如下这个配置适合“纯命令行工具 静态库”场景./configure \ --prefix/c/ffmpeg-3.4-mingw32 \ --target-osmingw32 \ --archx86 \ --enable-static \ --disable-shared \ --disable-doc \ --disable-debug \ --enable-small \ --disable-x86asm简单解释一下关键参数--prefix安装路径编译完成后make install会把头文件、库文件、exe 都放到这里。--target-osmingw32告诉 FFmpeg 目标系统是 Windows编译出的可执行文件是 PE 格式。--archx8632 位目标架构。如果你的工具链是 64 位这里要写x86_64同时工具链名称也要匹配。--enable-static生成静态库.a文件。--disable-shared不生成 DLL避免运行时还得带一堆动态库。--disable-x86asm跳过汇编优化。3.4 默认会找yasm如果没有 yasm 会直接报错。用这个参数可以省去安装 yasm 的麻烦。代价是部分编码器性能略低但对大多数工具场景影响不大。configure 顺利结束后执行make -j4 make install-j4表示用 4 个线程并行编译实测能明显缩短编译时间。如果机器内存小改成-j2更稳妥。2.3 编译中三个容易卡住的点第一个坑是 yasm 找不到。如果你用了--disable-x86asm这个问题基本不会出现。想保留汇编优化的话需要提前安装 yasm并把它加入 PATH。第二个坑是链接阶段报cannot find -lwinpthread或者cannot find -lws2_32。MinGW 环境下 FFmpeg 会依赖 Windows 的 socket 库和多线程库通常 GCC 会自动带。如果报错可以在 configure 前把环境变量LDFLAGS加上对应的库路径或者干脆在make之后手动改ffbuild/config.mak中的EXTRALIBS。第三个坑是make install之后直接运行ffmpeg.exe提示缺少libgcc_s_dw2-1.dll。这是因为编译时选择了shared的 GCC 运行时库。解决办法是在链接时加静态运行时参数比如在 configure 前设置CFLAGS-static-libgcc -static-libstdc ./configure ...或者直接把libgcc_s_dw2-1.dll从 MinGW 的 bin 目录复制到 ffmpeg.exe 旁边。为了省事我一般优先选静态运行时。3. 高频 FFmpeg 命令行实操从转换到修复3.1 解决“ffmpeg 不是内部或外部命令”在 Windows 上最容易遇到的问题就是这条报错。原因只有一个系统找不到ffmpeg.exe。解决办法是把ffmpeg.exe所在的目录加入 PATH或者在当前目录下调用。把C:\ffmpeg-3.4-mingw32\bin加进 PATH 后重新打开命令行输入ffmpeg -version如果能打出大段版本信息说明环境没问题。如果不想改全局 PATH也可以把 exe 直接放在项目目录里然后用.\ffmpeg.exe -version调用。3.2 m3u8 转 MP4最稳的转封装思路处理 m3u8 是 FFmpeg 的看家本领。m3u8 本质上是一个 TS 分片列表转成 MP4 最常用的是直接转封装不重新编码速度很快ffmpeg -i input.m3u8 -c copy -bsf:a aac_adtstoasc output.mp4这里的-c copy表示视频流和音频流都直接复制不重新编码。-bsf:a aac_adtstoasc是很多 m3u8 里 AAC 音频必须加的 bitstream filter否则转出来的 mp4 在播放器里可能没有声音。如果播放时发现画面和声音不同步可以去掉-bsf:a aac_adtstoasc换成ffmpeg -i input.m3u8 -c copy output.ts先把 TS 片段合并成一个 TS 文件再转成 mp4有时候能避开奇怪的封装问题。如果想把视频重新编码比如压缩体积可以指定编码器ffmpeg -i input.m3u8 -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k output.mp4这个命令适合对画质有要求、不怕慢的场景。只有在 configure 时开启了 libx264才会识别libx264这个编码器。3.3 破损 AVI 文件修复重写索引就够了AVI 格式的视频经常因为录制中断或拷贝不完整导致索引损坏表现是播放器拉到某个位置就卡住或者整个文件打不开。FFmpeg 修复的基本思路是重新扫描一遍数据流重建索引ffmpeg -i broken.avi -c copy fixed.avi之所以要-c copy是因为我们不需要重新编码只做“解封装再封装”的过程FFmpeg 会顺手把新的索引写进去。如果文件损坏比较严重直接报错退出可以试一下忽略错误ffmpeg -err_detect ignore_err -i broken.avi -c copy fixed.avi这个参数让 FFmpeg 尽量跳过损坏的数据包。注意如果文件的关键帧数据本身已经丢失修复出来的视频可能还是有画面抖动或花屏问题但至少能把能用的部分救回来。3.4 音频压缩与精准裁掉片尾的命令细节音频压缩是 FFmpeg 的强项。如果把一个 WAV 文件压成 MP3命令是ffmpeg -i input.wav -c:a libmp3lame -b:a 192k output.mp3编译 3.4 时如果没有开--enable-libmp3lame运行时会提示找不到编码器。这种情况下可以用内置的libmp3lame替代方案也就是把音频压成 AACffmpeg -i input.wav -c:a aac -b:a 192k output.m4aAAC 在相同码率下音质通常比 MP3 好一点而且 FFmpeg 内置编码器支持得很好不需要额外编译第三方库。精准裁掉片尾这个需求也很常见。比如片尾有 3 秒的鸣谢想去掉不需要手动计算时间点直接用负的时间偏移ffmpeg -sseof -3 -i input.mp4 -c copy output.mp4-sseof -3表示从文件结尾往前偏移 3 秒的位置开始处理也就是直接截掉最后 3 秒。这个参数对视频和音频都有效。如果希望只保留 30 分钟以内的内容那就用-t 1800ffmpeg -sseof -3 -i input.mp4 -c copy -t 1800 output.mp4注意-sseof配合-c copy时裁剪位置会落在关键帧上所以片尾切割未必能精确到毫秒但误差通常在 1 秒以内。如果要真正精准就得重新编码但成本会高很多。4. 在 CLion 中导入 FFmpeg 静态库4.1 整理 SDK 目录结构make install之后得到的目录结构大概是这样的C:\ffmpeg-3.4-mingw32\ ├── bin\ │ ├── ffmpeg.exe │ └── ffprobe.exe ├── include\ │ ├── libavcodec\ │ ├── libavformat\ │ ├── libavutil\ │ ├── libswresample\ │ └── libswscale\ └── lib\ ├── libavcodec.a ├── libavformat.a ├── libavutil.a ├── libswresample.a └── libswscale.a在 CLion 项目里我习惯用第三方库目录比如third_party\ffmpeg把 include 和 lib 整体丢进去方便 CMake 引用。4.2 CMakeLists.txt 配置实例下面是一个可以直接用的 CMakeLists.txt 示例假设目标项目叫video_toolcmake_minimum_required(VERSION 3.16) project(video_tool C) set(FFMPEG_DIR third_party/ffmpeg) include_directories(${FFMPEG_DIR}/include) add_executable(video_tool main.c) target_link_libraries(video_tool ${FFMPEG_DIR}/lib/libavformat.a ${FFMPEG_DIR}/lib/libavcodec.a ${FFMPEG_DIR}/lib/libavutil.a ${FFMPEG_DIR}/lib/libswresample.a ${FFMPEG_DIR}/lib/libswscale.a ws2_32 winpthread pthread gcc )在 CLion 中选择与编译 FFmpeg 一致的 MinGW 工具链构建时基本不会出问题。如果链接报错提示找不到__imp_xx多半是静态库顺序不对把libavformat放在最前面libavutil往后放这个顺序是 FFmpeg 依赖关系的常见要求。4.3 链接顺序与运行时注意事项静态库链接时依赖库需要排在引用它的库之后。FFmpeg 各库之间有明确的依赖层级avformat依赖avcodec和avutilavcodec依赖avutil所以常规顺序是avformat - avcodec - avutil如果同时使用swresample它通常放在avcodec之前或之后都行但一般放在avformat之后、avcodec之前。这样能避免出现“未定义引用”的错误。运行时还有一点要注意如果你在 configure 时选择了共享库生成的 exe 需要avcodec-57.dll系列文件在 PATH 中。用静态库的话就不用管这个问题直接跑 exe 就行。如果程序里还用了 MinGW 的 pthread别忘了在链接时加上winpthread否则运行时会崩溃。4.4 在代码里调用 FFmpeg 的一个最小示例一个最简单的例子打开视频文件并读取基本信息#include stdio.h #include libavformat/avformat.h int main(int argc, char *argv[]) { av_register_all(); AVFormatContext *fmt_ctx NULL; if (avformat_open_input(fmt_ctx, argv[1], NULL, NULL) 0) { fprintf(stderr, open failed\n); return 1; } printf(duration %lld seconds\n, fmt_ctx-duration / AV_TIME_BASE); avformat_close_input(fmt_ctx); return 0; }注意 3.4 版本仍然需要调用av_register_all()新版本已经不需要了。如果你的代码在 4.0 之后编译这里会直接报错反之在 3.4 上就是正常写法。这也解释了为什么老版本在老项目里绕不开。5. 常见问题速查与排查心得5.1 问题速查表现象原因解决办法ffmpeg is not recognized...环境变量未配置把 ffmpeg.exe 所在路径加入 PATHconfigure 提示yasm not found缺少汇编器安装 yasm 或使用--disable-x86asm链接报cannot find -lwinpthreadMinGW 多线程库未找到检查工具链安装或手动指定-lwinpthread运行 exe 提示缺 DLL使用了共享 GCC 运行时编译时加-static-libgcc -static-libstdcm3u8 转 mp4 没有声音AAC 流需要转换 bitstream加-bsf:a aac_adtstoasc破损 AVI 无法打开索引损坏用-c copy重写容器修复CLion 链接时 undefined reference库顺序错误按 avformat - avcodec - avutil 顺序排列5.2 我的踩坑记录与选择建议这次重新编译 ffmpeg-3.4-mingw32让我印象最深的是 yasm 和链接顺序这两个问题。yasm 还好说直接--disable-x86asm解决链接顺序则是典型的静态库使用痛点库的依赖关系写错了报错信息又长又唬人。我的习惯是每次链接报错先看第一个 undefined symbol 是哪个库的再回头调顺序比盲目加库有效率得多。还有一个选择建议如果你只是想用命令行处理视频其实完全可以直接下载现成的静态构建版本不必自己编译。但如果你需要在 CLion 里写自己的工具链或者你的老项目必须依赖 3.4 的 API那自己编译一遍是很有价值的至少能保证库和编译器完全匹配不会出现版本冲突。3.4 虽然老但构建简单、文档齐全在我接触过的老项目里它依然是很能打的一个版本。本文还有配套的精品资源点击获取

相关新闻

最新新闻

PHP实战:用mpdf实现订单报表导出PDF完整指南

PHP实战:用mpdf实现订单报表导出PDF完整指南

最近在做一个订单系统,客户那边提了个需求:表单提交之后,后台要能直接把数据导成一份规范的PDF文件,方便打印、留档、发给上下游。翻了一圈方案,最后选了PHP生态里很成熟的mpdf库来落地。折腾了一轮下来,把…

2026/9/8 7:49:45
数学建模国赛零基础备赛指南:从团队分工到论文写作全流程

数学建模国赛零基础备赛指南:从团队分工到论文写作全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/8 7:49:45
基于SpringBoot+Vue3+MyBatis+MySQL的养老保险管理系统实战解析

基于SpringBoot+Vue3+MyBatis+MySQL的养老保险管理系统实战解析

1. 为什么是 SpringBoot Vue3 MyBatis MySQL 这套组合先说个结论:养老保险管理系统这种业务,技术栈选型从来不是越新越好,而是越"稳"越好。这套系统我用 SpringBoot 做后端、Vue3 做前端、MyBatis 做数据持久层、MySQL 存数据&a…

2026/9/8 7:49:45
CYW-B240128A图形点阵屏驱动与调试实战指南

CYW-B240128A图形点阵屏驱动与调试实战指南

这块屏幕我前后折腾了两周,从连引脚都怕接错的小白状态,到能流畅刷出曲线和菜单,中间踩的坑比想象中多得多。CYW-B240128A是一块240x128分辨率的图形点阵液晶模块,和常见的1602、12864这类字符屏或小尺寸点阵屏不一样,…

2026/9/8 7:49:45
用22周拆解《哈利波特》:一套可复制的结构化精读与伏笔追踪方法

用22周拆解《哈利波特》:一套可复制的结构化精读与伏笔追踪方法

去年年底我给自己挖了个坑,代号叫harrypotter22-1。熟悉我的朋友一看就明白,这是“哈利波特专题计划”的 2022 年第一个成品,不是什么高深的编程项目,而是一套围绕《哈利波特与魔法石》做的深度拆解资料。我前后折腾了 22 周&…

2026/9/8 7:49:45
我把AI塞进前端日常:五个多月实战总结与避坑指南

我把AI塞进前端日常:五个多月实战总结与避坑指南

1. 为什么写这份试水报告:我把AI塞进了前端日常先说清楚这篇报告在干什么。过去五个多月,我把AI系统地用进了前端开发的日常链路:从搭后台页面、写表单组件、封装请求层,到排查WebSocket推送的时序问题,再到处理老项目…

2026/9/8 7:44:45