NVIDIA HARDWARE-ACCELERATED TRANSCODING USING FFMPEG
This guide is only relevant for proprietary nvidia driver installed. Guide was tested on Ubuntu 24.04 LTS, 24.04.1 LTS with proprietary nvidia driver installed and the following system configuration:
- MSI® motherboard Z170A
- Intel® Core™ i5-6600 Processor
- GeForce GTX 1650 AERO ITX 4G OC.
Please read the text carefully before you start system changes.
Disclaimer: This guide was written for research purposes. The author have no responsibility for any consequences, including potential device brick, violating manufacturer licenses, lose device warranty etc.
PREPARATION
STEP 1. Make sure that system is using NVIDIA proprietary driver
$ lspci -nnk | grep -EA3 "3D|VGA"
Note: When using the proprietary NVIDIA driver, you should see the text "Kernel driver in use: nvidia"
Note: To install NVIDIA Proprietary Drivers use “$ software-properties-gtk --open-tab=4” then reboot your system.
STEP 2. Set the NVIDIA Graphics Device as the primary then reboot your system
$ sudo prime-select nvidia
Note: See GPU PASSTHROUGH TROUBLESHOOTING
STEP 3. Install ffmpeg, git, make packages
$ sudo apt-get install ffmpeg git make
STEP 4. Run ffmpeg to see ffmpeg configuration, keep the configuration text
$ ffmpeg
STEP 5. Clone ffnvcodec
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
STEP 6. Go to the directory "nv-codec-headers-nxx.x.xx.x"
cd '/home/username/nv-codec-headers'
STEP 7. Install ffnvcodec
$ sudo make install
STEP 8. Leave the "nv-codec-headers" directory ($ cd)
STEP 9. Install necessary packages
$ sudo apt-get install libavdevice60 libjack-jackd2-0 libopenal1 libsndio7.0 libdc1394-25 libopenal-data libsdl2-2.0-0 build-essential yasm cmake libtool libc6 libc6-dev unzip wget libnuma1 libnuma-dev nvidia-cuda-toolkit libffmpeg-nvenc-dev libfdk-aac-dev libssl-dev librtmp-dev libpulse-dev libdrm-dev libchromaprint-dev libfrei0r-ocaml-dev libladspa-ocaml-dev libc6-dev-amd64 libaom-dev liblilv-0-0 liblilv-dev libiec61883-dev libavc1394-dev libraw1394-dev libass-dev libbluray-dev libbs2b-dev libcaca-dev libcodec2-dev libdav1d-dev libdc1394-dev libdvdnav-dev flite1-dev glslang-dev libgme-dev libgsm1-dev libjxl-dev libvpl-dev libmp3lame-dev libmysofa-dev libopenjp2-7-dev libopenmpt-dev libopus-dev libplacebo-dev librabbitmq-dev librav1e-dev librist-dev librsvg2-dev librubberband-dev libshine-dev libsnappy-dev libsoxr-dev libssh-dev libspeex-dev libsrt-gnutls-dev libsvtav1enc-dev libtheora-dev libtwolame-dev libvidstab-dev libvpx-dev libx264-dev libx265-dev libxvidcore-dev libzimg-dev libzmq3-dev libzvbi-dev libopenal-dev libpocketsphinx-dev libjack-jackd2-dev libcdio-dev libcdparanoia-dev libcdio++-dev libcdio-cdda-dev libcdio-paranoia-dev libsdl2-dev
STEP 10. To avoid the "WARNING: library configuration mismatch" message, install the following packages
$ sudo apt install libavcodec-extra libavcodec-dev libavcodec-extra60 libavfilter-extra libavdevice-dev libavdevice60 libavfilter-dev libavfilter-extra9 libavformat-extra libavformat-dev libavformat-extra60 libavutil-dev libavutil58 libpostproc-dev libpostproc57 libswresample-dev libswresample4 libswscale-dev libswscale7 liblept5 libtesseract5 libpostproc-dev libswresample4 libswresample-dev libswscale-dev
Note: Perhaps for some tasks you will need to install the gds-tools, cuda-drivers-fabricmanager-xxx packages. See NVIDIA CUDA Installation Guide for Linux
STEP 11. Download the ffmpeg source package "ffmpeg_x.x.x.orig.tar.xz" from the Ubuntu website
Note: If you are using Ubuntu 24.04.1 LTS or 24.04 LTS with the latest updates, see the warning of step 17.
STEP 12. Extract the ffmpeg_x.x.x.orig.tar.xz or ffmpeg-6.1.2.tar.xz (see the warning of step 17) file
$ tar xf '/home/username/Downloads/ffmpeg_x.x.x.orig.tar.xz'
or (see the warning of step 17)
$ tar xf '/home/username/Downloads/ffmpeg-6.1.2.tar.xz'
STEP 13. Go to the extracted directory "ffmpeg-x.x.x"
$ cd '/home/username/ffmpeg-x.x.x'
STEP 14. Configure
Use necessary minimum
$ ./configure --enable-nonfree --enable-cuda-nvcc --enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64 --disable-static --enable-shared --enable-libfdk-aac --enable-openssl --enable-librtmp --enable-libpulse --enable-libdrm
or combination with the configuration of already installed ffmpeg
$ ./configure --extra-version=3ubuntu5+esm1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --enable-gnutls --enable-libaom --enable-libass --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libharfbuzz --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-openal --enable-opencl --enable-opengl --enable-libvpl --enable-libdc1394 --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-ladspa --enable-libbluray --enable-libjack --enable-librabbitmq --enable-librist --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libx264 --enable-libzmq --enable-libzvbi --enable-lv2 --enable-sdl2 --enable-libplacebo --enable-librav1e --enable-pocketsphinx --enable-librsvg --enable-libjxl --enable-nonfree --enable-cuda-nvcc --enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64 --disable-static --enable-shared --enable-libfdk-aac --enable-librtmp --enable-libpulse --enable-libdrm
Note: If you get the error "ERROR: xxxxx not found using pkg-config" when configuring FFmpeg with "--enable-xxxxx", install the missing package using "$ sudo apt-get install xxxxx-dev". See Ubuntu Packages Search web page or use the command line tool for searching files in packages for the APT package management system ($ sudo apt install apt-file, $ sudo apt-file update, $ apt-file search packagename).
Note: The “--disable-stripping --disable-omx --disable-sndio --disable-libmfx” options was removed.
Note: The “--enable-libglslang” option was removed due to an “ERROR: spirv_compiler not found” message.
STEP 15. Compile
$ sudo make -j 8
STEP 16. Remove installed ffmpeg
$ sudo apt remove ffmpeg
STEP 17. Install ffmpeg
$ sudo make install
Warning! When trying to install ffmpeg “$ sudo make install” after upgrading Ubuntu 24.04 LTS, and on Ubuntu 24.04.1 LTS, the following error appears.
CC libavcodec/nvenc_hevc.o
libavcodec/nvenc.c: In function ‘nvenc_setup_hevc_config’:
libavcodec/nvenc.c:1373:9: error: ‘NV_ENC_CONFIG_HEVC’ has no member named ‘pixelBitDepthMinus8’
1373 | hevc->pixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
| ^~
libavcodec/nvenc.c: In function ‘nvenc_setup_av1_config’:
libavcodec/nvenc.c:1458:8: error: ‘NV_ENC_CONFIG_AV1’ has no member named ‘inputPixelBitDepthMinus8’
1458 | av1->inputPixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
| ^~
libavcodec/nvenc.c:1459:8: error: ‘NV_ENC_CONFIG_AV1’ has no member named ‘pixelBitDepthMinus8’
1459 | av1->pixelBitDepthMinus8 = (IS_10BIT(ctx->data_pix_fmt) || ctx->highbitdepth) ? 2 : 0;
| ^~
libavcodec/nvenc.c: In function ‘nvenc_map_buffer_format’:
libavcodec/nvenc.c:1692:16: error: ‘NV_ENC_BUFFER_FORMAT_YV12_PL’ undeclared (first use in this function); did you mean ‘NV_ENC_BUFFER_FORMAT_YV12’?
1692 | return NV_ENC_BUFFER_FORMAT_YV12_PL;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
| NV_ENC_BUFFER_FORMAT_YV12
libavcodec/nvenc.c:1692:16: note: each undeclared identifier is reported only once for each function it appears in
libavcodec/nvenc.c:1694:16: error: ‘NV_ENC_BUFFER_FORMAT_NV12_PL’ undeclared (first use in this function); did you mean ‘NV_ENC_BUFFER_FORMAT_NV12’?
1694 | return NV_ENC_BUFFER_FORMAT_NV12_PL;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
| NV_ENC_BUFFER_FORMAT_NV12
libavcodec/nvenc.c:1700:16: error: ‘NV_ENC_BUFFER_FORMAT_YUV444_PL’ undeclared (first use in this function); did you mean ‘NV_ENC_BUFFER_FORMAT_YUV444’?
1700 | return NV_ENC_BUFFER_FORMAT_YUV444_PL;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| NV_ENC_BUFFER_FORMAT_YUV444
CC libavcodec/on2avc.o
make: *** [ffbuild/common.mak:81: libavcodec/nvenc.o] Error 1
make: *** Waiting for unfinished jobs....
Solution: Download the FFmpeg 6.1.2 "Heaviside" from the FFmpeg website and start again from step 12.
STEP 18. Leave the extracted "ffmpeg-x.x.x" directory ($ cd).
STEP 19. Run ffmpeg to see new ffmpeg configuration
$ ffmpeg
Important: If you installed FFmpeg 6.1.2 "Heaviside" the following message will appear "bash: /usr/bin/ffmpeg: No such file or directory".
Solution: Run
$ /usr/local/bin/ffmpeg
or create soft/symbolic link
$ sudo ln -s '/usr/local/bin/ffmpeg' '/usr/bin'
once the link is created, run the application as usual
$ ffmpeg
Important: You may encounter the message "Driver does not support the required nvenc API version. Required: 12.2 Found: 12.1".
Solution: See ./nv-codec-headers/README, update the driver then reboot your system
$ sudo apt-get install dkms libnvidia-cfg1-550 libnvidia-common-550 libnvidia-compute-550 libnvidia-compute-550:i386 libnvidia-decode-550 libnvidia-decode-550:i386 libnvidia-encode-550 libnvidia-encode-550:i386 libnvidia-extra-550 libnvidia-fbc1-550 libnvidia-fbc1-550:i386 libnvidia-gl-550 libnvidia-gl-550:i386 nvidia-compute-utils-550 nvidia-dkms-550 nvidia-driver-550 nvidia-firmware-550-550.67 nvidia-kernel-common-550 nvidia-kernel-source-550 nvidia-utils-550 xserver-xorg-video-nvidia-550
STEP 20. Run NVIDIA-SMI to ensure that the NVIDIA driver is working properly
$ nvidia-smi
Note: If the message “NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.” appears, NVIDIA hardware transcoding acceleration will not be available.
LEARN ABOUT THE POSSIBILITIES
To find out about the possibilities, use the following command:
$ for i in encoders decoders filters; do echo $i:; ffmpeg -hide_banner -${i} | egrep -i "npp|cuvid|nvenc|cuda"; done
To get codec help:
$ ffmpeg -h encoder=hevc_nvenc
$ ffmpeg -h encoder=h264_nvenc
EXAMPLES OF USE
HWACCEL Transcode without Scaling
$ ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4
$ ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:a copy -c:v hevc_nvenc -b:v 5M output.mp4
See more Using FFmpeg with NVIDIA GPU Hardware Acceleration
See also NVIDIA FFmpeg Transcoding Guide
Desktop recording (examples are only suitable for X11 session)
$ ffmpeg -y -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f x11grab -framerate 30 -i :1.0+0,0 -c:v h264_nvenc -b:v 5M output.mp4
$ ffmpeg -y -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f x11grab -framerate 30 -i :1.0+0,0 -c:v hevc_nvenc -b:v 5M output.mp4
$ ffmpeg -y -f pulse -i default -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f x11grab -framerate 30 -i :1.0+0,0 -c:v hevc_nvenc -b:v 5M -c:a libfdk_aac -b:a 128k output.mp4
Note: Commands with x11grab work on X11 session. On a Wayland session, you will get a recording of a black screen.
Note: To get the DISPLAY environment variable, use the command $ echo $DISPLAY. For example, for the variable DISPLAY ":1" the result should look as follows "-f x11grab -framerate 30 -i :1.0+0,0".
Note: You can set the audio source for recording using PulseAudio Volume Control. To install PulseAudio Volume Control, run the following command $ sudo apt-get install pavucontrol.
Note: Press [q] to stop the process.
Previewing and recording the desktop region (examples are only suitable for X11 session)
Example for preview
$ ffplay -x 1280 -y 720 -f x11grab -i -video_size 1920x1080 :1.0+250,250
Example for recording
$ ffmpeg -y -f pulse -i default -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f x11grab -show_region 0 -s 1920x1080 -framerate 30 -i :1.0+250,250 -c:v hevc_nvenc -b:v 5M -c:a libfdk_aac -b:a 128k output.mp4
Note: The -show_region 1 command is used to display a region.
Screencasting to a virtual webcam
Necessary packages
$ sudo apt install v4l2loopback-utils v4l2loopback-dkms v4l2loopback-source
Examples of creating a virtual webcam
$ sudo modprobe v4l2loopback card_label="vwcam" exclusive_caps=1
$ sudo modprobe v4l2loopback card_label="vwcam" exclusive_caps=1 max_buffers=2
Examples of creating virtual webcams
$ sudo modprobe v4l2loopback devices=2 card_label="vwcam,vwcam2" exclusive_caps=1
Note: The virtual webcam will become available for Google Meet after a video stream is submitted to it. If you have a problem with the virtual webcam reload the v4l2loopback using the command $ sudo rmmod v4l2loopback.
Useful commands:
$ v4l2-ctl --list-devices
$ v4l2-ctl -L
$ ffmpeg -f video4linux2 -list_formats all -i /dev/video0
$ echo $DISPLAY
Examples of screencasting to a virtual webcam (examples are only suitable for X11 session)
$ ffmpeg -f x11grab -r 15 -i :1.0+0,0 -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 /dev/video2
$ ffmpeg -f x11grab -r 15 -i :1.0+0,0 -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 -vf scale=480:360,setdar=4/3 /dev/video2
$ ffmpeg -f x11grab -r 15 -i :1.0+0,0 -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 -vf hflip,scale=480:360,setdar=4/3 /dev/video2
$ ffmpeg -f x11grab -r 15 -i :1.0+0,0 -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 -vf hflip,scale=1280:720,setdar=16/9 /dev/video2
$ ffmpeg -f x11grab -r 15 -s 1920x1440 -i :1.0+0,0 -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 -vf hflip,scale=480:360,setdar=4/3 /dev/video2
$ ffmpeg -f x11grab -r 15 -s 1920x1080 -i :1.0+0,0 -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 -vf hflip,scale=1280:720,setdar=16/9 /dev/video2
Note: If "-vf scale" is unavailable, you will see nothing in the output. To fix the problem, install the following packages libswscale7, libswscale-dev. If the problem persists, try installing obs-studio using snap ($ sudo snap install obs-studio).
Screencasting on Youtube (example is only suitable for X11 session)
$ ffmpeg -y -f pulse -i default -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f x11grab -framerate 30 -i :1.0+0,0 -c:v hevc_nvenc -b:v 1M -c:a libfdk_aac -b:a 128k -f flv -vf scale=1280:720,setdar=16/9 Stream URL/Stream key
Live broadcast from webcam on YouTube
Example without -input_format mjpeg
$ ffmpeg -y -f pulse -i default -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f v4l2 -framerate 30 -video_size 640x480 -i /dev/video0 -c:v hevc_nvenc -b:v 0.5M -c:a libfdk_aac -b:a 128k -f flv -vf scale=1280:720,setdar=16/9 Stream URL/Stream key
Example with -input_format mjpeg
$ ffmpeg -y -f pulse -i default -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f v4l2 -framerate 30 -video_size 1920x1080 -input_format mjpeg -i /dev/video0 -c:v hevc_nvenc -b:v 0.5M -c:a libfdk_aac -b:a 128k -f flv -vf setdar=16/9 Stream URL/Stream key
Live broadcast from OBS VirtualCam on YouTube
$ ffmpeg -y -f pulse -i default -vsync 1 -hwaccel cuda -hwaccel_output_format cuda -f v4l2 -framerate 30 -i /dev/video2 -c:v h264_nvenc -b:v 0.5M -c:a libfdk_aac -b:a 128k -f flv -vf scale=1280:720,setdar=16/9 Stream URL/Stream key
See more Live stream on YouTube
Converting a single image to video
Example 1
$ sudo apt install libjpeg-tools
$ jpeg infile.jpg out.ppm
$ jpeg -q 100 infile.ppm outfile.jpg
$ ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -framerate 30 -loop 1 -t 30 -i outfile.jpg -c:v hevc_nvenc -vf scale_cuda=1920:1080:force_original_aspect_ratio=decrease output.mp4
Note: The example is suitable for a file created by a device such as a DSLR camera and a PC.
Example 2
$ ffmpeg -vsync 0 -hwaccel cuvid -c:v mjpeg_cuvid -framerate 30 -loop 1 -t 30 -i 'DSC00001.jpg' -c:v hevc_nvenc -vf hwupload,scale_npp=1920:1080:force_original_aspect_ratio=decrease output.mp4
Note: The example is suitable for a file created by a device, such as a DSLR camera.
SEE ALSO
TROUBLESHOOTING
Problem: Message "Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)"
Action:
- Set CPU governor on Ubuntu operating system to "Performance"
REFERENCES