FFmpeg is an extremely versatile video manipulation utility and used by many related software packages. It support many video and audio formats and can use hardware acceleration, with for example NVIDIA GPUs. Unfortunately, due to legal & license reasons and also version dependencies, the binary distributed versions of FFmpeg don't usually have NVIDIA hardware acceleration enabled. This tutorial will help you build proper FFmpeg packages that includes NVIDIA hardware acceleration for encoding and decoding of various video formats. The formats supported varies with the GPU used, consult this video encode & decode support matrix for details.
These instruction are meant for Ubuntu (and maybe Debian) based distributions and has been tested on Linux Mint 18. It is fully possible to use plain sources from the FFmpeg site on these and other distributions. By using PPAs and building proper packages they integrate better with your distribution.
We will need to add a couple of PPAs and install quite a lot of dependencies, so make sure you have enough disk space available. FFmpeg sources and build result will take about 3GB.
Why use hardware acceleration ?
Using the GPU for encoding or decoding is much faster the CPU-only based codecs and you can free up CPU resources for the uses. For example if you are streaming and your CPU is not fast enough you will get frame drops.
Lets get started !
Add required repositories
Add FFMPEG PPA
Fortunately there exists a PPA with everything we need for FFmpeg 4.
sudo add-apt-repository ppa:jonathonf/ffmpeg-4 sudo apt-get update
Note: If all you need is updated FFmpeg, without the NVIDIA hardware acceleration extras, then you can just install the ffmpeg package and you are done.
sudo apt-get install ffmpeg
Otherwise continue with the tutorial!
Add NVIDIA Driver PPA
You need to be running updated NVIDIA GPU driver, so first upgrade your NVIDIA drivers. Luckily there is a PPA for that too.
Add the Proprietary GPU Drivers PPA and upgrade your driver:
sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt-get update sudo apt-get install nvidia-418
Note: If nvidia-418 is not available for your distribution, for example if you are on Ubuntu Xenical / Linux Mint 18.3, then install nvidia-415.
Install various dependencies
Install build dependencies
sudo apt-get build-dep ffmpeg sudo apt install nvidia-cuda-toolkit
Install external dependencies
FFmpeg NVIDIA headers ("ffnvcodec")
FFmpeg sources used to come with the required headers, but they where recently split out into their own repository. You need to install them.
mkdir -p ffmpeg-deb/src cd ffmpeg-deb git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git cd nv-codec-headers make sudo make install
Note: If you are running NVIDIA Drivers 415 or older, you need to go back a bit in the API used. Checkout the 8.x API headers with:
git checkout 106d84a2c1960d1ccac7fa2646f0adc52d2d4ff2
Get the FFmpeg sources
Create a build location for FFmpeg and download the Debianized sources.
mkdir -p ffmpeg-deb/src cd -p ffmpeg-deb sudo apt-get source ffmpeg
This will fetch the FFmpeg sources from the ffmpeg ppa repository. At the time of writing, the version used was 4.1.1, but check first if the version has been bumped. In the following examples, substitue [version] with the version of the sources used.
Adjust the FFmpeg build rules
Edit ffmpeg-[version]/debian/rules
Add the line:
CONFIG+= --enable-nvenc --enable-cuda
somewhere after the big list of --enable-* lines. It should be quite obvious.
Optional: Add changelog entry
Edit ffmpeg-[version]/debian/changelog
and add an entry for your build version and changes.
Build the FFmpeg binary package
cd ffmpeg-[version] DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -r -b -j4
If all goes well, you should now have a bunch of packages, install the with:
dpkg -i *.deb
Check that FFmpeg has NVIDIA hardware acceleration enabled
ffmpeg -codecs|grep nvenc DEV.LS h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_crystalhd h264_v4l2m2m h264_cuvid ) (encoders: libx264 libx264rgb h264_nvenc h264_omx h264_v4l2m2m h264_vaapi nvenc nvenc_h264 ) DEV.L. hevc H.265 / HEVC (High Efficiency Video Coding) (decoders: hevc hevc_cuvid ) (encoders: libx265 nvenc_hevc hevc_nvenc hevc_vaapi )
How to use NVIDIA hardware acceleration with FFmpeg ?
FFmpeg won't use hardware acceleration automatically. You need to specify it as the encoder when encoding video material.
Example | FFmpeg command line |
---|---|
Accelerated encoding of random video file to h264, using codec default settings. |
ffmpeg -i input-file.mov \ -c:v h264_nvenc output-file.mp4 |
Accelerated decoding of h264 encoded video file to DNxHD (50 Fps, 75Mbit, FullHD), raw PCM audio |
ffmpeg -c:v h264_cuvid -i GOPR0926.MP4 \ -c:v dnxhd -vf "fps=50/1,format=yuv422p" -b:v 75M -c:a pcm_s16le output.mov |
High Quality h264 encoding, 4500K bitrate, High Quality encoding preset, Hiqh Quality VBR, 32 frame lookahead. |
ffmpeg -i input-file.mov \ -c:v h264_nvenc -profile:v high -pixel_format nv12 \ -b:v 4500k -preset slow -rc vbr_hq -rc-lookahead 32 output-file.mp4 |
Encode with yuv444p color format (Note: Not all GPUs support this) |
ffmpeg -i input-file.mov \ -c:v h264_nvenc -profile high444p \ -pixel_format yuv444p -preset default output-file.mp4 |
YouTube recommended 1080p 8000k video bitrate, fast start AAC384k audio bitrate |
ffmpeg -i input-file.mov \ -c:v h264_nvenc -profile:v high -pixel_format nv12 \ -b:v 8000k -preset slow -bf:v 2 -rc vbr_hq -rc-lookahead 32 \ -c:a aac -b:a 384k \ -movflags +faststart \ output-file.mp4 |
Encoding options for NVIDIA NVENC H.264 encoder
-preset <int> E..V..... Set the encoding preset (from 0 to 11) (default medium) default E..V..... slow E..V..... hq 2 passes medium E..V..... hq 1 pass fast E..V..... hp 1 pass hp E..V..... hq E..V..... bd E..V..... ll E..V..... low latency llhq E..V..... low latency hq llhp E..V..... low latency hp lossless E..V..... losslesshp E..V..... -profile <int> E..V..... Set the encoding profile (from 0 to 3) (default main) baseline E..V..... main E..V..... high E..V..... high444p E..V..... -level <int> E..V..... Set the encoding level restriction (from 0 to 51) (default auto) auto E..V..... 1 E..V..... 1.0 E..V..... 1b E..V..... 1.0b E..V..... 1.1 E..V..... 1.2 E..V..... 1.3 E..V..... 2 E..V..... 2.0 E..V..... 2.1 E..V..... 2.2 E..V..... 3 E..V..... 3.0 E..V..... 3.1 E..V..... 3.2 E..V..... 4 E..V..... 4.0 E..V..... 4.1 E..V..... 4.2 E..V..... 5 E..V..... 5.0 E..V..... 5.1 E..V..... -rc <int> E..V..... Override the preset rate-control (from -1 to INT_MAX) (default -1) constqp E..V..... Constant QP mode vbr E..V..... Variable bitrate mode cbr E..V..... Constant bitrate mode vbr_minqp E..V..... Variable bitrate mode with MinQP (deprecated) ll_2pass_quality E..V..... Multi-pass optimized for image quality (deprecated) ll_2pass_size E..V..... Multi-pass optimized for constant frame size (deprecated) vbr_2pass E..V..... Multi-pass variable bitrate mode (deprecated) cbr_ld_hq E..V..... Constant bitrate low delay high quality mode cbr_hq E..V..... Constant bitrate high quality mode vbr_hq E..V..... Variable bitrate high quality mode -rc-lookahead <int> E..V..... Number of frames to look ahead for rate-control (from 0 to INT_MAX) (default 0) -surfaces <int> E..V..... Number of concurrent surfaces (from 0 to 64) (default 0) -cbr <boolean> E..V..... Use cbr encoding mode (default false) -2pass <boolean> E..V..... Use 2pass encoding mode (default auto) -gpu <int> E..V..... Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on. (from -2 to INT_MAX) (default any) any E..V..... Pick the first device available list E..V..... List the available devices -delay <int> E..V..... Delay frame output by the given amount of frames (from 0 to INT_MAX) (default INT_MAX) -no-scenecut <boolean> E..V..... When lookahead is enabled, set this to 1 to disable adaptive I-frame insertion at scene cuts (default false) -forced-idr <boolean> E..V..... If forcing keyframes, force them as IDR frames. (default false) -b_adapt <boolean> E..V..... When lookahead is enabled, set this to 0 to disable adaptive B-frame decision (default true) -spatial-aq <boolean> E..V..... set to 1 to enable Spatial AQ (default false) -temporal-aq <boolean> E..V..... set to 1 to enable Temporal AQ (default false) -zerolatency <boolean> E..V..... Set 1 to indicate zero latency operation (no reordering delay) (default false) -nonref_p <boolean> E..V..... Set this to 1 to enable automatic insertion of non-reference P-frames (default false) -strict_gop <boolean> E..V..... Set 1 to minimize GOP-to-GOP rate fluctuations (default false) -aq-strength <int> E..V..... When Spatial AQ is enabled, this field is used to specify AQ strength. AQ strength scale is from 1 (low) - 15 (aggressive) (from 1 to 15) (default 8) -cq <float> E..V..... Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control (from 0 to 51) (default 0) -aud <boolean> E..V..... Use access unit delimiters (default false) -bluray-compat <boolean> E..V..... Bluray compatibility workarounds (default false) -init_qpP <int> E..V..... Initial QP value for P frame (from -1 to 51) (default -1) -init_qpB <int> E..V..... Initial QP value for B frame (from -1 to 51) (default -1) -init_qpI <int> E..V..... Initial QP value for I frame (from -1 to 51) (default -1) -qp <int> E..V..... Constant quantization parameter rate control method (from -1 to 51) (default -1) -weighted_pred <int> E..V..... Set 1 to enable weighted prediction (from 0 to 1) (default 0) -coder <int> E..V..... Coder type (from -1 to 2) (default default) default E..V..... auto E..V..... cabac E..V..... cavlc E..V..... ac E..V..... vlc E..V..... -b_ref_mode <int> E..V..... Use B frames as references (from 0 to 2) (default disabled) disabled E..V..... B frames will not be used for reference each E..V..... Each B frame will be used for reference middle E..V..... Only (number of B frames)/2 will be used for reference -a53cc <boolean> E..V..... Use A53 Closed Captions (if available) (default true)
Possible problems with FFmpeg
Issue | Possible Solution(s) |
---|---|
Trying to use hardware accelerated codec when running ffmpeg results in the following output: [h264_nvenc @ 0x561547b86280] Driver does not support the required nvenc API version. Required: 9.0 Found: 8.1 |
GPU Driver version problem:
|
[h264_nvenc @ 0x55aea2012280] EncodePicture failed!: unsupported param (12) | You are trying to encode with options that your GPU does not support. |