
简介ffmpeg n4.4.1 对应的 vs2015 静态库编译包提供 x86/x64 双平台 lib 文件专门面向需要在 Windows 下生成独立可执行程序、又不希望逐台部署 DLL 的音视频开发者。压缩包共 140 个文件包含 125 个 C/C 头文件、14 个静态库文件及 1 份依赖项说明 txt整个包大小约 28.78 MB。编译版本为 N104926-gc8b5f2848d官方对应 n4.4.1并已通过基础测试使用静态库后最终生成的 exe 无需依赖 avcodec.dll、avformat.dll 等动态库但需按压缩包内 txt 文档给出的清单在 VS2015 工程中额外附加必要的系统依赖以免链接报错。当前已有 457 人学习下载整体体量紧凑、目录明确。资源内部头文件覆盖 avcodec、avformat、avfilter、pixfmt、hwcontext 等常见模块适用于视频解码、音频处理、封装/解封装等二次开发场景拿到手即可按说明配置链接路径也可在此基础上调整编解码参数快速完成 FFmpeg 静态库的本地接入与功能验证。1. 静态库不是怀旧VS2015 下的 FFmpeg 构建x86/x64 的 .lib 值得自己做一份很多做播放器、录播、工业相机和安防平台的老项目至今还锁在 VS2015 MFC 的框架里。FFmpeg 官网给 Windows 用户的要么是 MinGW 编出来的 dll 包要么是让人看得头疼的 git 仓库网上搜 ffmpeg 编译 dll 库的教程一大堆但真正针对 VS2015、同时出 x86/x64 两套静态库.lib的完整流程却零零散散。这个标题想解决的事很简单用 VS2015 自己的编译器和链接器把 FFmpeg 从源码编成 libavcodec.lib、libavformat.lib 这类文件让音视频编解码逻辑直接嵌进你的 exe交付时不用拖一包 dll。这个方案适合两类人一类是接手老项目的维护者工程里还写死了 VS2015新同事装不上新版本 VS另一类是把 SDK 交付给第三方厂商的对方环境不可控一个 exe 加一套 .lib 比一坨带版本冲突风险的 dll 省心得多。这篇按我实际做的路线写先选版本和构建环境再分别跑 x86/x64 构建最后落到集成和排错。2. 编译前把环境想清楚版本、工具链和 MSYS2 怎么搭2.1 FFmpeg 版本怎么选VS2015 配 5.1.4 是稳妥组合FFmpeg 的版本选择直接影响后续能否用 MSVC 编过。VS2015 对应的是 VC14编译器对 C99 的支持马马虎虎对 C11/C17 的新特性支持非常有限。FFmpeg 4.x 和 5.1.x 的源码主体还停留在 C99 风格配合 MSVC 的 workaround 能顺利编过到了 6.x 之后官方在 Windows 上的测试重心明显偏向较新的 VS 版本和 MinGW你在 VS2015 下会遇到 configure 阶段检测失败或者编译到一半报某个函数未声明这类玄学问题。我一般固定用 FFmpeg 5.1.4 作为 VS2015 构建的默认版本。这个版本是 5.x 系列的维护分支出了很久网上能搜到的踩坑记录也最全。如果你接手的老项目原本就基于 4.4 或 4.2那就继续沿用原有大版本不要为了追新把整个依赖链推翻。尽量不要直接拉 master 源码master 为了新编码器和滤镜不断引入更新的语法VS2015 编不过的概率很高没必要在这个环节挑战自己。下载时注意拿 release 源码包不要用 GitHub 的 zip 快照。解压路径必须是一个没有空格、没有中文的纯英文路径比如D:\src\ffmpeg-5.1.4。MSYS2 和 configure 脚本对路径里的空格非常敏感放在C:\Program Files下大概率会在 configure 阶段莫名其妙失败而且报错信息很难联想到这里。2.2 为什么必须用 --toolchainmsvc而不是拿 MinGW 的 .a网上很多教程教你在 MSYS2 里直接用 gcc 编 FFmpeg编出来的确实是静态库但后缀是 .a不是 VS 工程认得的 .lib。就算你把 .a 强行改名为 .lib 塞进链接器也会因为符号修饰规则、导入导出格式、C 运行时库的差异报出一堆 unresolved external symbol。这片面的原因很简单MSVC 和 MinGW 各自有一套 ABI静态库必须由同一编译器家族产出才能被对方的链接器消费。所以给 VS2015 用的 FFmpeg 静态库configure 时必须指定--toolchainmsvc。这个参数让 FFmpeg 的构建系统用cl.exe编译 C 源码、用link.exe生成 .lib这样产出的库才能被 VS2015 工程直接引用。这里顺便说清楚静态库和动态库的区别避免做完发现不是自己要的。维度静态库.lib动态库dll交付形式一个 exe不依赖 FFmpeg 的 dllexe 旁要放对应 dll注意搜索路径版本冲突编解码逻辑锁进 exe不受系统环境影响dll 被替换或缺失时直接跑不起来体积明显变大裁剪不足可能增加十几 MB主体 exe 小但总分发体积相当运行时库必须和主工程保持同一套 CRTdll 自带运行时但也可能互相踩链接配置需要手动补 ws2_32、bcrypt 等系统库通常 dll 内部处理好依赖透出少调试可以进到 FFmpeg 源码里单步需要额外加载调试符号做静态库不是追求最小体积而是求稳。把 FFmpeg 嵌进 exe 之后客户机器上哪怕装满了各种乱七八糟的播放器组件也不会因为 FFmpeg 的 dll 名字冲突把你的程序拖垮。2.3 搭一套能重复用的构建环境VS2015 命令行 MSYS2构建环境只需要两样东西VS2015 的命令行编译环境和一个 MSYS2 发行版。FFmpeg 的 configure 是个 shell 脚本MSYS2 提供 sh 环境但编译和链接必须用 VS2015 的cl.exe和link.exe所以整个流程要在 VS2015 的命令行窗口里拉起 MSYS2让 MSYS2 继承 VS 的环境变量。先装 MSYS2默认安装到C:\msys64。装完后打开 MSYS2 的终端把构建 FFmpeg 需要的工具装上pacman -S --needed base-devel make diffutils pkgconf yasm nasm python这些包各自的角色base-devel提供 make 和基础编译链diffutils提供 configure 脚本需要的 diff 命令yasm和nasm是 x86/x64 汇编器FFmpeg 里大量高性能编解码和像素处理代码走汇编这两个必须装pkgconf用于后续可能引入外部库时的依赖探测。python 不是必须但新版 FFmpeg 的部分生成脚本用到顺手装上能少一个报错。然后打开一个 VS2015 的 x86 Native Tools Command Prompt或者用 vcvarsall.bat 手动初始化环境再在这个窗口里启动 MSYS2call C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat x86 set MSYS2_PATH_TYPEinherit C:\msys64\msys2_shell.cmd -use-full-path -deftermset MSYS2_PATH_TYPEinherit的作用是让 MSYS2 的 PATH 直接继承当前 Windows 窗口的 PATH这样cl.exe才能被 MSYS2 里的 shell 找到。-use-full-path是同一个目的在 msys2_shell.cmd 层面保证环境变量传进去。-defterm让 MSYS2 在当前窗口以交互式方式运行不用额外弹一个新终端。启动后先验证环境是否就绪which cl cl能打印出 Microsoft (R) C/C Optimizing Compiler 版本 19.00 字样说明 VS 环境成功透传进去了。这一步如果漏掉后面 configure 会直接报cl.exe is not found还容易让人误以为是 MSYS2 装坏了。3. 从 configure 到 makex86 静态库最小构建命令与参数调整3.1 最小可用的 configure 参数环境搭好后进入 FFmpeg 源码目录用 out-of-tree 方式构建。就是源码目录保持干净在源码下建一个 build-x86 子目录所有临时文件和产出物都在里面方便以后并行编 x64 版本而不互相污染。cd /d/src/ffmpeg-5.1.4 mkdir -p build-x86 cd build-x86 ../configure \ --toolchainmsvc \ --archx86 \ --enable-static \ --disable-shared \ --disable-programs \ --disable-doc \ --disable-debug \ --disable-autodetect \ --disable-network \ --disable-avdevice \ --disable-postproc \ --enable-avcodec \ --enable-avformat \ --enable-avutil \ --enable-swresample \ --enable-swscale \ --enable-avfilter逐个说参数。--toolchainmsvc是核心没有它整个构建会用 gcc产物就不是 VS2015 能直接用的 .lib。--archx86明确产出 32 位库不写有时会默认按照当前编译器的位数判断。--enable-static --disable-shared一个开一个关确保最终生成 .lib 而不是 dll。--disable-programs跳过 ffmpeg.exe、ffprobe.exe 这类命令行工具静态库场景用不到而且能省至少三分之一编译时间。--disable-doc跳过文档生成纯纯的节省时间。--disable-autodetect这个参数容易被人忽略但很重要。它让 configure 不再自动探测系统里装了什么第三方库避免出现「我明明没装 libx264configure 却检测到一个残留的 dll 然后就试着链接」这类黑匣子行为。没有它构建结果可能因为你机器上装了乱七八糟的开发库而改变今天编得出来明天换台机器就编不出来。后续如果要加 libx264需要去掉这个参数单独开启对应选项。最后的--enable-av*系列是明确开启需要的组件库。播放器通常只需要 avcodec、avformat、avutil、swresample、swscale 这几个avdevice 负责采集摄像头和声卡桌面项目一般用不到直接 disable。postproc 是后处理滤镜也关掉。如果想进一步裁剪体积可以追加编码器开关../configure \ --toolchainmsvc \ --archx86 \ --enable-static \ --disable-shared \ --disable-programs \ --disable-doc \ --disable-debug \ --disable-autodetect \ --disable-network \ --disable-avdevice \ --disable-postproc \ --disable-encoders \ --enable-encodermpeg4 \ --enable-encoderaac \ --enable-decoderh264 \ --enable-decoderhevc \ --enable-decoderaac \ --enable-parserh264 \ --enable-parserhevc \ --enable-demuxerflv \ --enable-demuxermov \ --enable-muxermp4 \ --enable-muxerflv这里注意FFmpeg 内置的纯 CPU H.264 编码器不是一个可用状态CPU 编码 H.264 基本都要走外部 libx264第 6 章会讲怎么补。上面这份裁剪只保证 H.264/HEVC 解码、AAC 解码、MPEG-4 编码、FLV/MP4 封装解封装。第一次构建不建议把裁剪做这么狠先按第一份命令跑通全流程再回来慢慢切。3.2 用 make 并行编译和核对 .lib 产物configure 跑完没有报错的话直接并行编译make -j8 21 | tee build.log-j8表示 8 线程并行。CPU 较弱或者内存只有 8 GB 的机器改成-j4更稳否则并行编译时内存暴涨可能导致 cl.exe 进程被杀。tee build.log把编译输出同时打印到屏幕和写进日志编译失败时翻日志比翻终端缓存方便得多。编译完成后检查 4 个主要输出ls -la libavcodec/*.lib libavformat/*.lib libavutil/*.lib libswscale/*.lib正常情况下能看到 libavcodec.lib、libavformat.lib 等文件单个库几十 MB 都很正常。如果发现某个 .lib 缺失去 build.log 里搜Error定位到具体模块。这里提醒一下不要用 nmake 来跑编译。FFmpeg 的 MSVC 工具链生成的是 Makefilenmake 对它的兼容性时好时坏并行任务支持也烂老老实实待在 MSYS2 里用 GNU make 是最顺的一条路。3.3 第一遍编译会踩的三个报错第一个报错是 configure 阶段直接退出提示nasm not found或yasm not found。原因是 FFmpeg 的汇编优化代码必须有汇编器才能编没有就干脆放弃整个构建。解决方式就是前面 pacman 命令里装的 yasm 和 nasm确认它们在 PATH 里能执行即可which nasm能看到路径就行。第二个报错是cl is not found。这基本可以确定是没有走 VS2015 的命令行窗口启动 MSYS2或者MSYS2_PATH_TYPEinherit没设置。有些教程让人从 MSYS2 的图标进终端那个环境里根本没有 VS 的 cl.exe编到一半才报错。老老实实按 2.3 的顺序来先 vcvarsall再启动 MSYS2。第三个报错比较隐蔽configure 卡在某个 C 99 兼容性检测上或者编译时大面积报C2057之类的语法错误。多数情况是源码路径里有空格。把 ffmpeg-5.1.4 挪到D:\src这种短路径重来一次问题会直接消失。这条我踩过不止一次每次都觉得不可思议但路径一短就真的好了。4. x86/x64 双架构构建同一套流程分开踩坑4.1 x64 和 x86 的四处配置差异x64 的构建流程和 x86 一模一样但有几个地方必须改。第一是 vcvarsall.bat 的参数从 x86 换成 x64保证 cl.exe 和 link.exe 是 64 位版本。第二是 configure 的--archx86改成--archx86_64让 FFmpeg 知道它在为 64 位目标生成代码。第三是汇编器版本x86 下老 yasm 还能凑合用x64 强烈建议用 nasm 2.13 以上老版本在处理 64 位重定位时会生成错误的机器码出来的库在链接和运行阶段都可能翻车。第四处差异不在编译阶段而在链接阶段。x64 构建的 FFmpeg 静态库链接进主工程时比 x86 多一个系统依赖bcrypt.lib。这个库来自 Windows SDK不是编译器自带VS2015 安装时勾选了 SDK 就有。如果最终集成时报unresolved external symbol BCrypt*不要怀疑 FFmpeg 库坏了只是你的工程缺少这个系统库。4.2 一次产出两套库build-x86 与 build-x64 的分目录脚本我习惯用一个批处理固定整个编译流程让重复构建变成一条命令。注意第一次编译不要直接跑整个循环先手动把 x86 跑通一次确认 configure 参数没问题再让脚本批量跑echo off set SRCD:\src\ffmpeg-5.1.4 set CFG--toolchainmsvc --enable-static --disable-shared --disable-programs --disable-doc --disable-debug --disable-autodetect --disable-network --disable-avdevice --disable-postproc --enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale --enable-avfilter for %%A in (x86 x64) do ( call C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat %%A set MSYS2_PATH_TYPEinherit C:\msys64\usr\bin\bash.exe -lc cd %SRC% mkdir -p build-%%A cd build-%%A ../configure %CFG% --arch%%A make -j8 )这里有个小技巧for %%A in (x86 x64)循环里%%A会依次变成 x86 和 x64同时被用在 vcvarsall 的参数和 configure 的--arch参数里。但注意x86 字符串直接传给--arch是合法的FFmpeg 能识别这两种写法。bash.exe -lc里用%SRC%展开源码路径%CFG%展开公共配置参数再用mkdir -p build-%%A保证两个架构目录独立。这个脚本每次跑都会重新编一遍全量有点浪费时间。实际使用中我一般只在源码版本升级或者想改裁剪参数时才全量跑平时直接进到对应的 build-x86 或 build-x64 目录单独执行make -j8做增量编译。4.3 交付目录怎么整理两套同名 .lib 的存放方案Windows 的静态库里没有内置架构信息很多开发者会把 libavcodec.lib 直接发给客户结果客户那边是 x64 工程一链接就报 LNK1112。这个错误提示很直白module machine type x86 conflicts with target machine type x64但客户不一定知道怎么应对。我交付时固定按架构分目录归档目录结构长这样ffmpeg-5.1.4-static/ x86/ include/ libavcodec/ libavformat/ libavutil/ libswresample/ libswscale/ lib/ libavcodec.lib libavformat.lib libavutil.lib libswresample.lib libswscale.lib README-x86.txt x64/ include/ libavcodec/ libavformat/ libavutil/ libswresample/ libswscale/ lib/ libavcodec.lib libavformat.lib libavutil.lib libswresample.lib libswscale.lib README-x64.txt头文件在 x86 和 x64 下内容是相同的但分别放一份能有效防止把 x86 的头文件和 x64 的 .lib 混在一起用。README 里写清楚这套库的 configure 参数以及集成时额外需要链接的系统库列表。两年后你自己看这个 README 都会感谢现在的决定。4.4 x64 专属坑nasm 版本与 bcrypt.lib 依赖x64 构建最常见的事故现场是 configure 已经过去了make 编到一半报汇编错误错误信息指向一些奇怪的 CPU 指令。这个现象我在老版本 yasm 上碰到过换 nasm 2.15 之后彻底消失。所以建议直接装 nasm并且确认它在 PATH 里优先被找到。configure 日志里会打印 assembler 用的哪一个进去瞄一眼。另一个 x64 下的集成坑是链接阶段。FFmpeg 在 x64 架构下默认启用了 Windows 的加密接口用于 TLS 和某些 hash 算法。你的 VS2015 工程如果沿用 x86 的依赖列表只加了 winmm.lib、ws2_32.lib就会在链接时冒出一串BCrypt*未解析。解决办法是在附加依赖项里加上bcrypt.lib这个文件由 Windows SDK 提供VS2015 自带不用额外装东西。5. 集成到 VS2015 工程时的避坑链接报错、运行库不一致、解码器不认5.1 unresolved external symbol 的四个真实来源把 .lib 加进工程后最常见的失败就是链接器报一大堆unresolved external symbol。第一次遇到会让人以为是 FFmpeg 库没编好实际上大多是主工程这边的问题。第一种来源是缺系统库。FFmpeg 即使裁剪得很干净avformat 和 avutil 也会引用 Windows 系统 API至少要补上这几项ws2_32.lib、user32.lib、bcrypt.lib、secur32.lib、winmm.lib。在 VS2015 工程里打开项目属性链接器 - 输入 - 附加依赖项把这些都填进去unresolved 会少掉一大半。第二种来源是架构混用。x86 工程里误加了 x64 的 libavcodec.lib链接器会报 LNK1112而不是普通的 unresolved。解决方式不用多说按 4.3 的目录结构检查即可。第三种来源是把 MinGW 编出来的 .a 改名成 .lib 硬塞进工程。现象是 unresolved 符号很多并且符号名带着__imp_前缀。这种库从源头就不该用回到第 2 章用--toolchainmsvc重新编一套。第四种来源是运行库不匹配。FFmpeg 静态库默认按/MD编译如果你的 VS2015 工程设置成了/MT链接时就会出现一类奇怪的重复符号或 unresolved指向_malloc之类的基础函数。解决方式在 5.3 细说。5.2 avcodec_find_decoder 返回 NULL解码器去哪了程序链接成功运行时avcodec_find_decoder(AV_CODEC_ID_H264)返回 NULL这是裁剪式构建最容易遇到的现象。configure 里如果用了--disable-all或者大范围 disable又没显式 enable 对应解码器FFmpeg 的注册表里就没有这个解码器。运行时不是找不到符号而是找到的库里头根本没有对应实现。解决思路分两步。第一步回头检查 configure 参数确认--enable-decoderh264 --enable-parserh264这类选项确实存在重新 configure 并编译。第二步在程序初始化里补一句avcodec_register_all();FFmpeg 4.0 之后这个函数已经是空操作编解码器通过静态链接自动注册但老版本或者特殊裁剪配置下它仍然是必需的。加上没有副作用能排除一类老写法带来的兼容性问题。如果仍然返回 NULL用avcodec_find_decoder遍历比较 debugger 里断点或者直接查 configure 生成的config.h里CONFIG_H264_DECODER是不是 1。5.3 释放崩溃和 heap corruption多 CRT 混用的后果链接和运行初期都正常但程序退出时弹 heap corruption或者在某个 av_free 之后崩溃优先级很高的怀疑对象就是 CRT 混用。VS2015 的 C 运行时有/MT静态版和/MD动态版之分FFmpeg 静态库默认是/MD也就是动态链接到 vcruntime140.dll如果你的主工程是/MT两个模块各自维护一套堆管理逻辑一块内存在 A 堆分配、在 B 堆释放当场就能把堆元数据写坏。解决方式是二选一但必须全局统一。最简单的路径是让主工程也切到/MD项目属性 - C/C - 代码生成 - 运行库选「多线程 DLL (/MD)」。这样做对大多数业务程序是安全的代价是目标机器需要装 VC2015 运行库对于大型装机场景这通常不会成为问题。如果必须坚持/MT那就需要回到 FFmpeg 构建步骤在 configure 时加上--extra-cflags/MT --extra-ldflags/MT然后重新编一套静态库。这两条参数会传导给 cl.exe 和 link.exe让 FFmpeg 的 .obj 也按静态 CRT 编译。注意用这种方式重新编完后整条链上所有参与链接的第三方库也必须都是/MT否则老问题以新形式复发。5.4 交付前用 dumpbin 验证依赖别让 dll 偷偷溜回来静态库做完最怕的就是交付前以为自己全静态了结果客户一跑就提示缺 dll。用 VS2015 自带的 dumpbin 工具可以一眼看穿dumpbin /dependents your_exe.exe输出里如果出现avcodec-59.dll这类字样说明你的 exe 其实还是动态依赖或者静态库没链进去。正常全静态链接的 exe 只依赖系统 dll以及 vcruntime140.dll 这类 VC 运行库。再进一步可以用dumpbin /headers your_exe.exe | findstr DLL检查机器码调度特征确认当前文件是 x86 还是 x64。交付给客户的版本每次构建完我都会对一遍这个输出确认没有 FFmpeg 相关 dll 之后才打安装包。这个习惯帮我挡下了不少「到客户现场才翻车」的尴尬。6. 验证与进阶最小解码程序、再编一个 libx264 静态库6.1 用 15 行 C 程序确认静态库真的被链接进去集成验证不用一上来就写完整播放器先写一个最小探测程序能通过链接并正确运行时说明静态库、头文件依赖和系统库配置全部正确#include stdio.h #include libavcodec/avcodec.h #include libavformat/avformat.h #pragma comment(lib, avcodec.lib) #pragma comment(lib, avformat.lib) #pragma comment(lib, avutil.lib) int main(void) { const AVCodec *dec avcodec_find_decoder(AV_CODEC_ID_H264); const AVCodec *enc avcodec_find_encoder(AV_CODEC_ID_MPEG4); if (!dec) { printf(H.264 decoder not linked\n); return 1; } if (enc) { printf(MPEG-4 encoder ok: %s\n, enc-name); } printf(ffmpeg static lib ready\n); return 0; }#pragma comment(lib, ...)是 MSVC 专用的写法作用等价于在工程属性里手动加附加依赖项验证阶段用这个能少点几次鼠标。程序逻辑很简单先找 H.264 解码器找不到直接退出找到就再试试 MPEG-4 编码器。运行时如果一切都安静地打印出结果没有弹缺 dll 的窗口说明静态链接链路是通的。6.2 想补 H.264 编码libx264 静态库的构建路径前面提过 FFmpeg 内置没有可用的 CPU H.264 编码器实际项目中要输出 H.264 视频流必须外挂 x264。x264 也要编成静态库才能接进这条链。在 MSYS2 里执行cd /d/src/x264 CCcl ./configure --enable-static --disable-cli --disable-opencl --extra-cflags/MD make -j8CCcl是核心强制 x264 的构建系统使用 MSVC 编译产出的库才是 VS2015 能直接消费的格式。编完后回到 FFmpeg 的 build 目录重新 configure 时去掉--disable-autodetect追加这三项../configure --toolchainmsvc --archx86_64 \ --enable-gpl --enable-libx264 \ --extra-cflags-I/d/src/x264 \ --extra-ldflags/LIBPATH:/d/src/x264--enable-gpl不能省x264 走 GPL 协议FFmpeg 链接它就必须打开 GPL 开关。--extra-ldflags里注意是 MSVC 风格的/LIBPATH:不是 MinGW 风格的-L写错了会链接不到 x264.lib。x264 的版本建议选稳定的 0.157 之后版本太老的版本对 VS2015 支持不稳定我当时用新版本配 VS2015 编了两次才通过卡在一个 configure 检测汇编器的环节最后升级 nasm 解决。我现在的发布习惯是每次构建完先跑 dumpbin 看依赖再用上面的最小程序验证解码器能被找到最后才进业务层联调。这套流程看着笨但它把「编译期问题」和「运行期问题」隔离开了哪一层出错看现象就能知道回哪一步修。希望帮到你。本文还有配套的精品资源点击获取