最近项目需要,使用了 ffmpeg 做摄像头视频采集和串流。这几天有点时间,打算把相关的一些知识记录分享一下。

在撰写本文时,我又在另外一台电脑上把 ffmpeg 重新安装了一遍,所以绝对真实靠谱!如果你觉得文章写得还不错,敬请点个赞支持一下,十分感谢~

ffmpeg 简介

ffmpeg是一套跨平台的,用于音视频录制、转换、流化等操作的完善的解决方案,它是业界最负盛名的开源音视频框架之一。许多软件都是基于ffmpeg开发的,如格式工厂、各种xx影音等。

ffmpeg 是一套开源库以及命令行工具的集合,用户既可以使用命令行直接对音视频进行操作(CLI),也可以调用其开源库进行个性化的功能开发(SDK)。

如果要在自己的程序中使用 ffmpeg ,那么使用它的 SDK 是最好的选择。当前 ffmpeg 包含以下几个库:

  • libavcodec : 编/解码
  • libavfilter : 帧级操作(如添加滤镜)
  • libavformat : 文件 I/O 和 封装/解封装
  • libavdevice : 设备视频文件的封装/解封装
  • libavutil : 通用工具集合
  • libswresample : 音频重采样、格式处理、混音等
  • libpostproc : 预处理
  • libswscale : 色彩处理和缩放

ffmpeg 库在 Windows 下的安装

这个项目大部分是在 Linux 开发板上做的,Windows 上占一小部分。虽然如此,在 Windows 上安装 ffmpeg 的步骤一点都没法省。

ffmpeg 目前不提供预编译的库文件,而是需要自己下载源码并编译。看网上说 Windows 下编译 ffmpeg 非常麻烦,我想应该是“找到好用的教程”比较麻烦。本文使用 MSYS2 来编译 ffmpeg ,许多问题可以迎刃而解!

环境准备

在 Windows 下,编译需要做的准备如下:

  • 安装并配置 MYSY2
  • 安装 git (可选)
  • ffmpeg 源码
  • x264 源码(可选)

本节只讲述 MSYS2 的安装和配置和源码的下载。git 可根据需要自行选择安装。

安装 MSYS2 及编译工具链

MSYS2 是 Windows 下的一组编译套件,它可以在 Windows 系统中模拟 Linux 下的编译环境,如使用 shell 运行命令、使用 pacman 安装软件包、使用 gcc (MinGW) 编译代码等。简单来说,使用 MSYS2 ,你可以通过在 Linux 下非常熟悉的各种命令,来编译 Windows 下的软件。

官网描述:It provides a native build environment, based on open source software, and makes you feel right at home when you are already comfortable with Linux.

MSYS2 的安装也非常省心,只需要到 MSYS2 官网 下载.exe安装包,管理员身份运行安装即可。

注意安装盘必须是NTFS,路径要全使用 ACSII 字符,不能有空格。建议就安装在默认位置,如果不想装在 C 盘,就直接改下盘符,装在其他盘的根目录。

安装完毕后,开始菜单里就会有下面的程序:

点击它们就会启动一个 shell 窗口,Just like on Linux ! 这个 shell 程序默认是 Mintty,类似 Linux 系统中的 bash shell。MSYS2 支持多个编译器工具链,它们的环境是独立的(可以去安装文件夹查看),这里选择启动 MINGW64 (如果你也是64位系统的话)。

首先为了提高下载速度,将下载源换成中科大的:

sed -i "s#mirror.msys2.org/#mirrors.ustc.edu.cn/msys2/#g" /etc/pacman.d/mirrorlist*pacman -Sy

然后安装mingw64编译链和基本的依赖:

pacman -S mingw-w64-x86_64-toolchain  # mingw64编译工具链,win下的gccpacman -S base-devel    # 一些基本的编译工具pacman -S yasm nasm     # 汇编器

安装完毕后,可以输入gcc -v查看 gcc 版本:

最后需要添加环境变量。右击此电脑 -> 属性 -> 高级系统设置 -> 环境变量 -> 选择 Path (用户变量和系统变量都要)-> 编辑 -> 新建,添加编译工具链的路径:

注意如果 MSYS2 没有安装在 C 盘,或者使用的不是 MINGW64 的shell,那么这里需要改成对应的路径。

添加环境变量这一步,是为了以后使用其他编辑器或者IDE时,能够找到 MINGW64 的编译工具链。在 MSYS2 中编译 ffmpeg 本身是不需要添加 Windows 的环境变量的。

ffmpeg 源码下载

在 ffmpeg 官网 下载源码,目前最新的版本是 5.1.2 。注意不要下载成 executable files 了,那个是可以直接运行的 CLI 程序。

你也可以直接下载 snapshot 版本,不过我个人更愿意下载带版本数字的。试想两年之后,谁能知道你电脑里的 snapshot 是何年何月的 snapshot 呢?

三个 download 都可以,只是压缩包格式不一样:

下载后解压到一个好找的文件夹即可。

x264 源码下载

ffmpeg 提供了相当多的外部库支持,但是如果要使用的话需要自己编译外部库。因为项目需要用到视频编码,所以此处加入 x264 库。

libx264 由 VideoLAN 组织所发布,它是 H.264 的一套性能较好的软编码器实现(不包括解码器)。H.264 (AVC) 是当前较常用的视频编码,目前 H.264 的继任者 H.265 (HEVC) 也渐趋成熟, VideoLAN 也有一套实现 libx265 。不过 libx265 的编译方式与 libx264 有所区别,目前我还没仔细研究。

戳这里访问 x264 的官方页面

官方建议使用 git 下载源码(下载压缩包再解压应该也是一样的):

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

编译和安装

将所有源码放到同一文件夹下便于管理,我把它们都统一放在一个叫 ffmpeg 的文件夹下。然后再建立各自的 install 文件夹存储编译好的库(当然你也可以选择其他任何地方的文件夹)。

为了方便,将编译的命令写成脚本 build-x264.shbuild-ffmpeg.sh。当前文件夹的结构如下(源码文件夹名称被我修改过了):

编译 x264 库

build-x264.sh脚本内容如下:

#!/bin/shbasepath=$(cd `dirname $0`;pwd)echo ${basepath}cd ${basepath}/x264-src   # 根据路径名称自行修改pwd./configure --prefix=${basepath}/x264_install --enable-sharedmake -j8make install

注意第一行必须是 #!/bin/sh ,才能被 MSYS2 的 shell 识别为可执行脚本。(亲测在 MSYS2 中chmod命令没有效果)

这几条命令中最重要的就是./configure命令,它的参数会指导编译器应该如何编译代码。这里 --prefix 参数指定了编译好的库文件的安装路径,可以自己任意指定。 --enable-shared 代表编译动态库。如果你需要静态库,那么需要加入 -enable-static 参数。

此外,make 命令的-j参数是指并行编译的线程数,可以根据你的 CPU 核数自行确定。

可以在源码文件夹下,通过 ./configure --help 命令查看所有可选参数。

在 MSYS2 的 shell 中,打开源码所在文件夹,并执行脚本:

cd /d/repos/ffmpeg./build-x264.sh

注意 MSYS2 中文件路径的写法,是以/d代表 D 盘,类似 Linux 的风格。

不出意外的话,等待片刻后就会在 x264_install 路径下看到编译好的库。其中 bin/libx264-164.dll 文件就是x264的动态库文件。

如果出现错误,可以先单独执行 .\configure 命令,然后再执行 make ,逐步查找错误原因。

编译 ffmpeg 库

build-ffmpeg.sh脚本内容如下:

#!/bin/shbasepath=$(cd `dirname $0`;pwd)echo ${basepath}cd ${basepath}/ffmpeg-5.1.2-srcpwdexport PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/d/repos/ffmpeg/x264_install/lib/pkgconfigecho ${PKG_CONFIG_PATH}./configure --prefix=${basepath}/ffmpeg_5.2.1_install \--enable-gpl --enable-libx264 --disable-static --enable-shared \--extra-cflags=-l${basepath}/x264_install/include --extra-ldflags=-L${basepath}/x264_install/libmake -j8make install

使用的命令与libx264类似,也是先 configuremake 。如果需要添加 x264 支持的话,需要注意以下几点:

  • 加入 --enable-libx264 参数
  • 指定 PKG_CONFIG_PATH 变量,告知编译器 x264 库的路径
  • 指定 x264 库的头文件包含路径及动态库链接的路径

ffmpeg 可自定义的编译参数非常多,有需要可自行研究。

然后同样也是执行脚本即可:

cd /d/repos/ffmpeg./build-ffmpeg.sh

ffmpeg 代码量较大,可能会编译比较久,多线程 make 可加快编译速度。我使用make -j8大约花了七八分钟。

编译完成后,就可以在 ffmpeg_5.2.1_install 路径下看到库文件了。其中 bin 下的一堆 dll 就是动态库文件。

现在 ffmpeg 的 SDK 就任你调用了!下一节我们来试试调用 ffmpeg 编写程序。

ffmpeg 的 Hello World 程序

在 ffmpeg 安装路径下,打开 share\ffmpeg\examples ,可以看到 ffmpeg 的示例程序,它们也可以在 ffmpeg 的在线 API 文档 中查看到。

其中的 avio_reading.c 相当于 ffmpeg 的 Hello World,它会读取一个媒体文件的元数据信息并打印显示。

另外建一个文件夹,将avio_reading.c复制过去,然后用在 MYSY2 中打开这个目录,使用 gcc 命令编译。

gcc命令如下:

gcc avio_reading.c -o test \-I"D:/repos/ffmpeg/ffmpeg_5.2.1_install/include/" \-L"D:/repos/ffmpeg/ffmpeg_5.2.1_install/bin/" \-lavcodec -lavformat -lavutil

编译完毕后,将在当前文件夹下生成可执行文件test.exe

注意在 shell 中运行程序之前,需要将两个库的安装目录添加到环境变量 PATH (这是MSYS2 的环境变量,不是 Windows 系统的)。

export PATH=$PATH:/d/repos/ffmpeg/x264_install/bin:/d/repos/ffmpeg/ffmpeg_5.2.1_install/bin

如果不执行export命令的话,那么运行test.exe时就无法链接到动态库,更令人困扰的是不会弹出任何提示,所以一定记得添加。当然如果你觉得每次打开都要运行太麻烦,也可以将这条命令添加到 你的安装位置/msys64/etc/profile 文件的末尾,这个文件和 Linux 下的/etc/profile文件作用是类似的。

运行测试效果如下:

至此,我们迈出了使用 ffmpeg 库的第一步——也是一大步!

由于 gcc 的编译命令很长,重复手打很不方便,所以我一般会使用 vscode+cmake 的方式来做开发。不过这个配置又是较为麻烦的一件事,限于篇幅本文不再详述,感兴趣的读者可自行查阅资料。基本上只要注意把 gcc 的命令参数转换到 CmakeLists.txt 文件里,并注意终端的环境变量配置即可。

入门资料

ffmpeg 我也是最近才开始用,官方对 SDK 没有详细的入门教程,仅提供了 Doxygen 风格的 API 文档供查询。所以这里贴两个我觉得很好的入门帖,供与我一样刚刚入门的朋友参考。

首先是 Github 上的一篇tutorial:ffmpeg-libav-tutorial ,篇幅不长,读完可以对音视频有一个基本的认知。

然后是已故的音视频领域先驱雷霄骅(雷神)的博客 。需要注意的是现在的 ffmpeg 相比雷神当年使用的版本已经有了许多变化,使用雷神的源代码有时还需要修改。(斯人已逝,生者如斯!)

其他较为系统的参考资料我还没有找到,基本就是根据需要去百度or谷歌。有时 ffmpeg 官网也能派上一些用场,可以多翻翻。

后记

MSYS2 真是个好东西!

下一篇将讨论 ffmpeg 在 Linux 上的安装以及交叉编译的问题。

参考资料:
MSYS2中科大镜像源帮助
FFmpeg编译无坑版(Windows篇)