-
-
Save krzemienski/946bb43118d2921d09e320f161065500 to your computer and use it in GitHub Desktop.
Installation script of CUDA-accelerated `ffmpeg` with NVIDIA Encoder
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 | |
# ================================================================== | |
# This script will compile and install a static ffmpeg build with | |
# support for NVENC in Ubuntu. Developed in Ubuntu 22.04 LTS, | |
# with NVIDIA Drivers v510.73 and CUDA v11.6 | |
# It assumes NVIDA drivers are installed and that you have a | |
# CUDA-compatible GPU. You can check installed drivers with: | |
# $ apt list *nvidia-driver-* | grep installed | |
# $ nvidia-smi | |
# ================================================================== | |
set -e | |
# Directories you might want to change | |
DIR_USR_BIN="$HOME/.local/bin" # user-writable binaries, where to install ffmpeg | |
DIR_INSTALL_ROOT="${XDG_STATE_HOME:-$HOME/.local/state}" # location to clone repos and build artifacts | |
DIR_FFMPEG_BUILD="$DIR_INSTALL_ROOT/ffmpeg-build" # where to build ffmpeg | |
DIR_FFMPEG_SOURCES="$DIR_INSTALL_ROOT/ffmpeg-sources" # ffmpeg source code | |
# Install required things from apt | |
install_libs() { | |
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 libopus-dev libunistring-dev \ | |
libavdevice-dev libfdk-aac-dev libmp3lame-dev libx264-dev libavcodec-dev \ | |
libgnutls28-dev | |
} | |
# Install NVENC SDK | |
install_nvenc_sdk() { | |
echo "Installing the NVIDIA NVENC SDK." | |
cd "$DIR_FFMPEG_SOURCES" || exit 1 | |
dir_nvcodec="$DIR_FFMPEG_SOURCES/nv-codec-headers" | |
if [ ! -d "$dir_nvcodec" ]; then | |
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git "$dir_nvcodec" | |
fi | |
cd "$dir_nvcodec" || exit 1 | |
make | |
sudo make install | |
} | |
# Compile nasm | |
compile_nasm() { | |
echo "Compiling nasm" | |
dir_nasm="$DIR_FFMPEG_SOURCES/nasm-2.15" | |
if [ ! -d "$dir_nasm" ]; then | |
cd "$DIR_FFMPEG_SOURCES" || exit 1 | |
wget "https://www.nasm.us/pub/nasm/releasebuilds/2.15/nasm-2.15.tar.gz" | |
tar xzvf nasm-2.15.tar.gz | |
fi | |
cd "$dir_nasm" || exit 1 | |
./configure --prefix="$DIR_FFMPEG_BUILD" --bindir="$DIR_USR_BIN" | |
make -j"${NUM_CORES}" || true # too many false positives, ignoring errors | |
make -j"${NUM_CORES}" install || true # too many false positives, ignoring errors | |
make -j"${NUM_CORES}" distclean | |
} | |
# Compile libvpx | |
compile_libvpx() { | |
echo "Compiling libvpx" | |
dir_vpx="$DIR_FFMPEG_SOURCES/libvpx" | |
if [ ! -d "$dir_vpx" ]; then | |
cd "$DIR_FFMPEG_SOURCES" || exit 1 | |
git clone https://chromium.googlesource.com/webm/libvpx "$dir_vpx" | |
fi | |
cd "$dir_vpx" || exit 1 | |
PATH="$DIR_USR_BIN:$PATH" ./configure --prefix="$DIR_FFMPEG_BUILD" --disable-examples \ | |
--enable-runtime-cpu-detect --enable-vp9 --enable-vp8 \ | |
--enable-postproc --enable-vp9-postproc --enable-multi-res-encoding \ | |
--enable-webm-io --enable-better-hw-compatibility --enable-vp9-highbitdepth \ | |
--enable-onthefly-bitpacking --enable-realtime-only --enable-pic \ | |
--cpu=native --as=nasm | |
PATH="$DIR_USR_BIN:$PATH" make -j"${NUM_CORES}" | |
make -j"${NUM_CORES}" install | |
make -j"${NUM_CORES}" clean | |
} | |
# Compile ffmpeg | |
compile_ffmpeg() { | |
echo "Compiling ffmpeg" | |
dir_ffmpeg="$DIR_FFMPEG_SOURCES/ffmpeg-repo" | |
if [ ! -d "$dir_ffmpeg" ]; then | |
cd "$DIR_FFMPEG_SOURCES" || exit 1 | |
git clone https://github.com/FFmpeg/FFmpeg.git -b master "$dir_ffmpeg" | |
fi | |
cd "$dir_ffmpeg" || exit 1 | |
# switch to version 5.1 (most recent version at the time of writing) | |
# check versions at https://github.com/FFmpeg/FFmpeg/branches/active | |
# check changelog at https://github.com/FFmpeg/FFmpeg/blob/master/Changelog | |
git fetch --tags | |
git switch release/5.1 | |
ccap=37 | |
PATH="$DIR_USR_BIN:$PATH" PKG_CONFIG_PATH="$DIR_FFMPEG_BUILD/lib/pkgconfig" ./configure \ | |
--pkg-config-flags="--static" \ | |
--prefix="$DIR_FFMPEG_BUILD" \ | |
--extra-cflags="-I$DIR_FFMPEG_BUILD/include" \ | |
--extra-ldflags="-L$DIR_FFMPEG_BUILD/lib" \ | |
--extra-cflags="-I/usr/local/cuda/include/" \ | |
--extra-ldflags=-L/usr/local/cuda/lib64/ \ | |
--nvccflags="-gencode arch=compute_${ccap},code=sm_${ccap} -O2" \ | |
--bindir="$DIR_USR_BIN" \ | |
--enable-static \ | |
--enable-cuda-nvcc \ | |
--enable-cuvid \ | |
--enable-decoder=aac \ | |
--enable-decoder=h264 \ | |
--enable-decoder=h264_cuvid \ | |
--enable-demuxer=mov \ | |
--enable-filter=scale \ | |
--enable-gnutls \ | |
--enable-gpl \ | |
--enable-libass \ | |
--enable-libfdk-aac \ | |
--enable-libfreetype \ | |
--enable-libmp3lame \ | |
--enable-libnpp \ | |
--enable-libopus \ | |
--enable-libtheora \ | |
--enable-libvorbis \ | |
--enable-libvpx \ | |
--enable-libx264 \ | |
--enable-nonfree \ | |
--enable-nvdec \ | |
--enable-nvenc \ | |
--enable-pic \ | |
--enable-protocol=file \ | |
--enable-protocol=https \ | |
--enable-shared \ | |
--enable-vaapi | |
PATH="$DIR_USR_BIN:$PATH" make -j"${NUM_CORES}" | |
make -j"${NUM_CORES}" install | |
make -j"${NUM_CORES}" distclean | |
hash -r | |
} | |
# check if nvidia-smi succeeds | |
check_nvidia_smi() { | |
if ! nvidia-smi &>/dev/null; then | |
echo -e "\tnvidia-smi not found or failed to run." | |
echo -e "\tMake sure NVIDIA drivers are installed e.g.:" | |
echo -e "\t\tsudo apt install nvidia-driver-515" | |
exit 1 | |
fi | |
} | |
check_nvidia_smi | |
# set number of cores to use | |
num_proc="$(nproc)" | |
NUM_CORES=$((num_proc - 2)) | |
echo "Using up to $NUM_CORES cores" | |
# create directories | |
cd "$DIR_INSTALL_ROOT" || exit 1 | |
mkdir -p "$DIR_FFMPEG_SOURCES" | |
# main things | |
install_libs | |
install_nvenc_sdk | |
compile_nasm | |
compile_libvpx | |
compile_ffmpeg | |
echo " >> Complete!" | |
echo -e " >> Some commands to try:\n" | |
echo "ffmpeg 2>/dev/null -version | grep -i 'nv[a-z]*|nvidia|cuda|nvenc'" | |
echo "ffprobe 2>/dev/null -decoders | grep -i 'nvidia|cuda|nvenc'" | |
echo "ffprobe 2>/dev/null -encoders | grep -i 'nvidia|cuda|nvenc'" | |
echo "ffprobe 2>/dev/null -filters | grep -i 'nvidia|cuda|nvenc'" | |
echo -e "\n\n" | |
echo -e " >> Example of nvenc usage:\n" | |
echo -e "wget https://filesamples.com/samples/video/mp4/sample_1280x720_surfing_with_audio.mp4 -O input.mp4" | |
echo -e "time ffmpeg -hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 4 -i input.mp4 -c:v h264_nvenc output.mp4" | |
echo -e "time ffmpeg -y -i input.mp4 -c:v h264 output.mp4" | |
echo -e "\n\tWall times for tested run:\t15.695s (CPU, 24 cores) vs. (CUDA, RTX 3080) 4.952s" | |
echo -e "\nIf everything works, you can mark the following directories for deletion:\n$DIR_FFMPEG_SOURCES\n$DIR_FFMPEG_BUILD\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment