Last active
May 9, 2024 07:12
-
-
Save TinDang97/d1f8dd9f7215e98a8fc1ee3a85c4f8d4 to your computer and use it in GitHub Desktop.
Build FFMPEG script with full feature, include scale_cuda, scale_npp, vpx, libx,...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# https://github.com/markus-perl/ffmpeg-build-script | |
PROGNAME=$(basename $0) | |
VERSION=1.18 | |
CWD=$(pwd) | |
PACKAGES="$CWD/packages" | |
WORKSPACE="$CWD/workspace" | |
CFLAGS="-I$WORKSPACE/include" | |
LDFLAGS="-L$WORKSPACE/lib" | |
LDEXEFLAGS="" | |
EXTRALIBS="-lpthread -lm -lz" | |
CONFIGURE_OPTIONS=() | |
# Speed up the process | |
# Env Var NUMJOBS overrides automatic detection | |
if [[ -n $NUMJOBS ]]; then | |
MJOBS=$NUMJOBS | |
elif [[ -f /proc/cpuinfo ]]; then | |
MJOBS=$(grep -c processor /proc/cpuinfo) | |
elif [[ "$OSTYPE" == "darwin"* ]]; then | |
MJOBS=$(sysctl -n machdep.cpu.thread_count) | |
CONFIGURE_OPTIONS=("--enable-videotoolbox") | |
else | |
MJOBS=4 | |
fi | |
make_dir () { | |
remove_dir "$1" | |
if ! mkdir "$1"; then | |
printf "\n Failed to create dir %s" "$1"; | |
exit 1 | |
fi | |
} | |
remove_dir () { | |
if [ -d "$1" ]; then | |
rm -r "$1" | |
fi | |
} | |
download () { | |
# download url [filename[dirname]] | |
DOWNLOAD_PATH="$PACKAGES" | |
DOWNLOAD_FILE=${2:-"${1##*/}"} | |
if [[ "$DOWNLOAD_FILE" =~ "tar." ]]; then | |
TARGETDIR="${DOWNLOAD_FILE%.*}" | |
TARGETDIR=${3:-"${TARGETDIR%.*}"} | |
else | |
TARGETDIR=${3:-"${DOWNLOAD_FILE%.*}"} | |
fi | |
if [ ! -f "$DOWNLOAD_PATH/$DOWNLOAD_FILE" ]; then | |
echo "Downloading $1" | |
curl -L --silent -o "$DOWNLOAD_PATH/$DOWNLOAD_FILE" "$1" | |
EXITCODE=$? | |
if [ $EXITCODE -ne 0 ]; then | |
echo "" | |
echo "Failed to download $1. Exitcode $EXITCODE. Retrying in 10 seconds"; | |
sleep 10 | |
curl -L --silent -o "$DOWNLOAD_PATH/$DOWNLOAD_FILE" "$1" | |
fi | |
EXITCODE=$? | |
if [ $EXITCODE -ne 0 ]; then | |
echo "" | |
echo "Failed to download $1. Exitcode $EXITCODE"; | |
exit 1 | |
fi | |
echo "... Done" | |
else | |
echo "$DOWNLOAD_FILE has already downloaded." | |
fi | |
make_dir "$DOWNLOAD_PATH/$TARGETDIR" | |
if [ -n "$3" ]; then | |
if ! tar -xvf "$DOWNLOAD_PATH/$DOWNLOAD_FILE" -C "$DOWNLOAD_PATH/$TARGETDIR" 2>/dev/null >/dev/null; then | |
echo "Failed to extract $DOWNLOAD_FILE"; | |
exit 1 | |
fi | |
else | |
if ! tar -xvf "$DOWNLOAD_PATH/$DOWNLOAD_FILE" -C "$DOWNLOAD_PATH/$TARGETDIR" --strip-components 1 2>/dev/null >/dev/null; then | |
echo "Failed to extract $DOWNLOAD_FILE"; | |
exit 1 | |
fi | |
fi | |
echo "Extracted $DOWNLOAD_FILE"; | |
cd "$DOWNLOAD_PATH/$TARGETDIR" || (echo "Error has occurred." ; exit 1) | |
} | |
execute () { | |
echo "$ $*" | |
OUTPUT=$("$@" 2>&1) | |
# shellcheck disable=SC2181 | |
if [ $? -ne 0 ]; then | |
echo "$OUTPUT" | |
echo "" | |
echo "Failed to Execute $*" >&2 | |
exit 1 | |
fi | |
} | |
build () { | |
echo "" | |
echo "building $1" | |
echo "=======================" | |
if [ -f "$PACKAGES/$1.done" ]; then | |
echo "$1 already built. Remove $PACKAGES/$1.done lockfile to rebuild it." | |
return 1 | |
fi | |
return 0 | |
} | |
command_exists() { | |
if ! [[ -x $(command -v "$1") ]]; then | |
return 1 | |
fi | |
return 0 | |
} | |
build_done () { | |
touch "$PACKAGES/$1.done" | |
} | |
cleanup () { | |
remove_dir "$PACKAGES" | |
remove_dir "$WORKSPACE" | |
echo "Cleanup done." | |
echo "" | |
} | |
usage () { | |
echo "Usage: $PROGNAME [OPTIONS]" | |
echo "Options:" | |
echo " -h, --help Display usage information" | |
echo " --version Display version information" | |
echo " -b, --build Starts the build process" | |
echo " -c, --cleanup Remove all working dirs" | |
echo " -f, --full-static Complete static build of ffmpeg (eg. glibc, pthreads etc...) **not recommend**" | |
echo " Note: Because of the NSS (Name Service Switch), glibc does not recommend static links." | |
echo "" | |
} | |
while (( $# > 0 )); do | |
case $1 in | |
-h | --help) | |
usage | |
exit 0 | |
;; | |
--version) | |
echo $VERSION | |
exit 0 | |
;; | |
-*) | |
if [[ "$1" == "--build" || "$1" =~ 'b' ]]; then | |
bflag='-b' | |
fi | |
if [[ "$1" == "--cleanup" || "$1" =~ 'c' ]]; then | |
cflag='-c' | |
cleanup | |
fi | |
if [[ "$1" == "--full-static" || "$1" =~ 'f' ]]; then | |
LDEXEFLAGS="-static" | |
fi | |
shift | |
;; | |
*) | |
usage | |
exit 1 | |
;; | |
esac | |
done | |
if [ -z $bflag ]; then | |
if [ -z $cflag ]; then | |
usage | |
exit 1 | |
fi | |
exit 0 | |
fi | |
echo "ffmpeg-build-script v$VERSION" | |
echo "=========================" | |
echo "" | |
echo "Using $MJOBS make jobs simultaneously." | |
if [[ -n $LDEXEFLAGS ]]; then | |
echo "Start the build in full static mode." | |
fi | |
mkdir -p "$PACKAGES" | |
mkdir -p "$WORKSPACE" | |
export PATH="${WORKSPACE}/bin:$PATH" | |
if ! command_exists "make"; then | |
echo "make not installed."; | |
exit 1 | |
fi | |
if ! command_exists "g++"; then | |
echo "g++ not installed."; | |
exit 1 | |
fi | |
if ! command_exists "curl"; then | |
echo "curl not installed."; | |
exit 1 | |
fi | |
## | |
## Pre-requirement | |
## | |
echo "Installing prerequisites" | |
sudo apt-get update | |
sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev libgpac-dev \ | |
libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev \ | |
libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev cmake nasm gcc-8 g++-8 | |
sudo ln -s $(which gcc-8) /usr/local/bin/gcc | |
sudo ln -s $(which g++-8) /usr/local/bin/g++ | |
if build "yasm"; then | |
download "https://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" | |
execute make -j $MJOBS | |
execute make install | |
build_done "yasm" | |
fi | |
if build "nasm"; then | |
download "https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static | |
execute make -j $MJOBS | |
execute make install | |
build_done "nasm" | |
fi | |
if build "pkg-config"; then | |
download "https://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz" | |
execute ./configure --silent --prefix="${WORKSPACE}" --with-pc-path="${WORKSPACE}"/lib/pkgconfig --with-internal-glib | |
execute make -j $MJOBS | |
execute make install | |
build_done "pkg-config" | |
fi | |
#if build "cmake"; then | |
# download "https://cmake.org/files/v3.15/cmake-3.15.4.tar.gz" | |
# rm Modules/FindJava.cmake | |
# perl -p -i -e "s/get_filename_component.JNIPATH/#get_filename_component(JNIPATH/g" Tests/CMakeLists.txt | |
# perl -p -i -e "s/get_filename_component.JNIPATH/#get_filename_component(JNIPATH/g" Tests/CMakeLists.txt | |
# execute ./configure --prefix="${WORKSPACE}" | |
# execute make -j $MJOBS | |
# execute make install | |
# build_done "cmake" | |
#fi | |
## | |
## video library | |
## | |
if build "x264"; then | |
download "https://code.videolan.org/videolan/x264/-/archive/stable/x264-stable.tar.bz2" | |
if [[ "$OSTYPE" == "linux-gnu" ]]; then | |
execute ./configure --prefix="${WORKSPACE}" --enable-static --enable-pic CXXFLAGS="-fPIC" | |
else | |
execute ./configure --prefix="${WORKSPACE}" --enable-static --enable-pic | |
fi | |
execute make -j $MJOBS | |
execute make install | |
execute make install-lib-static | |
build_done "x264" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libx264") | |
if build "x265"; then | |
download "https://github.com/videolan/x265/archive/Release_3.5.tar.gz" "x265-3.5.tar.gz" | |
cd source || exit | |
execute cmake -DCMAKE_INSTALL_PREFIX:PATH="${WORKSPACE}" -DENABLE_SHARED:bool=off -DSTATIC_LINK_CRT:BOOL=ON -DENABLE_CLI:BOOL=OFF . | |
execute make -j $MJOBS | |
execute make install | |
sed -i 's/-lgcc_s/-lgcc_eh/g' "$WORKSPACE/lib/pkgconfig/x265.pc" | |
build_done "x265" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libx265") | |
if build "libvpx"; then | |
download "https://github.com/webmproject/libvpx/archive/v1.9.0.tar.gz" "libvpx-1.9.0.tar.gz" | |
if [[ "$OSTYPE" == "darwin"* ]]; then | |
echo "Applying Darwin patch" | |
sed "s/,--version-script//g" build/make/Makefile > build/make/Makefile.patched | |
sed "s/-Wl,--no-undefined -Wl,-soname/-Wl,-undefined,error -Wl,-install_name/g" build/make/Makefile.patched > build/make/Makefile | |
fi | |
execute ./configure --prefix="${WORKSPACE}" --disable-unit-tests --disable-shared | |
execute make -j $MJOBS | |
execute make install | |
build_done "libvpx" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libvpx") | |
if build "xvidcore"; then | |
download "https://downloads.xvid.com/downloads/xvidcore-1.3.7.tar.gz" | |
cd build/generic || exit | |
execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static | |
execute make -j $MJOBS | |
execute make install | |
if [[ -f ${WORKSPACE}/lib/libxvidcore.4.dylib ]]; then | |
execute rm "${WORKSPACE}/lib/libxvidcore.4.dylib" | |
fi | |
if [[ -f ${WORKSPACE}/lib/libxvidcore.so ]]; then | |
execute rm "${WORKSPACE}"/lib/libxvidcore.so* | |
fi | |
build_done "xvidcore" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libxvid") | |
if build "vid_stab"; then | |
download "https://github.com/georgmartius/vid.stab/archive/v1.1.0.tar.gz" "vid.stab-1.1.0.tar.gz" | |
execute cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH="${WORKSPACE}" -DUSE_OMP=OFF -DENABLE_SHARED:bool=off . | |
execute make | |
execute make install | |
build_done "vid_stab" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libvidstab") | |
if build "av1"; then | |
download "https://aomedia.googlesource.com/aom/+archive/430d58446e1f71ec2283af0d6c1879bc7a3553dd.tar.gz" "av1.tar.gz" "av1" | |
make_dir "$PACKAGES"/aom_build | |
cd "$PACKAGES"/aom_build || exit | |
execute cmake -DENABLE_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH="${WORKSPACE}" "$PACKAGES"/av1 | |
execute make -j $MJOBS | |
execute make install | |
build_done "av1" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libaom") | |
## | |
## audio library | |
## | |
if build "opencore"; then | |
download "https://deac-riga.dl.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-0.1.5.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static | |
execute make -j $MJOBS | |
execute make install | |
build_done "opencore" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libopencore_amrnb" "--enable-libopencore_amrwb") | |
if build "lame"; then | |
download "https://netcologne.dl.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static | |
execute make -j $MJOBS | |
execute make install | |
build_done "lame" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libmp3lame") | |
if build "opus"; then | |
download "https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static | |
execute make -j $MJOBS | |
execute make install | |
build_done "opus" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libopus") | |
if build "libogg"; then | |
download "https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.3.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static | |
execute make -j $MJOBS | |
execute make install | |
build_done "libogg" | |
fi | |
if build "libvorbis"; then | |
download "https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.6.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" --with-ogg-libraries="${WORKSPACE}"/lib --with-ogg-includes="${WORKSPACE}"/include/ --enable-static --disable-shared --disable-oggtest | |
execute make -j $MJOBS | |
execute make install | |
build_done "libvorbis" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libvorbis") | |
if build "libtheora"; then | |
download "https://ftp.osuosl.org/pub/xiph/releases/theora/libtheora-1.1.1.tar.gz" | |
sed "s/-fforce-addr//g" configure > configure.patched | |
chmod +x configure.patched | |
mv configure.patched configure | |
execute ./configure --prefix="${WORKSPACE}" --with-ogg-libraries="${WORKSPACE}"/lib --with-ogg-includes="${WORKSPACE}"/include/ --with-vorbis-libraries="${WORKSPACE}"/lib --with-vorbis-includes="${WORKSPACE}"/include/ --enable-static --disable-shared --disable-oggtest --disable-vorbistest --disable-examples --disable-asm --disable-spec | |
execute make -j $MJOBS | |
execute make install | |
build_done "libtheora" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libtheora") | |
if build "fdk_aac"; then | |
download "https://sourceforge.net/projects/opencore-amr/files/fdk-aac/fdk-aac-2.0.1.tar.gz/download?use_mirror=gigenet" "fdk-aac-2.0.1.tar.gz" | |
execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static | |
execute make -j $MJOBS | |
execute make install | |
build_done "fdk_aac" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libfdk-aac") | |
## | |
## other library | |
## | |
if build "zlib"; then | |
download "https://www.zlib.net/zlib-1.2.11.tar.gz" | |
execute ./configure --static --prefix="${WORKSPACE}" | |
execute make -j $MJOBS | |
execute make install | |
build_done "zlib" | |
fi | |
if build "openssl"; then | |
download "https://www.openssl.org/source/openssl-1.1.1h.tar.gz" | |
execute ./config --prefix="${WORKSPACE}" --openssldir="${WORKSPACE}" --with-zlib-include="${WORKSPACE}"/include/ --with-zlib-lib="${WORKSPACE}"/lib no-shared zlib | |
execute make -j $MJOBS | |
execute make install | |
build_done "openssl" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-openssl") | |
if build "srt"; then | |
download "https://github.com/Haivision/srt/archive/v1.4.1.tar.gz" "srt-1.4.1.tar.gz" | |
export OPENSSL_ROOT_DIR="${WORKSPACE}" | |
export OPENSSL_LIB_DIR="${WORKSPACE}"/lib | |
export OPENSSL_INCLUDE_DIR="${WORKSPACE}"/include/ | |
execute cmake . -DCMAKE_INSTALL_PREFIX:PATH="${WORKSPACE}" -DENABLE_SHARED=OFF -DENABLE_STATIC=ON -DENABLE_APPS=OFF -DUSE_STATIC_LIBSTDCXX=ON | |
execute make install | |
sed -i 's/-lgcc_s/-lgcc_eh/g' "$WORKSPACE/lib/pkgconfig/srt.pc" | |
build_done "srt" | |
fi | |
CONFIGURE_OPTIONS+=("--enable-libsrt") | |
## | |
## HWaccel library | |
## | |
if command -V nvcc > /dev/null ; then | |
if build "nv-codec"; then | |
download "https://github.com/FFmpeg/nv-codec-headers/releases/download/n10.0.26.0/nv-codec-headers-10.0.26.0.tar.gz" | |
sed -i "s#PREFIX = /usr/local#PREFIX = ${WORKSPACE}#g" Makefile | |
execute make install | |
build_done "nv-codec" | |
fi | |
CFLAGS+=" -I/usr/local/cuda/include" | |
LDFLAGS+=" -L/usr/local/cuda/lib64" | |
CONFIGURE_OPTIONS+=("--enable-cuda-nvcc" "--enable-cuvid" "--enable-nvenc" "--enable-cuda-llvm") | |
if [ -z $LDEXEFLAGS ]; then | |
CONFIGURE_OPTIONS+=("--enable-libnpp") # Only libnpp cannot be static link. | |
fi | |
echo "" | |
if [[ -z "$CUDA_ARCH" ]]; then | |
echo "Please give me your CUDA_ARCH at https://developer.nvidia.com/cuda-gpus." | |
echo "Pre-setup by \"export CUDA_ARCH=XX\"" | |
echo "Example: \"50\" if compute capability version is 5.0" | |
read -r -p "> CUDA_ARC=" cuda_arch | |
re='^[0-9]+$' | |
if ! [[ $cuda_arch =~ $re ]] ; then | |
echo "Verion not supported!" | |
fi | |
CUDA_ARCH="$cuda_arch" | |
else | |
echo "> CUDA_ARC=$CUDA_ARCH" | |
fi | |
# check at https://developer.nvidia.com/cuda-gpus | |
CONFIGURE_OPTIONS+=("--nvccflags=-gencode arch=compute_$CUDA_ARCH,code=sm_$CUDA_ARCH -O2") | |
echo "=======================" | |
fi | |
## | |
## FFmpeg | |
## | |
build "ffmpeg" | |
download "https://ffmpeg.org/releases/ffmpeg-4.3.1.tar.bz2" | |
echo "./configure \\" | |
for lib in "${CONFIGURE_OPTIONS[@]}" | |
do | |
echo "$lib \\" | |
done | |
echo "--disable-debug \\" | |
echo "--disable-shared \\" | |
echo "--enable-gpl \\" | |
echo "--enable-nonfree \\" | |
echo "--enable-pthreads \\" | |
echo "--enable-static \\" | |
echo "--enable-small \\" | |
echo "--enable-version3 \\" | |
echo "--extra-cflags=\"${CFLAGS}\" \\" | |
echo "--extra-ldflags=\"${LDFLAGS}\" \\" | |
echo "--extra-libs=\"${EXTRALIBS}\" \\" | |
echo "--pkgconfigdir=\"$WORKSPACE/lib/pkgconfig\" \\" | |
echo "--pkg-config-flags=\"--static\" \\" | |
echo "--prefix=\"${WORKSPACE}\"" | |
echo "=======================" | |
./configure "${CONFIGURE_OPTIONS[@]}" \ | |
--disable-debug \ | |
--disable-doc \ | |
--disable-shared \ | |
--enable-gpl \ | |
--enable-nonfree \ | |
--enable-pthreads \ | |
--enable-static \ | |
--enable-small \ | |
--enable-version3 \ | |
--extra-cflags="${CFLAGS}" \ | |
--extra-ldexeflags="${LDEXEFLAGS}" \ | |
--extra-ldflags="${LDFLAGS}" \ | |
--extra-libs="${EXTRALIBS}" \ | |
--pkgconfigdir="$WORKSPACE/lib/pkgconfig" \ | |
--pkg-config-flags="--static" \ | |
--prefix="${WORKSPACE}" | |
execute make -j $MJOBS | |
execute make install | |
INSTALL_FOLDER="/usr/bin" | |
if [[ "$OSTYPE" == "darwin"* ]]; then | |
INSTALL_FOLDER="/usr/local/bin" | |
fi | |
echo "" | |
echo "Building done. The binary can be found here: $WORKSPACE/bin/ffmpeg" | |
echo "" | |
if [[ $AUTOINSTALL == "yes" ]]; then | |
sudo cp "$WORKSPACE/bin/ffmpeg" "$INSTALL_FOLDER/ffmpeg" | |
sudo cp "$WORKSPACE/bin/ffprobe" "$INSTALL_FOLDER/ffprobe" | |
sudo cp "$WORKSPACE/bin/ffplay" "$INSTALL_FOLDER/ffplay" | |
echo "Done. ffmpeg is now installed to your system" | |
elif [[ ! $SKIPINSTALL == "yes" ]]; then | |
read -r -p "Install the binary to your $INSTALL_FOLDER folder? [Y/n] " response | |
case $response in | |
[yY][eE][sS]|[yY]) | |
sudo cp "$WORKSPACE/bin/ffmpeg" "$INSTALL_FOLDER/ffmpeg" | |
sudo cp "$WORKSPACE/bin/ffprobe" "$INSTALL_FOLDER/ffprobe" | |
sudo cp "$WORKSPACE/bin/ffplay" "$INSTALL_FOLDER/ffplay" | |
echo "Done. ffmpeg is now installed to your system" | |
;; | |
esac | |
fi | |
sudo rm /usr/local/bin/gcc /usr/local/bin/g++ | |
hash -r | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment