0%

Windows下编译FFmpeg5.0

在我的FFmpeg课程中,我总是推荐大家使用 Linux(Ubuntu)系统Mac系统 来学习FFmpeg。其原因,是在Windows下编译FFmpeg太麻烦了,这大大增加了我们学习FFmpeg的成本。

不光如此,在Windows下编译FFmpeg所需要的依赖库也很麻烦,比如我们经常使用的fdk-aac、x264等在Windows下都要单独编译才可以使用。

不过,总还是有一些同学需要在Windows下使用FFmpeg,而FFmpeg官网上介绍的Windows下编译FFmpeg的文章实在是太老了,基本不可用。为了解决这部分同学的难题,这里我总结了一份Windows下编译和使用FFmpeg的方法,希望能帮助到大家!

准备编译环境

首先,我们要准备好编译环境,一台装有Windows10系统的电脑是必须的(没有比这再正确的废话了:))。

同时,要将Visual Studio安装好,比如 VS2019 社区版或 VS2022社区版(VS2019可以到这里下载,VS2022可以到这里下载)。这两个版本你用哪个都行,根据自己的需要选择吧。如果不是工作中必须要使用VS2019,那我建议你使用最新版的VS2022。

除了需要安装VS之外,还要安装MSYS2,这是一款Windows下模拟Linux的软件。FFmpeg的编译就是在该软件中进行的,而编译时使用的编译器(cl.exe)和链接器(link.exe)则是由Visual Studio提供的。MSYS2可以到这里下载

需要注意的是,在下载MSYS2时可能需要有网络代理才行。考虑到有些同学没有网络代理软件,我将MSYS2的一个备份放到了百度盘上,你也可以到这里下载。不过当你去百度盘下载这个软件时,它的版本可能已经比较老了,建议有条件的同学还是到官网上下载。

顺便说一下,对于刚学习Linux的同学来说,在Windows上装MSYS2学习Linux是个不错的选择,它比PowerShell要好用得多

下载源码

编译环境准备好之后,接下来我们需要下载一份最新的FFmpeg源码,你可以从这里下载,也可以使用Git下载。Git下载的方法如下:

  • 先将Git命令安装好
  • 然后执行下面的命令
    1
    2
    cd /d
    git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
    此时,代码就被下载到D:盘的ffmpeg目录下了

Windows下编译FFmpeg的方法

当 FFmpeg 源码准备就绪后,我们就可以编译FFmpeg了。

首先,进入MSYS2的安装目录,比如我这里将MSYS2安装到了D:\MSYS64目录下。在该目录下打开 msys2_shell.cmd 文件,将该文件第 17 行代码的注释打开,即去掉 rem 关键字,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@echo off
setlocal EnableDelayedExpansion

set "WD=%__CD__%"
if NOT EXIST "%WD%msys-2.0.dll" set "WD=%~dp0usr\bin\"
set "LOGINSHELL=bash"
set /a msys2_shiftCounter=0

rem To activate windows native symlinks uncomment next line
rem set MSYS=winsymlinks:nativestrict

rem Set debugging program for errors
rem set MSYS=error_start:%WD%../../mingw64/bin/qtcreator.exe^|-debug^|^<process-id^>

rem To export full current PATH from environment into MSYS2 use '-use-full-path' parameter
rem or uncomment next line
set MSYS2_PATH_TYPE=inherit
...

之所以要打开该注释,是为了让MSYS2可以继承Windows控制台的环境变量。

之后,通过面的方法找到x64 Native Tools Command Prompt for VS 2019命令窗口:

1
Windows开始菜单 -> Visual Studio 2022 -> x64 Native Tools Command Prompt for VS 2019

在该命令窗口中输入下面的命令启动 MSYS2 软件

1
2
3
4
5
# 进入到MSYS2 目录下
cd D:\MSYS64

# 启动MSYS2
msys2_shell.cmd

此时,会弹出MSYS2的命令窗口。接下来,在该窗口中输入下面命令,安装必要的编译工具:

1
pacman -S diffutils make pkg-config yasm

其中 pacman 是MSYS2的 包安装工具;而 diffutils、make……都是编译FFmpeg时需要用的 编译工具

当编译工具安装好后,曳光弹在MSYS2命令窗中执行下面命令,进入到FFmpeg源码目录下:

1
cd /d/ffmpeg

紧接着,运行 FFmpeg 源码目录中的 configure 脚本生成 Makefile 文件,命令如下:

1
./configure --prefix=/usr/local/ffmpeg--enable-gpl --enable-nonfree --enable-shared --disable-ffprobe --toolchain=msvc

上述命令的含义是使用mscv作为FFmpeg的编译工具链;编译出的FFmpeg库被放到/usr/local/ffmpeg 目录下;编译的库是动态库,在Windows下就是 DLL 库;编译时不生成 ffprobe 程序。

上述脚本执行完成后,你可以在 FFmpeg 源码目录下发现多了一个 Makefile 文件。有了这个文件我们就可以编译FFmpeg了,编译命令如下:

1
make -j 4 && make install

当执行完这条命令后,在 /usr/local/ffmpeg/bin 目录下就可以找到编译好的FFmpeg库和FFmpeg命令了。

需要注意的是,編译时有你有可能会遇到到如下错误:

1
2
...... error C2065: “slib”: 未声明的标识符
...... error C2296: “%”: 非法,左操作数包含“char [138]”类型

该问题是因为在Windows下无法识别 CC_IDENT 导致的,只需将包括 CC_IDENT关键字的那行代码注释掉即可。

在Windows上找到编译好的FFmpeg库

上面我将编译好的FFmpeg库安装到了/usr/local/ffmpeg目录下,但在Windows下如何找到这个目录呢?

其实非常简单,你只需确定好MSYS2的根目录是哪儿就可以找到编译好的FFmpeg库了。以我的环境为例,我将MSYS2安装到了D:\MSYS64这个目录下,那么D:\MSYS64这个目录就是MSYS2的根目录。

因此,我编译好的FFmpeg库就存放在D:\MSYS64\usr\local\ffmpeg目录下。

VS项目中引用FFmpeg库

编译好FFmpeg库后,下面我们就可以在VS中引用它了。

首先你要创建一个新的VS项目,具体方法如下:

1
打开VS -> 创建新项目 -> 创建控制台项目 -> 填写项目名 

项目创建好后你会发现它里边只有一个testffmpeg.cpp文件,该文件特别简单,只有一个main(...)函数和一条cout << ...语句。现在我们就可以在这个main(...)函数中调用FFmpeg API 了。

但在开始编码之前,我们需要将用到的FFmpeg库和头文件引入到VS工程中,这样后面VS才能正确的将程序编译出来。下面咱们来看看该如何在VS中引入FFmpeg库头文件、库文件:

  • 引入FFmpeg头文件

    1
    项目右键 -> 属性 -> C/C++ -> 常规 -> 附加包含目录

    中添加FFmpeg头文件所在路径。

  • 指定库文件位置

    1
    项目右键 -> 属性 -> 链接器 -> 常规 -> 附加库目录

    中添加FFmpeg库所在路径。

  • 指定使用哪个库

    1
    项目右键 -> 属性 -> 链接器 -> 输入 -> 附加依赖项

    中指定你所用到的FFmpeg库,如avutil.lib

当上面这此工作完成后,我们就可以在main(...)函数中调用FFmpeg API了,如调用FFmpeg库中的日志函数:

