Skip to content

Instantly share code, notes, and snippets.

@krzemienski
Forked from lucaspar/nvenc-install.sh
Created June 4, 2023 04:08
Show Gist options
  • Save krzemienski/946bb43118d2921d09e320f161065500 to your computer and use it in GitHub Desktop.
Save krzemienski/946bb43118d2921d09e320f161065500 to your computer and use it in GitHub Desktop.
Installation script of CUDA-accelerated `ffmpeg` with NVIDIA Encoder
#!/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