Skip to content

Instantly share code, notes, and snippets.

@Ghostbird
Last active April 25, 2024 02:46
Show Gist options
  • Save Ghostbird/0445ebe0d9f6d945c3978702ad455103 to your computer and use it in GitHub Desktop.
Save Ghostbird/0445ebe0d9f6d945c3978702ad455103 to your computer and use it in GitHub Desktop.
Build FFMPEG with NVIDIA hardware accelleration libraries on Debian 12. Includes non-free libnpp!
#!/bin/bash
# Automatically compile and install FFMPEG with NVIDIA hardware acceleration on Debian 12
# Includes cuvid, cuda, nvenc, nvdec, and non-free libnpp
# Based on:
# https://www.tal.org/tutorials/ffmpeg_nvidia_encode
# https://developer.nvidia.com/blog/nvidia-ffmpeg-transcoding-guide/
# Abort on error
set -e
suite=$(source /etc/os-release && echo $VERSION_CODENAME)*
# Install libavcodec-extra manually so the build-deps step doesn't pull the problematic libavcodec59
# libjs-bootstrap is a dependency of ffmpeg-doc
# devscripts contains the dch command
sudo apt-get install libavcodec-extra libjs-bootstrap devscripts
sudo apt-mark auto libavcodec-extra libjs-bootstrap devscripts
sudo apt-get build-dep ffmpeg -t $suite
sudo apt-get install nvidia-cuda-toolkit -t $suite
mkdir -p ffmpeg-deb/src
cd ffmpeg-deb
if [[ -d nv-codec-headers ]]
then
cd nv-codec-headers
git fetch --tags
else
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers
fi
# Checkout latest release, intead of HEAD. The Debian driver in stable may not yet support the pre-release API.
git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
make
sudo make install
cd ../src
rm -rf ./*
apt-get source ffmpeg -t $suite
cd ffmpeg-*
sed -i 's/--enable-sdl2/--enable-sdl2 --enable-cuda --enable-cuvid --enable-nvdec --enable-nvenc --enable-libnpp --enable-nonfree/' debian/rules
DEBEMAIL="root@local" DEBFULLNAME="script" dch --local "+nvidiasupport" "Compiled with support for nvidia hardware acceleration"
DEB_BUILD_OPTIONS="nocheck notest" dpkg-buildpackage -r -nc --jobs=auto --no-sign
cd ..
# Install all built packages, except the non-extra variants of libavfilter, libavcodec and libavformat
sudo dpkg -i $(ls *.deb | grep -Ev "(libavfilter|libavcodec|libavformat)[0-9]+_")
echo "Verification:"
ffmpeg -codecs 2> /dev/null | grep nvenc
@Ghostbird
Copy link
Author

Ghostbird commented Sep 6, 2023

I've update it with a mechanism that works for me, give it a try once you have the time.

I've used suite=$(source /etc/os-release && echo $VERSION_CODENAME)* which yields bookworm* on my system. This seems to work.

However suite=$(source /etc/os-release && echo $VERSION_ID)* which yields 12* works just as well.

I opted for the code name because it's clearer what it means. When you see (e.g. in a log) an apt command that includes a version number you won't instantly know whether it's a software version number or an OS version number. When you see a Debian code-name, it's obviously an OS version and not a software version.

@gitmybox
Copy link

The topic description mentioned Build FFMPEG with NVIDIA hardware accelleration libraries on Debian 11

Does the script support Debian 12 ?

Thanks.

@Ghostbird
Copy link
Author

Ghostbird commented Sep 14, 2023 via email

@gitmybox
Copy link

I managed to compile FFmpeg from the script without error in Debian 12 with ASUS RTX-4060 Ti 8GB Nvidia GPU Card.

Reference to Nvidia link Using FFmpeg with NVIDIA GPU Hardware Acceleration:- https://docs.nvidia.com/video-technologies/video-codec-sdk/11.1/ffmpeg-with-nvidia-gpu/index.html

I tried the Basic Testing first transcode command:-
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

But I encountered the following errors:-

  1. -vsync is deprecated. Use -fps_mode
    Passing a number to -vsync is deprecated, use a string argument as described in the manual.

  2. No decoder surfaces left
    Error while decoding stream #0:0: Invalid data found when processing input

If I remove both flags -vsync & -hwaccel_output_format cuda , the errors disappear. I think these flags are there for a good reason.

Does anyone have experience on this issue to share some hints on how to solve it ?

Thanks in advance.

@Ghostbird
Copy link
Author

Ghostbird commented Sep 23, 2023 via email

@gitmybox
Copy link

gitmybox commented Sep 23, 2023

Thanks for the feedback.

I have another clarification that encoder av1_nvenc is not included:-
ffmpeg -hide_banner -encoders | grep nvenc
V....D h264_nvenc NVIDIA NVENC H.264 encoder (codec h264)
V....D hevc_nvenc NVIDIA NVENC hevc encoder (codec hevc)

Is it possible to compile this av1_nvenc into ffmpeg ?

According to Nvidia SDK v12 it is part of it:-
The NVENC plugin in FFMPEG supports the following codecs: h264_nvenc - H264 Encoder hevc_nvenc - HEVC Encoder av1_nvenc - AV1 Encoder The command lines in this document use h264_nvenc, and should be replaced by hevc_nvenc for HEVC encode and av1_nvenc for AV1 encode.

Thanks

@Ghostbird
Copy link
Author

I'd expect it to be included automatically, however I don't know for sure, and I can't test it. On my system it is not present after the compilation, simply because my hardware doesn't support it. You should check your hardware support here

@gitmybox
Copy link

I have verified that RTX-4060 Ti 8GB Nvidia GPU Card is listed to support AV1 in here.

If it is automatically complied to include encoder av1_nvenc, can I verify it in the log & what key word to look out for ?

Thanks

@Ghostbird
Copy link
Author

I see that the NVIDIA page on compiling FFMPEG lists a configuration flag --enable-cuda-nvcc. I have no idea whether it'll work, but you can try adding that to the sed line in the script. In the line that starts with sed -i, add --enable-cuda-nvcc after --enable-cuda and see whether that works. I'm not sure whether that's valid, but it's worth a quick try. If it isn't valid you'll probably get an error an you'll have to remove it again.

@Ghostbird
Copy link
Author

If it is automatically complied to include encoder av1_nvenc, can I verify it in the log & what key word to look out for ?

The script greps for nvenc at the end. If the encoder av1_nvenc is present, it would show up in the verification output at the end of the script. The fact that you haven't seen it already probably means it really isn't present.

@booski
Copy link

booski commented Oct 3, 2023

I've update it with a mechanism that works for me, give it a try once you have the time.

I've used suite=$(source /etc/os-release && echo $VERSION_CODENAME)* which yields bookworm* on my system. This seems to work.

However suite=$(source /etc/os-release && echo $VERSION_ID)* which yields 12* works just as well.

I opted for the code name because it's clearer what it means. When you see (e.g. in a log) an apt command that includes a version number you won't instantly know whether it's a software version number or an OS version number. When you see a Debian code-name, it's obviously an OS version and not a software version.

Testing this out, it doesn't seem to work at all on bullseye:

root@bullseye:~# apt-get build-dep ffmpeg -t bullseye
[...]
The following packages have unmet dependencies:
[...]
E: Unable to correct problems, you have held broken packages.

The other options do even worse (same result for 11 and 11*):

root@bullseye:~# apt-get build-dep ffmpeg -t bullseye*
Reading package lists... Done
E: Unable to find a source package for ffmpeg

On bookworm it works as long as the wildcard is specified:

root@bookworm:~# apt-get build-dep ffmpeg -t bookworm
[...]
The following packages have unmet dependencies:
[...]
E: Unable to correct problems, you have held broken packages.
root@bookworm:~# apt-get build-dep ffmpeg -t bookworm*
[...]
After this operation, 1,040 MB of additional disk space will be used.
Do you want to continue? [Y/n]
root@bookworm:~# apt-get build-dep ffmpeg -t 12
Reading package lists... Done
E: Unable to find a source package for ffmpeg
root@bookworm:~# apt-get build-dep ffmpeg -t 12*
[...]
After this operation, 1,040 MB of additional disk space will be used.
Do you want to continue? [Y/n]

So in short, I think the solution of using $VERSION_CODENAME* is the best for the clarity reasons you bring up.

While poking at this, I fixed some other issues I ran into, feel free to incorporate them if they seem useful to you:

  • I kept running into issues with the build-deps for ffmpeg automatically installing the problematic libavcodec59 package, so I added a line manually installing libavcodec-extra, which dpkg can replace without issue.
  • ffmpeg-doc gets built even though "nodoc" is specified. I don't mind getting the docs package, so I just made sure the dependencies for the package are in place (libjs-bootstrap) and removed the "nodoc" that doesn't seem to do anything.
  • I changed the parallelism level for dpkg-buildpackage to "auto" (from 4), it felt like a better choice considering the compilation time.
  • Once the packages were installed, apt immediately wanted to overwrite them with "newer" versions from the repo, so I added a version suffix (+nvidiasupport) to stop that happening.
  • Since the $suite logic doesn't work on bullseye, updated the top comment to refer to Debian 12.

Here's the diff covering all the above changes:

2c2
< # Automatically compile and install FFMPEG with NVIDIA hardware acceleration on Debian 11
---
> # Automatically compile and install FFMPEG with NVIDIA hardware acceleration on Debian 12
12a13,18
> # Install libavcodec-extra manually so the build-deps step doesn't pull the problematic libavcodec59
> # libjs-bootstrap is a dependency of ffmpeg-doc
> # devscripts contains the dch command
> sudo apt-get install libavcodec-extra libjs-bootstrap devscripts
> sudo apt-mark auto libavcodec-extra libjs-bootstrap devscripts
> 
31a38
> 
34c41,42
< DEB_BUILD_OPTIONS="nocheck nodoc notest" dpkg-buildpackage -r -nc -j4 --no-sign
---
> DEBEMAIL="root@local" DEBFULLNAME="script" dch --local "+nvidiasupport" "Compiled with support for nvidia hardware acceleration"
> DEB_BUILD_OPTIONS="nocheck notest" dpkg-buildpackage -r -nc --jobs=auto --no-sign
35a44
> 

I will probably set something up to automatically build the package again when there is a newer version in apt, I can share the result if that seems interesting to you.

/T

@Ghostbird
Copy link
Author

Ghostbird commented Oct 5, 2023

Odd that it didn't work on Bullseye. I've added your changes and it worked perfectly on my system. How the libavcodec59 problem happened, I don't know. The inverse grep in the subcommand that generates the package list for dpkg should have excluded it based on the regular expression.

I had no idea that I had left -j4 in there. --jobs=auto is of course much more desirable. I didn't know that option existed. I normally used -j$(nproc).

I have edited your message above. The word acceleration was somehow word-wrapped using a newline character, which broke the patch file.

UPDATE: Actually I didn't realise, but the new script broke some stuff on my system, but it was fixed after removing a lot of :i386 packages that I didn't need anyway.

@gitmybox
Copy link

I see that the NVIDIA page on compiling FFMPEG lists a configuration flag --enable-cuda-nvcc. I have no idea whether it'll work, but you can try adding that to the sed line in the script. In the line that starts with sed -i, add --enable-cuda-nvcc after --enable-cuda and see whether that works. I'm not sure whether that's valid, but it's worth a quick try. If it isn't valid you'll probably get an error an you'll have to remove it again.

I have tried by adding --enable-cuda-nvcc after --enable-cuda, the script stopped with error log shown below:-
. . . . . . .
nvcc -gencode arch=compute_60,code=sm_60 -O2 -std=c++11 -m64 -ptx -c -o /tmp/ffconf.jCphOBPP/test.o /tmp/ffconf.jCphOBPP/test.cu
ERROR: No supported gcc/g++ host compiler found, but clang-14 is available.
Use 'nvcc -ccbin clang-14' to use that instead.
ERROR: failed checking for nvcc.
make[1]: Leaving directory '/home/user233l/ffmpeg-deb/src/ffmpeg-5.1.3'
make[1]: *** [debian/rules:257: configure_standard] Error 1
make: *** [debian/rules:250: binary] Error 2
dpkg-buildpackage: error: debian/rules binary subprocess returned exit status 2

@Ghostbird
Copy link
Author

Interesting, I can't help you much with that, but you can look at NVIDIA/cuda-samples#46 as a starting point.

@falcie1337
Copy link

does this work on debian sid? i really need obs right now

@Ghostbird
Copy link
Author

Give it a try. You can run the first 43 lines of the script, and see whether it compiles, without changing your system too much.

@weskerty
Copy link

Thank you. It helped me.

@Ghostbird
Copy link
Author

Oddly, the added manual install of libavcodec-extra line suggested above today caused a problem and removing that package from the installation solved it.

The message was that libavcodec-extra59-XXX could not be installed because libavcodec-extra-59-XXX+nvidiasupport1 was already installed. (XXX is the same version identifier in both cases, but I forgot which one exactly it was).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment