Document GPU setup, --gpus vs --runtime=nvidia, and VRAM starvation
Required Mount section now shows full Extra Parameters for both GPU and non-GPU containers and explains why --gpus beats --runtime=nvidia at setup time rather than burying it in Troubleshooting. New troubleshooting entry documents the GPU memory starvation cascade: OCR sidecar (PaddleOCR) holds VRAM → Jellyfin hard-fails, Emby falls back to CPU silently. Emby's NVIDIA startup probe is one-shot — VRAM must be free before restarting or NVIDIA stays disabled for the session. Includes correct recovery sequence and Tesseract fallback for EmbyCredits. README callout updated from two to three non-obvious requirements.
This commit is contained in:
@@ -44,16 +44,43 @@ suppressed.
|
||||
|
||||
### Required Mount
|
||||
|
||||
In Emby's **Extra Parameters** in the unRAID Docker template:
|
||||
Everything goes in the unRAID Docker template **Extra Parameters** field. Do NOT use the
|
||||
path mapping UI for the transcode directory — it does not support `bind-propagation`.
|
||||
|
||||
**Non-GPU containers:**
|
||||
```
|
||||
--mount type=bind,source=/mnt/ram-transcode,target=/ext-ram-transcode,bind-propagation=shared
|
||||
```
|
||||
|
||||
This **replaces** the transcode path in the standard template path mapping UI. Do NOT
|
||||
add this via the path mapping UI — that UI does not support propagation. Extra Parameters only.
|
||||
**GPU-accelerated containers (Emby, Jellyfin with NVENC/NVDEC):**
|
||||
```
|
||||
--gpus "device=GPU-62e1659d-1ed4-935f-3df3-4bb4339438f1" --pids-limit=0 --mount type=bind,source=/mnt/ram-transcode,target=/ext-ram-transcode,bind-propagation=shared
|
||||
```
|
||||
|
||||
In Emby's transcoding settings, set the transcode path to `/ext-ram-transcode`.
|
||||
Replace the UUID with your GPU's UUID (`nvidia-smi -L` to find it).
|
||||
In Emby and Jellyfin's transcoding settings, set the transcode path to `/ext-ram-transcode`.
|
||||
|
||||
---
|
||||
|
||||
### `--gpus` vs `--runtime=nvidia`
|
||||
|
||||
There are two ways to give a container GPU access. **Always use `--gpus`.**
|
||||
|
||||
`--runtime=nvidia` is the old approach. It requires the NVIDIA Container Toolkit configured
|
||||
at the Docker daemon level and spreads across multiple XML fields (runtime flag +
|
||||
`NVIDIA_VISIBLE_DEVICES` env var + `NVIDIA_DRIVER_CAPABILITIES` env var). When unRAID
|
||||
rebuilds a container from template (update, reinstall) these fields can break or get dropped
|
||||
— requiring manual XML repair to recover. `--runtime=nvidia` combined with
|
||||
`NVIDIA_VISIBLE_DEVICES` also conflicts with `bind-propagation=shared` on unRAID 7.2.5+
|
||||
due to a kernel change in mount namespace initialization (see
|
||||
[Troubleshooting](#emby-with-nvidia-gpu--bind-propagationshared-fails-to-start) for the
|
||||
full error and fix).
|
||||
|
||||
`--gpus "device=UUID"` is Docker-native GPU support (Docker 19.03+). One field in Extra
|
||||
Parameters. Pins a specific GPU by UUID — no ambiguity on a single-GPU system. Survives
|
||||
container rebuilds cleanly. Does not conflict with `bind-propagation=shared`.
|
||||
|
||||
**HOST1 GPU UUID (Quadro P2000):** `GPU-62e1659d-1ed4-935f-3df3-4bb4339438f1`
|
||||
|
||||
### Why `shared` Is Required
|
||||
|
||||
@@ -482,6 +509,70 @@ leave the container in a broken state where Emby refuses to start at all.
|
||||
# Re-adding the mount after a clean start works reliably.
|
||||
```
|
||||
|
||||
### GPU Memory Exhausted — Jellyfin Fails, Emby Falls Back to CPU
|
||||
|
||||
**Symptoms:**
|
||||
- Jellyfin refuses to play anything — session fails immediately, no transcode starts
|
||||
- Emby plays but transcodes on CPU (logs show `libx265` or `libx264` instead of `h264_nvenc`/`hevc_nvenc`)
|
||||
|
||||
Both symptoms can appear at the same time and have the same root cause: another process has
|
||||
consumed all available VRAM and not released it. The media servers respond differently to a
|
||||
failed GPU session init:
|
||||
|
||||
- **Jellyfin:** hard fails — no session is created, playback stops entirely
|
||||
- **Emby:** falls back to CPU transcoding silently and keeps going
|
||||
|
||||
```bash
|
||||
# Confirm VRAM is exhausted:
|
||||
nvidia-smi
|
||||
|
||||
# Find what is holding it:
|
||||
nvidia-smi --query-compute-apps=pid,used_memory,name --format=csv,noheader
|
||||
```
|
||||
|
||||
**Common source — OCR plugin sidecars:** Credit detection and subtitle extraction plugins
|
||||
often talk to a GPU-accelerated OCR container running alongside the media server. The
|
||||
EmbyCredits plugin (`yocksers/EmbyCredits`) can be configured to use a PaddleOCR backend.
|
||||
PaddleOCR loads a neural network into VRAM at first use and **does not release it between
|
||||
runs**. After a single credit scan the GPU memory stays consumed, starving Emby and
|
||||
Jellyfin of VRAM for transcoding.
|
||||
|
||||
This is not obvious because PaddleOCR is a separate container — `nvidia-smi` shows the
|
||||
process, but the connection to failing playback is not immediate.
|
||||
|
||||
**Emby startup probe — the restart trap:**
|
||||
|
||||
Emby runs a one-shot NVIDIA hardware detection when the container starts. If VRAM is
|
||||
exhausted at startup, NVIDIA is marked unavailable for the entire container session — there
|
||||
is no retry. Emby will use CPU for all transcoding until the container is restarted, and
|
||||
only after VRAM has been freed. Restarting Emby while VRAM is still exhausted causes the
|
||||
probe to fail again and NVIDIA is disabled again.
|
||||
|
||||
Correct recovery sequence:
|
||||
1. Free VRAM (stop the offending container/process)
|
||||
2. Confirm VRAM is free: `nvidia-smi` — GPU memory used should drop to near zero
|
||||
3. Restart Emby — startup probe now succeeds, NVENC available
|
||||
|
||||
**Fix — switch OCR to CPU:**
|
||||
|
||||
For EmbyCredits: use the `yock1/embycreditocr` Tesseract image instead of PaddleOCR.
|
||||
Tesseract is CPU-based, never touches VRAM, and is the plugin's own documented backend.
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name EmbyCredit-OCR \
|
||||
-p 8884:8884 \
|
||||
--restart unless-stopped \
|
||||
yock1/embycreditocr
|
||||
```
|
||||
|
||||
In EmbyCredits plugin settings, set the OCR endpoint to `http://localhost:8884`.
|
||||
|
||||
The accuracy tradeoff is real (PaddleOCR is stronger on non-Latin scripts) but GPU
|
||||
starvation is not an acceptable failure mode for a live media server.
|
||||
|
||||
---
|
||||
|
||||
### Emby With NVIDIA GPU — bind-propagation=shared Fails to Start
|
||||
|
||||
> **Regression:** This worked before unRAID 7.2.5. The kernel update changed how mount
|
||||
|
||||
@@ -5,11 +5,17 @@ at full speed. When the ramdisk fills, new sessions shift to SSD automatically
|
||||
without interrupting anything already playing. When pressure drops, new sessions shift
|
||||
back to RAM.
|
||||
|
||||
> **Two configuration requirements that are not obvious and were both discovered the
|
||||
> **Three configuration requirements that are not obvious and were all discovered the
|
||||
> hard way in production.** The Docker mount must use `bind-propagation=shared` or
|
||||
> symlink flips are silently ignored after the first flip. The `transcoding-temp`
|
||||
> directory must be pre-created on the ramdisk or Emby finds the SSD version and
|
||||
> routes all sessions there until restarted. Both are documented in Manual-Transcoding.md.
|
||||
> routes all sessions there until restarted. GPU containers require `--gpus "device=UUID"`
|
||||
> in Extra Parameters — not `--runtime=nvidia` — or the container fails to start after
|
||||
> unRAID 7.2.5. Additionally: any GPU-accelerated sidecar (OCR plugins, credit detection)
|
||||
> that holds VRAM and never releases it will starve Emby and Jellyfin of VRAM for
|
||||
> transcoding — Jellyfin hard-fails, Emby silently falls back to CPU. Emby's startup
|
||||
> NVIDIA probe is one-shot: if VRAM is exhausted when the container starts, NVIDIA stays
|
||||
> disabled for the entire session. All three are documented in Manual-Transcoding.md.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user