Guide: NVDEC Hardware Acceleration Patch for Plex Media Server on Linux

Looks like it’s decoding then.

image

Are there any quality settings for this script that you can choose from?

Additionally, is there a way to quickly undo and re-do the patch to compare the GPU transcoding quality with CPU transcoding? I’d like to see if I can tell the difference and compare them.

audio, and subtitles are all done through cpu and are single threaded.

so I suppose it depends on what cpu you have and it’s single core performance level.

but in general on a decently modern cpu, yes the cpu load should be fairly low. Older cpus will of course be more heavily loaded.

my post # 94 above shows cpu load on a dual cpu xeon with 2x 4k and 1 something else going on.

if your streams are 4 x265 streams and your not getting any buffering, then the gpu is working.

read the script…

https://github.com/revr3nd/plex-nvdec

Any idea what I can look into to get nvdec working for me? I have the patch installed as you can see, but It is still not giving decoding for whatever reason…

So this is working great currently, and the GPU decoding seems to speed transcodes up considerably compared to CPU decoding, which is great to see.

Does this still honor the Transcoder default throttle buffer setting (Amount in seconds to buffer before throttling the transcoder)? Because I would like to buffer much more so that I can easily skip forward and skip back without any lag.

Will the script still honor the value that you setup in here (eg if I put in 300 seconds, will it only throttle the GPU transcoding after it has 5 minutes of video)? And if not, how can I force Plex to do this?

Still not able to get this working – updated my CPU since I needed to do that anyways and there is no imbedded GPU in my new CPU. Still not able to get HW Dec to work on this with the patch applied and encoding working just fine. Guess i’ll just have to wait for full support via Plex’s feature request

Here’s what I’m doing to get this working in docker but I get the following error:

cannot load libcuda.so.1
Could not dynamically load CUDA

Any ideas?


FROM linuxserver/plex
RUN mkdir /temp
COPY ./plex-nvdec-patch.sh /temp/plex-nvdec-patch.sh
RUN /bin/bash -c ‘chmod +x /temp/plex-nvdec-patch.sh’
RUN /bin/bash -c ‘/temp/plex-nvdec-patch.sh’
RUN /bin/bash -c ‘rm -rf /temp’
ENTRYPOINT ["/init"]

Make sure you have the plex-nvdec-patch.sh file in the same dire as the docker file.

run: docker image build -f dockerfile -t plex-hw-transcode .

Change your docker compose.yaml to use plex-hw-transcode or use docker run with plex-hw-transcode.

Any time the parent image is updated it will run the script automatically for you.

Note you need to use linuxserver/plex because plexinc/pms-docker doesn’t have hardware access yet. (There’s an outstanding pull request for it)

Here’s a .sh script that you can use to get the latest version of this script, and then rebuild the docker image whenever you need to:

rm plex-nvdec-patch.sh
curl -O https://raw.githubusercontent.com/revr3nd/plex-nvdec/master/plex-nvdec-patch.sh
docker image build -f dockerfile -t plex-hw-transcode .

HI all!
I have 872XT QNAP with 1050GT. I tried using PLEX with GPU, but I could not get Docker never to work. I donwloaded many PLEX dockers, even witn ones that say NVIDIA included… But none of them uses NVIDIA… Is there now ready PLEX package to download and use, or is it still something that regular user cannot do… because just PUTTY alone is too much…

I installed latest 1.16.7.1574 and It seems that NVIDIA is implemented finally to this version. Now my QNAP runs at 13% with 4K and GPU is 750mb/4GT… =)

I can kick EMBY out… and start tagging all media again watched, not watched… =)

This patch seems deprecated now that Plex Media Server 1.17.0.1709 contains the API support for linux Nvidia hardware encode & decode, and it seems to function ideally - Plex Media Server

Use keylase’s Nvidia driver library patch to remove the two transcode limit on consumer nvidia cards for a more holistic solution - https://github.com/keylase/nvidia-patch

Hi. I have updated my PMS to 1.17.0.1709 and have an Nvidia 1060(GP106) card in my server machine running Mint 19.1. Below is the link to my machine’s basic hardware info.

Below is another image showing whats happening on my machine., where I’m forcing transcoding of 4 concurrent streams hoping that it would go to the GPU. The image shows ‘nvidia-smi’ handling all 4 streams. It also shows netdata snapshot of the PMS server, showing CPU usage hitting 99%.

Below are my issues:

  1. When my friend tries to initiate a different stream after PMS update to 1.17.0.1709, it buffers for ever and never plays back anything. Attached below is the logs zip. The action happens at after 22:30 yesterday, with user hexvalues in the logs.
  2. I have heard that Nvidia on consumer graphics card limit to 2 transcodings at a time. I have been able to trigger 4 as shown in the image above using 430.xx driver. Not sure when all the 4 streams are being handled by the GPU, why the CPU usage still spikes to 99%? Does the GPU just handle 2 and just dump the others to the CPU?

Appreciate any help in resolving this issue.

Plex Media Server Logs_2019-09-26_09-54-44.zip (4.6 MB)

I’m using 1.18.0.1944 with Plex Pass and it’s using both NVDEC and NVENC.

