-
-
Save denji/fc963b79498328a2145944fc5029cddc to your computer and use it in GitHub Desktop.
Installation script of CUDA-accelerated `ffmpeg` with NVIDIA Encoder ( docker NVIDIA Encoder https://github.com/markus-perl/ffmpeg-build-script )
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 | |
# ========================================================================= | |
# Source: https://gist.github.com/lucaspar/27f5e108b80524b315be10b2a9049817 | |
# ========================================================================= | |
# This script will compile and install a static FFmpeg build with | |
# support for NVENC in Ubuntu. Developed in Ubuntu 23.10, | |
# with NVIDIA Drivers v535.129.03 and CUDA v12.2 with a GPU | |
# with CUDA capability 8.6 (RTX 3080) (see ccap below). | |
# 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 | |
# Variables 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 | |
# CUDA compute capability: check yours at https://developer.nvidia.com/cuda-gpus, or run: | |
# nvidia-smi --query-gpu=compute_cap --format=csv | |
ccap=86 | |
# NASM (Netwide Assembler) version to install (most recent version at the time of writing) | |
# https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu#NASM | |
NASM_VERSION=2.16.01 | |
# ffmpeg version to install (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 | |
FFMPEG_VERSION=6.1 | |
# Install required things from apt | |
install_libs() { | |
echo " π Installing prerequisites" | |
sudo apt-get update | |
sudo apt-get -y install autoconf automake build-essential \ | |
libass-dev libfreetype6-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 libx265-dev libnuma-dev libaom-dev libaom3 | |
} | |
# 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-${NASM_VERSION}" | |
if [ ! -d "${dir_nasm}" ]; then | |
cd "${DIR_FFMPEG_SOURCES}" || exit 1 | |
wget "https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.gz" | |
tar xzvf nasm-${NASM_VERSION}.tar.gz && rm -f nasm-${NASM_VERSION}.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 and install it | |
compile_and_install_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 | |
git fetch --tags | |
git switch "release/${FFMPEG_VERSION}" | |
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-libx265 \ | |
--enable-libaom \ | |
--enable-nonfree \ | |
--enable-nvdec \ | |
--enable-nvenc \ | |
--enable-pic \ | |
--enable-protocol=file \ | |
--enable-protocol=https \ | |
--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-545" | |
exit 1 | |
fi | |
} | |
# link installed binaries to user bin | |
link_installed() { | |
echo "Linking installed binaries to ${DIR_USR_BIN}" | |
cd "${DIR_USR_BIN}" || exit 1 | |
declare -a arr=("ffmpeg" "ffprobe" "ffplay" "ffserver" "ffprobe") | |
for f in "${arr[@]}"; do | |
f_path="${DIR_FFMPEG_BUILD}/bin/${f}" | |
if [ -f "${f_path}" ]; then | |
ldd "${f_path}" | |
fi | |
done | |
} | |
# main things | |
function main() { | |
check_nvidia_smi | |
# set number of cores to use | |
num_proc="$(nproc)" | |
NUM_CORES=$((num_proc <= 2 ? num_proc : num_proc - 1)) | |
echo "Using up to ${NUM_CORES} cores" | |
# create directories | |
DIR_PREV="$(pwd)" | |
cd "${DIR_INSTALL_ROOT}" || exit 1 | |
mkdir -p "${DIR_FFMPEG_SOURCES}" | |
install_libs | |
install_nvenc_sdk | |
compile_nasm | |
compile_libvpx | |
compile_and_install_ffmpeg | |
cd "${DIR_PREV}" || exit 1 | |
link_installed | |
wrap_up | |
benchmark | |
} | |
function wrap_up() { | |
echo " π Complete!" | |
echo -e " π‘ Some commands to try:\n" | |
echo "which ffmpeg ffprobe" | |
echo "whereis ffmpeg ffprobe # to run the correct binary in case your system has others" | |
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\t\t EXAMPLE OF NVENC USAGE" | |
echo -e "\n π Get a sample video to work with:\n" | |
echo -e "wget https://delamain.s3.amazonaws.com/public/samples/video-sample-720p.mp4 -O input.mp4" | |
echo -e "\n π GPU encoding test:\n" | |
echo -e "time ffmpeg -y -hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 4 -i input.mp4 -c:v h264_nvenc output-nvenc.mp4" | |
echo -e "\n π CPU encoding test:\n" | |
echo -e "time ffmpeg -y -i input.mp4 -c:v h264 output-cpu.mp4" | |
echo -e "\n π Wall 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\n π§Ή ${DIR_FFMPEG_SOURCES}\n π§Ή ${DIR_FFMPEG_BUILD}\n" | |
} | |
function benchmark() { | |
if ! [ -f input.mp4 ]; then | |
echo "Downloading sample video" | |
wget https://delamain.s3.amazonaws.com/public/samples/video-sample-720p.mp4 -O input.mp4 | |
fi | |
echo "Benchmarking x264 (MPEG-4/H.264) CPU vs. NVENC" | |
time ffmpeg -y -i input.mp4 -c:v h264 output-cpu-h264.mp4 | |
time ffmpeg -y -hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 4 -i input.mp4 -c:v h264_nvenc output-nvenc-h264.mp4 | |
echo "Benchmarking x265 (HEVC/H.265) CPU vs. NVENC" | |
time ffmpeg -y -i input.mp4 -c:v hevc output-cpu-hevc.mp4 | |
time ffmpeg -y -hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 4 -i input.mp4 -c:v hevc_nvenc output-nvenc-hevc.mp4 | |
} | |
main |
Update
# set number of cores to use
num_proc="$(nproc)"
NUM_CORES=$((num_proc <= 2 ? num_proc : num_proc - 1))
echo "Using up to $NUM_CORES cores"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this errors out
Using up to 158 cores
Installing prerequisites
Get:1 http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease [1,581 B]
Hit:2 http://us.archive.ubuntu.com/ubuntu jammy InRelease
Get:3 http://us.archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
Get:4 http://us.archive.ubuntu.com/ubuntu jammy-backports InRelease [109 kB]
Err:1 http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease
The following signatures couldn't be verified because the public key is not available: NO_PUBKEY A4B469963BF863CC
Get:5 http://us.archive.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Hit:6 https://ppa.launchpadcontent.net/graphics-drivers/ppa/ubuntu jammy InRelease
Ign:7 https://ppa.launchpadcontent.net/nilarimogard/webupd8/ubuntu jammy InRelease
Err:8 https://ppa.launchpadcontent.net/nilarimogard/webupd8/ubuntu jammy Release
404 Not Found [IP: 185.125.190.52 443]
Reading package lists... Done
W: GPG error: http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY A4B469963BF863CC
E: The repository 'http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
E: The repository 'https://ppa.launchpadcontent.net/nilarimogard/webupd8/ubuntu jammy Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
also I had to add the following to auto create your staging folders
Create folders
mkdir -p $DIR_USR_BIN
mkdir -p $DIR_INSTALL_ROOT
mkdir -p $DIR_FFMPEG_BUILD
mkdir -p $DIR_FFMPEG_SOURCES