最近项目需要,使用了 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位系统的话)。
首先为了提高下载速度,将下载源换成中科大的:
1 | sed -i "s#mirror.msys2.org/#mirrors.ustc.edu.cn/msys2/#g" /etc/pacman.d/mirrorlist* |
然后安装mingw64编译链和基本的依赖:
1 | pacman -S mingw-w64-x86_64-toolchain # mingw64编译工具链,win下的gcc |
安装完毕后,可以输入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 有所区别,目前我还没仔细研究。
官方建议使用 git 下载源码(下载压缩包再解压应该也是一样的):
1 | git clone https://code.videolan.org/videolan/x264.git |
编译和安装
将所有源码放到同一文件夹下便于管理,我把它们都统一放在一个叫 ffmpeg 的文件夹下。然后再建立各自的 install 文件夹存储编译好的库(当然你也可以选择其他任何地方的文件夹)。
为了方便,将编译的命令写成脚本 build-x264.sh
和 build-ffmpeg.sh
。当前文件夹的结构如下(源码文件夹名称被我修改过了):
编译 x264 库
build-x264.sh
脚本内容如下:
1 |
|
注意第一行必须是 #!/bin/sh
,才能被 MSYS2 的 shell 识别为可执行脚本。(亲测在 MSYS2 中chmod
命令没有效果)
这几条命令中最重要的就是./configure
命令,它的参数会指导编译器应该如何编译代码。这里 --prefix
参数指定了编译好的库文件的安装路径,可以自己任意指定。 --enable-shared
代表编译动态库。如果你需要静态库,那么需要加入 -enable-static
参数。
此外,make 命令的-j
参数是指并行编译的线程数,可以根据你的 CPU 核数自行确定。
可以在源码文件夹下,通过
./configure --help
命令查看所有可选参数。
在 MSYS2 的 shell 中,打开源码所在文件夹,并执行脚本:
1 | cd /d/repos/ffmpeg |
注意 MSYS2 中文件路径的写法,是以/d
代表 D 盘,类似 Linux 的风格。
不出意外的话,等待片刻后就会在 x264_install
路径下看到编译好的库。其中 bin/libx264-164.dll
文件就是x264的动态库文件。
如果出现错误,可以先单独执行 .\configure
命令,然后再执行 make
,逐步查找错误原因。
编译 ffmpeg 库
build-ffmpeg.sh
脚本内容如下:
1 |
|
使用的命令与libx264
类似,也是先 configure
再 make
。如果需要添加 x264 支持的话,需要注意以下几点:
- 加入
--enable-libx264
参数 - 指定 PKG_CONFIG_PATH 变量,告知编译器 x264 库的路径
- 指定 x264 库的头文件包含路径及动态库链接的路径
ffmpeg 可自定义的编译参数非常多,有需要可自行研究。
然后同样也是执行脚本即可:
1 | cd /d/repos/ffmpeg |
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命令如下:
1 | gcc avio_reading.c -o test \ |
编译完毕后,将在当前文件夹下生成可执行文件test.exe
。
注意在 shell 中运行程序之前,需要将两个库的安装目录添加到环境变量 PATH (这是MSYS2 的环境变量,不是 Windows 系统的)。
1 | 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 上的安装以及交叉编译的问题。