However, I am using a Turing GPU with the Turing NVENC block, but it seems from the command line that Plex isn’t using any of the improved features of Turing to increase picture quality at a given bitrate.

I figured modifying the patch slightly to prepend the necessary arguments might do the trick. Will try as soon as I can.

Edit: Tested without success, both prepending and appending around “$@”

It would be really nice if we were allowed to choose preset (default hq, same as medium), enable bframes, physchovisual analysis, and high profile (default main).

Edit:
I’ve modififed the script to fit Turing GPUs. The quality is vastly improved!

  ARRAY=()
  for i in "$@"; do
     if [[ $i =~ "hq" ]]; then
         ARRAY+=("slow" "-profile:v" "high" "-bf" "3" "-temporal-aq" "1" "-rc-lookahead" "20" )
     else
         ARRAY+=("$i")
     fi
  done
  exec "$PLEX_PATH/Plex Transcoder2" -hwaccel nvdec "${ARRAY[@]}"

Appending to the above, it’s unclear if any of the arguments above are rejected by or unknown to the transcoder, but they’re present in FFMPEG. I’ve not tested if all of the arguments have an active effect, but they’re at their recommended settings according to nVidia’s documentation.

However, I have tested multiple videos and seen a very noticeable improvement in visual quality for those interested and who are using a Turing GPU with the Turing NVENC, such as GTX 1660 and above.

Do note that the above settings produce a PQ much better than that of software encoding with the setting “Make my CPU hurt”, although there’s plenty of room for those settings to improve, too. For example, that seems to still use “veryfast” for the most part.

Edit: changed bframes to 4 (max for Turing AFAIK), and appended “-b_ref_mode” “2”, assuming the Plex Transcoder supports it, allows for dynamic bframe placement.

Edit: Reading closer about the b_ref_mode it works differently than I figured it would, and refers instead to how many can be referenced, according to https://fossies.org/linux/ffmpeg/libavcodec/nvenc_h264.c

I’m starting to wish I had gone for a 1660 instead of the 1650. :nauseated_face:

Thanks for the testing and script updates. Has Turing NVENC support been included in PMS or do we still need to hack it?

Turing NVDEC is working for me in Plex.

@revr3nd Hi, I was wondering if you ever considered modifying this patch (or creating a similar one) based up on forcing plex to transcode TO HEVC ?

Since there isn’t really a need for this patch for NVDEC any more, but it could still be useful as a basis to force hevc encoding (assuming plex’s transcoder can be forced to do such).

thoughts?

Interesting idea. for clients that can handle native HEVC playback, it could be greater quality at similar bitrate, or lower bitrate at similar quality. Within handbrake my 10 series card using NVENC + CPU to encode BluRay to to HEVC at better than real time, so it sould work in at least some systems.

Yea it would not be good for people who have mixed clients that don’t direct play hevc, but could be a great bandwidth and or quality saver for those who can make use of it.

@TeknoJunky This would be a cool idea, but it sadly is a non-starter.

The FFMPEG transcoder that Plex has custom compiled does not include NVENC support for HEVC/H.265. You can see this via the output below:

$ /usr/lib/plexmediaserver/Plex\ Transcoder -codecs
Codecs:
 D..... = Decoding supported
 .E.... = Encoding supported
 ..V... = Video codec
 ..A... = Audio codec
 ..S... = Subtitle codec
 ...I.. = Intra frame-only codec
 ....L. = Lossy compression
 .....S = Lossless compression
 -------
 .EV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: h264_nvenc h264_vaapi )
 .EV.L. hevc                 H.265 / HEVC (High Efficiency Video Coding) (encoders: hevc_vaapi )

$ /usr/lib/plexmediaserver/Plex\ Transcoder -encoders
Encoders:
 V..... = Video
 A..... = Audio
 S..... = Subtitle
 .F.... = Frame-level multithreading
 ..S... = Slice-level multithreading
 ...X.. = Codec is experimental
 ....B. = Supports draw_horiz_band
 .....D = Supports direct rendering method 1
 ------
 V..... h264_nvenc           NVIDIA NVENC H.264 encoder (codec h264)
 V..... h264_vaapi           H.264/AVC (VAAPI) (codec h264)
 V..... hevc_vaapi           H.265/HEVC (VAAPI) (codec hevc)

I snipped the output to the relevant lines, but it shows that HEVC is a supported codec, but the only encoder option is hevc_vaapi, which uses Intel Quicksync or otherwise falls back to purely CPU only. NVENC is only supported in H.264 without painstakingly recompiling the FFMEPG transcoder. I know some other users had attempted to do this, but there is some secret sausce from Plex baked in here, so it’s pretty much not possible without Plex adding the support themselves.

As a note, you FFMEPG itself does have the ability to use NVENC in HEVC encoding, but it requires this feature to be built in on compile, and Plex is not including that in their compile of FFMPEG. This is very likely to reduce bugs and keep a consistent experience for everyone.

You can still request this be added as a feature, but I think it would be difficult to gain traction as HEVC in general takes much more processing to encode and is much more limited in what devices can consume direct HEVC streams.