NVIDIA+TVHEADEND+UNRAID+ACCELERATED FFMPEG
I recently had a need to get hardware accelerated ffmpeg running on tvheaded under unraid, I eventually achieved this with a few tricks, here are my notes on what I did to achieve this.
First up, Unraid NVIDIA support
Install the Nvidia plugin under Unraid, this installs a custom kernel complete with the nidia drivers and docker runtime to support thiese.
Next install a hardware accelerated FFMPEG
Create a new docker container named "ffmpeg", we will clone the following repo:
jrottenberg/ffmpeg:4.1-nvidia
I chose this version as it is linked against a version of the nvidia drivers that is compatible with the Unraid Nvidia plugin.
Go into advanced settings on the docker container and set the "Extra Parameters" to the following:
-it --entrypoint bash --runtime=nvidia
The container as default simply runs an instance of ffmpeg and then exits. Modifying the entrypoint allows us to spawn a container containing the FFMPEG binary and keep it running so we don't have to create a container on the fly every time.
Setting the runtime to nvidia is important, without it hardware acceleration won't work.
Now we have a container set up which is capable of running a hardware accelerated FFMPEG.
Modifying the tvheadend container
We need to make some changes to the tvheadend container to allow it to use our ffmpeg, you could make these changes by cloning the docker file and then creating your own modified image, but I have gone with a second option of overlaying some modified files over the existing installation.
In the appdata folder for your tvheadend, create the following files with the following content:
Filename: run (for example /mnt/user/appdata/tvheadend/run)
#!/usr/bin/with-contenv bash
IFS=" " read -r -a RUN_ARRAY <<< "$RUN_OPTS"
apk add docker
chmod o+rw /var/run/docker.sock
exec \
s6-setuidgid abc /usr/bin/tvheadend -C -c /config "${RUN_ARRAY[@]}"
I have added the lines to install docker and change the permissions on docker.sock. This allows us to access the containers running on the host, the permission change is required as the tvheadend runs as an unprivileged user in the container and with the default permissions cannot access the docker.sock socket.
Ensure the file has execute permissions (chmod +x /mnt/user/appdata/tvheadend/run
on the host)
Filename: ffmpeg.hw (for example /mnt/user/appdata/tvheadend/ffmpeg.hw)
#!/bin/sh
docker exec -i ffmpeg /usr/local/bin/ffmpeg $@
(If you called your container something other than ffmpeg then you will need to change the "-i ffmpeg
" to match the name of your container.)
Ensure the file has execute permissions (chmod +x /mnt/user/appdata/tvheadend/ffmpeg.hw
on the host)
Modifying the tvheadend container
We need to add the following paths to the tvheadend container:
Host Path: /var/run/docker.sock
Container Path: /var/run/docker.sock
Host Path: /mnt/user/appdata/tvheadend/run
Container Path: /etc/services.d/tvheadend/run
Host Path: /mnt/user/appdata/tvheadend/run
Container Path: /etc/services.d/tvheadend/run
Host Path: /mnt/user/appdata/tvheadend/ffmpeg.hw
Container Path: /usr/local/bin/ffmpeg.hw
(I have noticed tvheadend doing some weird things with the run script, sometimes a copy appears in /root, so I have added that as well, no idea if it's actually required, but it doesn't hurt so....)
Configuring tvheadend
Ensure that the ffmpeg container is started and restart the tvheadend container, you should now be able to add a custom stream format in tvheaded with a command like:
Command Line:
/usr/local/bin/ffmpeg.hw -hwaccel cuvid -c:v mpeg2_cuvid -i pipe:0 -c:a copy -c:v h264_nvenc -b:v 5M -f matroska pipe:1
Mime Type:
video/h264
When you select that stream profile you should find that it uses the hardware accelerated ffmpeg, you can check this by running nvidia-smi on the host, you should see ffmpeg running.
Yeah, I setup everything per the instructions.
Only thing I can think of is the stream shows as
htsp
profile: