本篇文章主要是对ffmpeg在Ubuntu上的编译的总结,最后会提供一个编译脚本,来实现一键编译。
我选择的是VirtualBox来安装虚拟机,镜像文件是ubuntu-20.04.4-desktop-amd64.iso,下载地址我用的是网易开源镜像:ubuntu-releases/20.04/。(建议不要使用16.04版本)
这里记录下vim的配置:
输入命令sudo vim /etc/vim/vimrc
打开后在改文件末尾加上如下代码:
set nu #行号
set tabstop #首行缩进
set cursorline #高亮显示
set ruler #右下角显示光标位置
以上的配置按照自己的需求选择。注意:注释部分不要输入进去!
在准备手动编译ffmpeg的时候需要安装必须的支持软件,现在我将它们列举出来:
sudo apt-get update // 从服务器获取软件列表,并在本地保存为文件
sudo apt-get upgrade // 本地安装软件与本地软件列表对比,如本地安装版本低,会提示更新
sudo apt-get install git // 分布式版本控制系统
sudo apt-get install vim // vim编辑器
sudo apt-get install make // 编译工具
sudo apt-get install cmake // x265等所需要的编译工具
// 解决ffplay播放视频报错:Could not initialize SDL - No available video device问题
sudo apt-get install libx11-dev
sudo apt-get install xorg-dev
// 解决ffplay播放音频报错:Could not initialize SDL - Audio target 'pulse' not available,以及No such audio device问题
sudo apt-get install libpulse-dev
// 以下这两个我只安装了libasound2也是可以的,如果不行就两个都安装
sudo apt-get install libasound2
sudo apt-get install libasound2-dev
完成以上的工作就可以开始编写编译脚本了。
准备过程完成后,后面我们就可以编写编译脚本了!
#! /bin/bash
# enableShared=[treu/false]
enableShared=false # true编译动态库,false编译静态库(全局配置)
该脚本是用来做全局配置,目前只有一个选项,用来编译动态库还是静态库,后续会增加其他的全局配置。
#! /bin/bash
SYSTEM=`uname` # 用于显示操作系统名称
MY_DIR=`pwd` # 获取当前目录的绝对路径
PREFIX=${MY_DIR}/output # 输出目录,用于存放生成好的二进制文件
cpu_num=`cat /proc/stat | grep cpu[0-9] -c` # 用于获取当前系统的cpu数量
CLONE_GIT_COMMAND="git clone " # git clone
辅助脚本,用于编译ffmpeg的各个支持包的时候提供帮助。
接下来就是编译ffmpeg各个支持包,总体的原理很简单:
./configure
的安装参数。编码AAC音频,ffmpeg通过编译参数–enable-libfdk-aac来开启
#! /bin/bash
# 编码AAC音频,ffmpeg通过编译参数--enable-libfdk-aac来开启
set -e
FDK_AAC="fdk-aac"
FDK_AAC_VERSION="2.0.2"
FDK_AAC_URL="https://downloads.sourceforge.net/opencore-amr/"
FDK_AAC_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
"
if [[ "$enableShared" == true ]]; then
FDK_AAC_CONFIGURE_COMMAND=$FDK_AAC_CONFIGURE_COMMAND"
--enable-shared
--disable-static
"
else
FDK_AAC_CONFIGURE_COMMAND=$FDK_AAC_CONFIGURE_COMMAND"
--enable-static
--disable-shared
"
fi
echo "==========================download fdk-aac=========================="
if [ ! -e $FDK_AAC"-"$FDK_AAC_VERSION".tar.gz" ]; then
if [[ $SYSTEM == "Darwin" ]]; then
curl $FDK_AAC_URL$FDK_AAC"-"$FDK_AAC_VERSION".tar.gz" > $FDK_AAC"-"$FDK_AAC_VERSION".tar.gz"
else
wget $FDK_AAC_URL$FDK_AAC"-"$FDK_AAC_VERSION".tar.gz" -O $FDK_AAC"-"$FDK_AAC_VERSION".tar.gz"
fi
fi
echo "==========================unzip fdk-aac=========================="
if [ -e $FDK_AAC"-"$FDK_AAC_VERSION".tar.gz" ]; then
if [ -e $FDK_AAC"-"$FDK_AAC_VERSION ]; then
rm -rf $FDK_AAC"-"$FDK_AAC_VERSION
fi
tar zxvf $FDK_AAC"-"$FDK_AAC_VERSION".tar.gz"
fi
echo "==========================build fdk_aac=========================="
if [ -e $FDK_AAC"-"$FDK_AAC_VERSION ]; then
cd $FDK_AAC"-"$FDK_AAC_VERSION
$FDK_AAC_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================fdk_aac build successful!=========================="
注意到该shell脚本的配置(configure)参数有一个选项叫做--prefix=
,事实上该选项主要的作用是配置软件安装的路径,在默认安装的情况下,软件会被安装到/usr/local
目录下。可执行文件放在/usr/local/bin
,库文件放在/usr/local/lib
,等等。如果我们配置一下,可以保证软件被安装到指定目录下面,当前脚本就将软件安装到tools.sh
脚本所配置的目录下。如果你想查看该软件的配置选项,你可以在源码目录下执行./configure -h
来查看所有的配置选项。
编码MP3音频,ffmpeg通过编译参数–enable-libmp3lame来开启
#! /bin/bash
# 编码MP3音频,ffmpeg通过编译参数--enable-libmp3lame来开启
set -e
LAME="lame"
LAME_VERSION="3.100"
LAME_URL="https://sourceforge.net/projects/lame/files/lame/3.100/"
LAME_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
"
if [[ "$enableShared" == true ]]; then
LAME_CONFIGURE_COMMAND=$LAME_CONFIGURE_COMMAND"
--enable-shared
--disable-static
"
else
LAME_CONFIGURE_COMMAND=$LAME_CONFIGURE_COMMAND"
--enable-static
--disable-shared
"
fi
echo "==========================download lame=========================="
if [ ! -e $LAME"-"$LAME_VERSION".tar.gz" ]; then
if [[ $SYSTEM == "Darwin" ]]; then
curl $LAME_URL$LAME"-"$LAME_VERSION".tar.gz" > $LAME"-"$LAME_VERSION".tar.gz"
else
wget $LAME_URL$LAME"-"$LAME_VERSION".tar.gz" -O $LAME"-"$LAME_VERSION".tar.gz"
fi
fi
echo "==========================unzip lame=========================="
if [ -e $LAME"-"$LAME_VERSION".tar.gz" ]; then
if [ -e $LAME"-"$LAME_VERSION ]; then
rm -rf $LAME"-"$LAME_VERSION
fi
tar zxvf $LAME"-"$LAME_VERSION".tar.gz"
fi
echo "==========================build lame=========================="
if [ -e $LAME"-"$LAME_VERSION ]; then
cd $LAME"-"$LAME_VERSION
$LAME_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================lame build successful!=========================="
编码opus音频,ffmpeg通过编译参数–enable-libopus来开启
#! /bin/bash
# 编码opus音频,ffmpeg通过编译参数--enable-libopus来开启
set -e
OPUS="opus"
OPUS_URL="http://downloads.xiph.org/releases/opus/"
OPUS_VERSION="1.3.1"
OPUS_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
"
if [[ "$enableShared" == true ]]; then
OPUS_CONFIGURE_COMMAND=$OPUS_CONFIGURE_COMMAND"
--enable-shared
--disable-static
"
else
OPUS_CONFIGURE_COMMAND=$OPUS_CONFIGURE_COMMAND"
--enable-static
--disable-shared
"
fi
echo "==========================download libopus=========================="
if [ ! -e $OPUS"-"$OPUS_VERSION".tar.gz" ]; then
if [[ $SYSTEM == "Darwin" ]]; then
curl $OPUS_URL$OPUS"-"$OPUS_VERSION".tar.gz" > $OPUS"-"$OPUS_VERSION".tar.gz"
else
wget $OPUS_URL$OPUS"-"$OPUS_VERSION".tar.gz" -O $OPUS"-"$OPUS_VERSION".tar.gz"
fi
fi
echo "==========================unzip libopus=========================="
if [ -e $OPUS"-"$OPUS_VERSION".tar.gz" ]; then
if [ -e $OPUS"-"$OPUS_VERSION ]; then
rm -rf $OPUS"-"$OPUS_VERSION
fi
tar zxvf $OPUS"-"$OPUS_VERSION".tar.gz"
fi
echo "==========================build libopus=========================="
if [ -e $OPUS"-"$OPUS_VERSION ]; then
cd $OPUS"-"$OPUS_VERSION
$OPUS_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================libopus build successful!=========================="
VP8/VP9视频编码器,ffmpeg通过编译参数–enable-libvpx来开启
#! /bin/bash
# VP8/VP9视频编码器,ffmpeg通过编译参数--enable-libvpx来开启
set -e
PATH=$PATH:$PREFIX/bin # 设置环境变量,将$PREFIX/bin目录下的可执行二进制文件设置进去,方便调用
LIBVPX="libvpx"
LIBVPX_URL="http://ftp.osuosl.org/pub/blfs/conglomeration/libvpx/"
LIBVPX_VERSION="1.11.0"
LIBVPX_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
--enable-vp8
--enable-vp9
--enable-vp9-highbitdepth
--enable-vp9-postproc
--enable-vp9-temporal-denoising
--disable-examples
--disable-unit-tests
--as=yasm
"
# --as=yasm 使用yasm汇编
if [[ "$enableShared" == true ]]; then
LIBVPX_CONFIGURE_COMMAND=$LIBVPX_CONFIGURE_COMMAND"
--enable-shared
--disable-static
"
else
LIBVPX_CONFIGURE_COMMAND=$LIBVPX_CONFIGURE_COMMAND"
--enable-static
--disable-shared
"
fi
echo "==========================download libvpx=========================="
if [ ! -e $LIBVPX"-"$LIBVPX_VERSION".tar.gz" ]; then
if [[ $SYSTEM == "Darwin" ]]; then
curl $LIBVPX_URL$LIBVPX"-"$LIBVPX_VERSION".tar.gz" > $LIBVPX"-"$LIBVPX_VERSION".tar.gz"
else
wget $LIBVPX_URL$LIBVPX"-"$LIBVPX_VERSION".tar.gz" -O $LIBVPX"-"$LIBVPX_VERSION".tar.gz"
fi
fi
echo "==========================unzip libvpx=========================="
if [ -e $LIBVPX"-"$LIBVPX_VERSION".tar.gz" ]; then
if [ -e $LIBVPX"-"$LIBVPX_VERSION ]; then
rm -rf $LIBVPX"-"$LIBVPX_VERSION
fi
tar zxvf $LIBVPX"-"$LIBVPX_VERSION".tar.gz"
fi
echo "==========================build libvpx=========================="
if [ -e $LIBVPX"-"$LIBVPX_VERSION ]; then
cd $LIBVPX"-"$LIBVPX_VERSION
$LIBVPX_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================libvpx build successful!=========================="
刚开始的时候遇到找不到yasm,后面知道了yasm编译的静态库的路径需要设置,从而告诉libvpx编译脚本,这段代码PATH=$PATH:$PREFIX/bin
就起到了这个作用,另外编译yasm或者nasm的脚本要放在该脚本执行之前。
编码H.264视频,ffmpeg通过编译参数–enable-gpl --enable-libx264来开启
#! /bin/bash
# 编码H.264视频,ffmpeg通过编译参数--enable-gpl --enable-libx264来开启
set -e
X264="x264"
X264_GIT_URL="https://code.videolan.org/videolan/x264.git"
X264_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
--disable-asm
"
if [[ "$enableShared" == true ]]; then
X264_CONFIGURE_COMMAND=$X264_CONFIGURE_COMMAND"
--enable-shared
"
else
X264_CONFIGURE_COMMAND=$X264_CONFIGURE_COMMAND"
--enable-static
"
fi
echo $CLONE_GIT_COMMAND$X264_GIT_URL
if [ ! -e $X264 ]; then
echo "==========================clone x264=========================="
$CLONE_GIT_COMMAND$X264_GIT_URL
fi
echo "==========================build x264=========================="
if [ -e $X264 ]; then
cd $X264
$X264_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================x264 build successful!=========================="
编码H.265视频,ffmpeg通过编译参数–enable-gpl --enable-libx265来开启
#! /bin/bash
# 编码H.265视频,ffmpeg通过编译参数--enable-gpl --enable-libx265来开启
set -e
PATH=$PATH:$PREFIX/bin
X265="x265_git"
X265_GIT_URL="https://bitbucket.org/multicoreware/x265_git.git"
echo $CLONE_GIT_COMMAND$X265_GIT_URL
if [ ! -e $X265 ]; then
echo "==========================clone x265=========================="
$CLONE_GIT_COMMAND$X265_GIT_URL
fi
echo "==========================build x265=========================="
if [ -e $X265 ]; then
cd $X265/build/linux
if [[ "$enableShared" == true ]]; then
switchStatus=on
else
switchStatus=off
fi
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=$PREFIX -DENABLE_SHARED=$switchStatus ../../source
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================x265 build successful!=========================="
用于ffmpeg编译生成ffplay所必须的SDL2,如果不安装SDL2会导致编译出来的ffmpeg没有ffplay可执行文件。
#! /bin/bash
# SDL2 生成ffplay需要
set -e
SDL2="SDL2"
SDL2_VERSION="2.0.22"
SDL2_URL="http://www.libsdl.org/release/"
SDL2_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
"
if [[ "$enableShared" == true ]]; then
SDL2_CONFIGURE_COMMAND=$SDL2_CONFIGURE_COMMAND"
--enable-shared
--disable-static
"
else
SDL2_CONFIGURE_COMMAND=$SDL2_CONFIGURE_COMMAND"
--enable-static
--disable-shared
"
fi
echo "==========================download SDL2=========================="
if [ ! -e $SDL2"-"$SDL2_VERSION".tar.gz" ]; then
if [[ $SYSTEM == "Darwin" ]]; then
curl $SDL2_URL$SDL2"-"$SDL2_VERSION".tar.gz" > $SDL2"-"$SDL2_VERSION".tar.gz"
else
wget $SDL2_URL$SDL2"-"$SDL2_VERSION".tar.gz" -O $SDL2"-"$SDL2_VERSION".tar.gz"
fi
fi
echo "==========================unzip SDL2=========================="
if [ -e $SDL2"-"$SDL2_VERSION".tar.gz" ]; then
if [ -e $SDL2"-"$SDL2_VERSION ]; then
rm -rf $SDL2"-"$SDL2_VERSION
fi
tar zxvf $SDL2"-"$SDL2_VERSION".tar.gz"
fi
echo "==========================build SDL2=========================="
if [ -e $SDL2"-"$SDL2_VERSION ]; then
cd $SDL2"-"$SDL2_VERSION
$SDL2_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================SDL2 build successful!=========================="
编译ffmpeg的时候解决pkg-config not found
问题
#! /bin/bash
set -e
PKG_CONFIG="pkg-config"
PKG_CONFIG_VERSION="0.29.2"
PKG_CONFIG_URL="https://pkg-config.freedesktop.org/releases/"
PKG_CONFIG_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
--with-internal-glib
"
if [[ "$enableShared" == true ]]; then
PKG_CONFIG_CONFIGURE_COMMAND=$PKG_CONFIG_CONFIGURE_COMMAND"
--enable-shared
"
else
PKG_CONFIG_CONFIGURE_COMMAND=$PKG_CONFIG_CONFIGURE_COMMAND"
--enable-static
"
fi
echo "==========================download pkg-config=========================="
if [ ! -e $PKG_CONFIG"-"$PKG_CONFIG_VERSION".tar.gz" ]; then
if [[ $SYSTEM == "Darwin" ]]; then
curl $PKG_CONFIG_URL$PKG_CONFIG"-"$PKG_CONFIG_VERSION".tar.gz" > $PKG_CONFIG"-"$PKG_CONFIG_VERSION".tar.gz"
else
wget $PKG_CONFIG_URL$PKG_CONFIG"-"$PKG_CONFIG_VERSION".tar.gz" -O $PKG_CONFIG"-"$PKG_CONFIG_VERSION".tar.gz"
fi
fi
echo "==========================unzip pkg-config=========================="
if [ -e $PKG_CONFIG"-"$PKG_CONFIG_VERSION".tar.gz" ]; then
if [ -e $PKG_CONFIG"-"$PKG_CONFIG_VERSION ]; then
rm -rf $PKG_CONFIG"-"$PKG_CONFIG_VERSION
fi
tar zxvf $PKG_CONFIG"-"$PKG_CONFIG_VERSION".tar.gz"
fi
echo "==========================build pkg-config=========================="
if [ -e $PKG_CONFIG"-"$PKG_CONFIG_VERSION ]; then
cd $PKG_CONFIG"-"$PKG_CONFIG_VERSION
$PKG_CONFIG_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================pkg-config build successful!=========================="
编译vpx和ffmpeg的时候需要用到的yasm开源汇编库,貌似yasm只能编译静态库。
#! /bin/bash
set -e
YASM="yasm"
YASM_DOWNLOAD_URL="http://www.tortall.net/projects/yasm/releases/"
YASM_VERSION="1.3.0"
YASM_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
"
echo "==========================download yasm=========================="
if [ ! -e $YASM"-"$YASM_VERSION".tar.gz" ]; then
if [[ $SYSTEM == "Darwin" ]]; then
curl $YASM_DOWNLOAD_URL$YASM"-"$YASM_VERSION".tar.gz" > $YASM"-"$YASM_VERSION".tar.gz"
else
wget $YASM_DOWNLOAD_URL$YASM"-"$YASM_VERSION".tar.gz" -O $YASM"-"$YASM_VERSION".tar.gz"
fi
fi
echo "==========================unzip yasm=========================="
if [ -e $YASM"-"$YASM_VERSION".tar.gz" ]; then
if [ -e $YASM"-"$YASM_VERSION ]; then
rm -rf $YASM"-"$YASM_VERSION
fi
tar zxvf $YASM"-"$YASM_VERSION".tar.gz"
fi
echo "==========================build yasm=========================="
if [ -e $YASM"-"$YASM_VERSION ]; then
cd $YASM"-"$YASM_VERSION
$YASM_CONFIGURE_COMMAND
make clean
make -j${cpu_num}
make install
fi
cd $MY_DIR
echo "==========================yasm build successful!=========================="
上面的脚本完成了支持包的编译,如果遇到下载很慢的支持包,可以预先将其下载下来。而接下来,就可以编译ffmpeg了。
编译ffmpeg
#! /bin/bash
# mac --cc=clang
# 禁用编译器优化选项 --disable-optimizations
# 编译libmp3lame需要使用到--extra-cflags和--extra-ldflags属性
set -e
PATH=$PATH:$PREFIX/lib # 设置环境变量,将$PREFIX/bin目录下的可执行二进制文件设置进去,方便调用
PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig"
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
FFMPEG="FFmpeg"
# 通用配置
COMMON_FFMPEG_CONFIGURE_COMMAND="./configure
--prefix=$PREFIX
--extra-cflags=-I$PREFIX/include
--extra-ldflags=-L$PREFIX/lib
--pkg-config-flags="--static"
--extra-libs="-lpthread"
--enable-ffplay
--enable-gpl
--enable-version3
--disable-optimizations
--enable-debug
--enable-nonfree
--enable-filter=delogo
"
if [[ "$enableShared" == true ]]; then
COMMON_FFMPEG_CONFIGURE_COMMAND=$COMMON_FFMPEG_CONFIGURE_COMMAND"
--enable-shared
--disable-static
"
else
COMMON_FFMPEG_CONFIGURE_COMMAND=$COMMON_FFMPEG_CONFIGURE_COMMAND"
--enable-static
--disable-shared
"
fi
# linux配置
LINUX_FFMPEG_CONFIGURE_COMMAND=$COMMON_FFMPEG_CONFIGURE_COMMAND"
--enable-libx264
--enable-libx265
--enable-libfdk-aac
--enable-libmp3lame
--enable-libopus
--enable-libvpx
"
# mac配置
MAC_CONFIGURE_COMMAND=$COMMON_FFMPEG_CONFIGURE_COMMAND"
--enable-libfdk-aac
--enable-libx264
--enable-libmp3lame
--enable-hardcoded-tables
--host-cflags=
--host-ldflags=
--cc=clang
"
FFMPEG_GIT_URL="[email protected]:FFmpeg/FFmpeg.git"
if [ ! -e $FFMPEG ]; then
echo "==========================clone FFmpeg=========================="
$CLONE_GIT_COMMAND$FFMPEG_GIT_URL
fi
echo "==========================build ffmpeg=========================="
if [ -e $FFMPEG ]; then
cd $FFMPEG
if [[ $SYSTEM == "Darwin" ]]; then
$MAC_FFMPEG_CONFIGURE_COMMAND
else
$LINUX_FFMPEG_CONFIGURE_COMMAND
fi
make clean
make -j${cpu_num}
make install
fi
echo "==========================ffmpeg build successful!=========================="
接下来就是将脚本给串起来。
#! /bin/bash
set -e
source ./tools.sh
source ./config.sh
cd $MY_DIR
startTime=`date +%Y%m%d-%H:%M:%S`
startTime_s=`date +%s`
if [ -e "output" ]; then
rm -rf output
fi
mkdir output
mkdir output/bin
. build_pkg_config.sh
. build_libfdk_aac.sh
. build_libmp3lame.sh
. build_libopus.sh
. build_sdl2.sh
. build_yasm.sh
. build_libvpx.sh
. build_libx264.sh
. build_libx265.sh
. build_ffmpeg.sh
endTime=`date +%Y%m%d-%H:%M:%S`
endTime_s=`date +%s`
sumTime=$[ $endTime_s - $startTime_s ]
echo "Total Compilation Time $sumTime seconds"
echo "==========================test ffmpeg!=========================="
if [[ "$enableShared" == true ]]; then
export LD_LIBRARY_PATH=$MY_DIR/output/lib/
cd $MY_DIR/output/bin
./ffmpeg -version
else
cd $MY_DIR/output/bin
./ffmpeg -version
fi
build.sh就是启动入口,调用指令是./build.sh
,当然为了避免出现权限问题,建议首先执行 chmod +x build.sh
。
编译成功后,会出现如下结果:
代表编译成功,编译完成后,你可以找到output目录,该目录下有四个目录,它们分别是:
调用ffplay播放视频成功:
编译静态库,无论执行ffplay还是ffmpeg都不需要做任何配置。但是,如果编译的是动态库,那么需要通过export LD_LIBRARY_PATH=你编译好的动态库的绝对路径
来设置下动态库的路径,我的建议是写一个脚本,类似这样:
#! /bin/bash
set -e
export LD_LIBRARY_PATH=你编译好的动态库的绝对路径(自己填写路径)
./ffplay ffmpeg-test-video.mp4
写好后,将该脚本扔到output
目录下面(测试的音视频也扔到output
目录下),然后执行脚本就可以了。
为了方便大家编译ffmpeg,我直接给出该脚本的git地址,供大家学习!
github地址:MyFFmpeg
clone地址:
git clone git@github.com:rq973017553/MyFFmpeg.git
以上就是关于在ubuntu上,编译ffmpeg以及编译ffmpeg支持包的脚本。你完全可以在按下一个回车键之后,泡一杯咖啡等待编译自动完成!