1
2
3
4
5
6
7
8
9
10
11
12
...
extern "C"
{
#include <libavtuil/log.h>
}
...
int main(...)
{
av_log_set_level(AV_LOG_DEBUG);
av_log(NULL, AV_LOG_INFO, "Hello World!\n);
...
}

上述代码中,调用了FFmpeg中的两个API,分别是 av_log_set_level(...)以及av_log(...),这两个函数都是FFmpeg avutil库中的API。所以在使用这两个API之前,我们要在main.c中需要通过#include关键字将 libavtuil/log.h 这个头文件引入进来。

此外,由于FFmpeg是C语言库,而我们用VS创建的是C++工程,所以在引入头文件时需要加上extern "C"关键字,否则的话VS无法将其成功编译。

运行编译好的程序

上面当我们运行编译好的程序时你会发现,它弹出了报错窗口,显示 “无法找到xxx.dll库” 的出错信息,其原因是在运行时无法找到需要的动态库。

解决办法很简单,只需将我们之前编译好的FFmpeg库,即提示的无法找到的.dll库,拷贝到执行程序的同一目录下,这样执行程序就可以找到该库并正确执行了。

编译FFmpeg依赖库

很多时候我们在编译FFmpeg库时还要增加一些其它库,如SDL、x264等,如何能将这些库添加到FFmpeg中呢?

要想将这些库编译到FFmpeg中,首先我们要编译出Windows下可用的对应库,下面咱们就来看一下如何在Windows系统下将它们编译出来。

编译SDL

首先从github上获取SDL源码,命令如下:

1
2
git clone https://github.com/libsdl-org/SDL.git
git checkout release-2.26.x

需要注意的是,SDL现在已经发布了3.0版本,而ffmpeg目前只能用SDL2版本,所以在拉取代码后,需要切换到2.26这个版本

下载好 SDL2 源码后,我们需要使用 CMake 为其生成VS工程,所以我们首先到这里下载CMake,并将其安装到Windows系统上。

之后打开 CMake-GUI,在 CMake-GUI 中指定SDL2源码所在路径以及编译后的输出路径,随后执行

1
Configure -> Generate

生成VS工程。有了VS工程,我们就可以通过VS2019或VS2022来编译SDL了。

需要指出的是,编译好的SDL会保存到指定输出目录的 ReleaseDebug 目录下(例如指定的输出目录为/usr/local/sdl2,则输出路径为/usr/local/sdl2/Release),而我们希望输出的路径则是/usr/local/sdl2/lib

为了满足要求,我们需要在指定输出目录下创建 lib 目录,并将SDL2.lib 和 SDL2.dll文件拷贝到 lib 目录下。同时在 lib 目录下创建 pkgconfig 目录,将sdl2.pc 文件拷贝到该目录中

此外,我们还要修改 sdl2.pc 中的内容,将其中的库路径修改为指定的输出路径,最终完整的目录结构如下所示:

1
2
3
4
5
6
7
/usr/local/sdl2
|------------ lib
| |-- sdl2.lib
| |-- sdl2.dll
| |-- pkgconfig
| |----- sdl2.pc
|------------ include

编译x264

x264库的编译还是比较简单的,与SDL一样我们也要先获取其源码,可以通过下面的命令获取x264源码:

1
git clone https://code.videolan.org/videolan/x264.git

源码获取到后,可以直接在MSYS2环境下编译出Windows下可用的动态库,具体步骤如下:

1
2
3
4
5
6
7
8
9
# 通过VS X64 Native... 窗口打开MSYS2

cd /d/x264 # 在MSYS2中进入x264源码目录

pacman -S automake autoconf libtool # 安装生成Makefile的工具

CC=cl ./configure --prefix=/usr/local/x264 --enable-shared

make -j 4 && make install

通过上面的命令就可以将x264编译出来了。x264编译好后,其输出的目录结构与SDL2是一样的,在/usr/local/x264中包括了includelibbin等目录。

要特别强调的一点是,我们需要将lib目录下的libx264.dll.lib文件名修改为libx264.lib,否则ffmpeg编译时会报 “无法找到该库” 的错误。

编译fdk-aac

fdk-aac的编译与SDL类似,它同样要使用CMake生成VS工程文件,之后再通过VS编译该库。

首先,通下面的的命令获取fdk-aac源码:

1
git clone https://github.com/mstorsjo/fdk-aac.git

之后,通过CMake生成VS工程文件,具体执行步骤请参考 SDL 生成 VS 工程的步骤,这里就不再重复了。

接下来,使用VS2019或VS2022编译fdk-aac,编译好的库同要会被放到Release或Debug目录下,因此我们必须像处理SDL库一样,需要手工组织fdk-aac的输出目录树。

至此fdk-aac就算编译好了。

在编译fdk-aac时有个特殊情况,就是使用CMake的方式无法产生include头文件(这也有可能是我哪块执行的不对)。为了解决这个问题,我又用 MSYS2+mingw 的方式重新编译了一遍fdk-aac,这种方式是可以生成 include 头文件的,然后将生成的头文件手动拷贝到了/usr/local/fdk-aac目录下即可。

FFmpeg如何使用上述编译好的库呢?

首先,我们要设置环境变量PKG_CONFIG_PATH,通过它告诉FFmpeg上述几个库从哪儿可以找到,具体的设置方法如下:

  • 在MSYS2窗口中打开.bashrc
    1
    2
    pacman -S vim
    vim ~/.bashrc
  • ~/.bashrc中设置环境变量
    1
    2
    3
    export PKG_CONFIG_PATH=/usr/local/sdl2/lib/pkgconfig:/usr/local/x264/lib/pkgconfig:/usr/local/fdk-aac/lib/pkgconfig:$PKG_CONFIG_PATH

    :wq #保存并退出vim
  • 让环境变是生效
    1
    source ~/.bashrc

接下来,重新生成FFmpeg的Makefile文件,并重新编译,命令如下:

1
2
3
4
5
./configure --prefix=/usr/local/ffmpeg --arch=x86_64 --enable-shared --disable-ffprobe --disable-doc --enable-libx264 --enable-gpl --enable-fdk-aac --enable-nonfree --toolchain=msvc

make clean

make -j 4 && make install

最后,将sdl2的dll、x264的dll以及fdk-aac的dll拷贝到ffmpeg的bin目录下,这样就可以正确的执行 ffmpeg.exe 或 ffplay.exe 命令了

小结

上面就是在Windows下编译和使用FFmpeg的方法。如果你在Linux或Mac下可以熟练的编译FFmpeg,你会发现,在Window下编译FFmpeg的步骤与在Linux和Mac下编译的步骤是一样的,关键点是在Windows下该如何搭建好编译环境。

此外需要强调的是,在Windows下编译FFmpeg时,由于它不能识别 CC_IDENT 关键字,所以编译时会报错,我们只需将使用该关键字的语句注释掉即可解决该问题。

另外,在程序中通过#include引用FFmpeg头文件时,一定要记得加 extern "C"关键字,告诉C++编译器,这个头文件是一个C类型的头文件,这样它才能正确编译。

附录

  • ShiftMediaProject,有同学给我推荐了这个项目,我简单了解了一下,这个项目真不错,可以直接使用VS对FFmpeg进行调试,有兴趣的同学可以偿试一下。

欢迎关注我的其它发布渠道