Transcodifica hardware NVIDIA di Jellyfin in Docker
Configura GPU NVIDIA, NVENC e NVDEC con Docker Compose e verifica la transcodifica reale nel container usando nvidia-smi, senza supposizioni.
Cosa stai configurando
La transcodifica hardware di Jellyfin su una GPU NVIDIA richiede 4 passaggi in un ordine preciso, e solo l'ultimo viene eseguito all'interno di Jellyfin. Il container non può accedere a una GPU per cui il driver dell'host non è stato caricato. Jellyfin non può usare una GPU che il container non riesce a vedere. Procedi in questo ordine: ogni errore avrà una causa evidente da verificare.
- Installa il driver NVIDIA sull'host, quindi verifica l'installazione con
nvidia-smi. - Installa NVIDIA Container Toolkit, in modo che Docker possa assegnare una GPU a un container.
- Riserva la GPU per il servizio Jellyfin in
docker-compose.yml, quindi verifica che il container riesca a vederla. - Abilita NVENC e NVDEC nelle impostazioni di riproduzione di Jellyfin, quindi verifica che una riproduzione reale li utilizzi.
NVENC (encoder NVIDIA) e NVDEC (decoder NVIDIA) sono blocchi a funzione fissa presenti sulla scheda. Sono circuiti distinti dagli shader core che eseguono i carichi di lavoro CUDA (compute unified device architecture). È proprio questa separazione a rendere utile la configurazione: un flusso che in modalità software utilizza diversi core della CPU richiede soltanto una piccola frazione di un core e un blocco hardware dedicato della GPU.
Il direct play è sempre preferibile alla transcodifica, quindi verificalo per primo
Prima di configurare qualsiasi componente, verifica se stai transcodificando per un motivo che puoi semplicemente eliminare. Jellyfin esegue la transcodifica quando il client non può riprodurre il file nel formato originale. Il motivo rientra sempre in un elenco ristretto: codec video, codec audio, formato del contenitore, sottotitoli basati su immagini oppure limite di bitrate richiesto dal client.
Apri Dashboard, quindi Playback, e controlla una sessione attiva mentre viene riprodotto un contenuto. Una sessione indicata come Direct playing invia il file senza modificarlo e richiede quasi nessuna CPU. Una sessione indicata come Transcoding mostra il motivo scelto da Jellyfin. Elimina quel motivo e la GPU non dovrà eseguire alcuna operazione.
Due modifiche eliminano la maggior parte delle transcodifiche. Imposta la qualità dell'app client su Auto o sul valore massimo, perché un client che richiede 4 Mbps forza la ricodifica di un file da 20 Mbps, indipendentemente dal codec utilizzato. Usa quindi un'app client nativa invece di una scheda del browser, perché il browser è il riproduttore più limitato tra quelli disponibili e un'app nativa installata sullo stesso televisore spesso esegue il direct play dello stesso file.
I sottotitoli basati su immagini sono l'eccezione che nessuna impostazione del client può risolvere. I sottotitoli PGS estratti da un Blu-ray e quelli VOBSUB estratti da un DVD sono immagini, quindi devono essere sovrapposti direttamente al video. Questo richiede la ricodifica completa del flusso video. I sottotitoli testuali in formato SRT vengono inviati al client come traccia separata e non consumano risorse significative. Quando possibile, convertire le tracce dei sottotitoli in testo è più utile che aggiungere una GPU. Il resto della configurazione lato server è descritto in la guida per eseguire un media server Jellyfin su un VPS.
La maggior parte dei piani VPS non include alcuna GPU
I piani VPS standard non includono una GPU. Esegui questo comando sul server prima di pianificare qualsiasi altra attività.
lspci -nn | grep -Ei "3d|display|vga"Su un VPS KVM tipico, questo comando mostra un adattatore video virtuale fornito dall’hypervisor oppure non restituisce informazioni utili. Questo dispositivo non può codificare video. Una GPU reale è disponibile solo quando il provider assegna direttamente alla tua istanza una scheda fisica oppure una sua porzione; questi piani hanno un prezzo proporzionato. Quali carichi di lavoro giustificano davvero il costo di un VPS con GPU spiega chi dovrebbe pagare una GPU VPS e chi no.
Se non c’è una GPU, punta sul direct play e considera la transcodifica software un caso raro. Una singola transcodifica software 1080p H.264 è impegnativa, ma può essere gestita da pochi core CPU. Una transcodifica software 4K HDR con tone mapping non può essere completata in tempo reale da un VPS di piccole dimensioni; lo streaming procede quindi a scatti mentre la CPU resta al 100 percento.
Installare il driver NVIDIA sull'host
Jellyfin 10.11 indica come requisito minimo il driver NVIDIA 520.56.06 su Linux. Ubuntu include uno strumento che seleziona automaticamente un pacchetto compatibile.
sudo ubuntu-drivers list --gpgpu
sudo ubuntu-drivers install --gpgpu
sudo reboot--gpgpu seleziona la variante headless server del driver. È quella adatta a un media server, perché il sistema non dispone di un ambiente desktop. Il comando list mostra i branch disponibili. È possibile fissarne uno in base al nome, ad esempio sudo ubuntu-drivers install --gpgpu nvidia:570-server. Usare un branch effettivamente mostrato dall'elenco, non quello riportato qui.
La variante server non installa sempre nvidia-smi. Installare il pacchetto utils corrispondente al branch scelto, ad esempio sudo apt install nvidia-utils-570-server. Verificare quindi il driver.
nvidia-smiUn risultato corretto mostra nell'intestazione una tabella con la versione del driver e la versione di CUDA, elenca la scheda in base al nome e presenta un elenco dei processi vuoto. In questo punto sono comuni due errori. nvidia-smi: command not found indica che manca il pacchetto utils, non il driver. NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver indica che il modulo del kernel non è caricato. In una nuova installazione, la causa è quasi sempre un riavvio non ancora eseguito oppure il blocco del caricamento di un modulo non firmato da parte di Secure Boot. Verificare la presenza del modulo con lsmod | grep nvidia.
Installare NVIDIA Container Toolkit
Il driver consente all'host di utilizzare la GPU. Docker, però, non la inoltra automaticamente al container, perché il container non dispone né dei device node né delle librerie del driver. NVIDIA Container Toolkit inserisce entrambi all'avvio del container. Questi sono i comandi di installazione ufficiali di NVIDIA per Debian e Ubuntu.
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkitInstallare il pacchetto non è sufficiente, perché è necessario informare Docker dell'esistenza del runtime.
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart dockernvidia-ctk runtime configure scrive una voce di runtime nvidia in /etc/docker/daemon.json. Il riavvio è il passaggio che viene più spesso saltato. Se lo si omette, si ottiene l'errore più comune dell'intera procedura. Verificare il funzionamento dell'integrazione prima di intervenire su Jellyfin.
sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smiDovrebbe stampare la stessa tabella visualizzata dall'host. Se invece restituisce un errore relativo all'impossibilità di selezionare un device driver con funzionalità GPU, il demone Docker non conosce il runtime nvidia. Eseguire nuovamente il comando di configurazione e riavviare il demone.
Assegnare la GPU al container Jellyfin in Docker Compose
Questa è la sintassi Compose moderna, conforme all’esempio pubblicato da Jellyfin.
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
user: 1000:1000
network_mode: host
restart: unless-stopped
environment:
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=all
volumes:
- /srv/jellyfin/config:/config
- /srv/jellyfin/cache:/cache
- /srv/media:/media:ro
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]Avvia lo stack e interroga direttamente il container.
docker compose up -d
docker compose exec jellyfin nvidia-smiSe il comando visualizza la tabella dei driver dall’interno del container, il passthrough della GPU funziona correttamente e ogni problema residuo riguarda una configurazione di Jellyfin.
Quattro righe di questo file richiedono una spiegazione. capabilities: [gpu] è richiesta direttamente da Compose: se manca, Compose rifiuta il servizio invece di avviarlo senza GPU. NVIDIA_DRIVER_CAPABILITIES=all è importante perché il toolkit monta le librerie video nel container solo quando viene richiesta la capability video. La documentazione di Jellyfin indica inoltre questa variabile come richiesta per l’immagine ufficiale. Senza questa variabile, CUDA funziona ma NVDEC no, e il log della transcodifica riporta Cannot load libnvcuvid.so.1. network_mode: host è usata nell’esempio di Jellyfin perché la rilevazione automatica dei client sulla porta UDP 7359 non funziona attraverso una rete bridge.
user: 1000:1000 è l’ultima riga e non riguarda la GPU. Determina quali file Jellyfin può leggere nel mount dei contenuti multimediali. Un valore non corrispondente si manifesta con una libreria vuota, non con un errore di permessi. Come PUID e PGID associano un utente del container ai file sul disco spiega la numerazione. Si tratta della stessa numerazione già configurata se esegui lo stack Sonarr e Radarr in Docker Compose insieme a questo.
Perché la maggior parte dei tutorial usa ancora runtime: nvidia
La sintassi più vecchia compare in quasi tutte le guide disponibili e non è errata. È una scelta storica. Il pacchetto nvidia-docker2 originale registrava un runtime OCI denominato nvidia, quindi l'unico modo per rendere disponibile una GPU in un container era usare --runtime=nvidia insieme a NVIDIA_VISIBLE_DEVICES. Docker 19.03 ha aggiunto il flag --gpus e un'API specifica per le richieste dei dispositivi. Compose ha impiegato più tempo per adeguarsi e, quando lo ha fatto, la richiesta del dispositivo è stata inserita in deploy.resources.reservations.devices, una chiave che molti avevano imparato a ignorare perché deploy indicava in precedenza Docker Swarm.
Di conseguenza, oggi entrambe le sintassi funzionano e l'esempio pubblicato da Jellyfin le include entrambe. Mantenere runtime: nvidia non comporta costi e consente al file di funzionare con versioni meno recenti di Compose. Se mantieni soltanto runtime: nvidia e rimuovi il blocco deploy, devi mantenere NVIDIA_VISIBLE_DEVICES=all, perché quel percorso legacy legge la variabile d'ambiente per decidere quali dispositivi iniettare e non ha alcuna richiesta di dispositivo alternativa da leggere.
Attivare la transcodifica hardware NVIDIA in Jellyfin
Finora nessuna impostazione ha indicato a Jellyfin di usare la scheda. Apri Dashboard, quindi Playback e Transcoding. Imposta Hardware acceleration su Nvidia NVENC. Seleziona Enable hardware encoding. In caso contrario Jellyfin decodifica sulla GPU e poi codifica sulla CPU. È la situazione intermedia più difficile da interpretare: la GPU mostra attività, ma la CPU continua a essere fortemente utilizzata.
Attiva Enable enhanced NVDEC decoder. Questa opzione seleziona il percorso NVDEC attuale invece del percorso CUVID precedente. Lasciala attiva. La gestione di Dolby Vision richiede questa opzione per usare NVDEC.
In Enable hardware decoding for, seleziona soltanto i codec che la scheda è effettivamente in grado di decodificare. È l'impostazione che spesso viene configurata in modo errato. Se selezioni AV1 su una scheda priva di decoder AV1, non viene visualizzato alcun errore. Jellyfin richiede la decodifica hardware, non la ottiene e passa alla decodifica software. Il risultato è un utilizzo elevato della CPU e una GPU quasi inattiva. Questo comportamento è identico a quello che si osserva quando il passthrough non funziona.
Esiste un'ulteriore condizione per l'intera pagina: l'accelerazione hardware funziona soltanto con la build jellyfin-ffmpeg inclusa. Se hai impostato il percorso di FFmpeg su un'installazione di FFmpeg del sistema, l'accelerazione è parziale o assente.
Quali codec può decodificare e codificare la generazione della tua GPU
Questi sono i limiti documentati da Jellyfin per NVENC e NVDEC. La decodifica e la codifica sono funzionalità separate: una scheda può supportarne una senza supportare l’altra.
- H.264 8-bit: ogni GPU NVIDIA con NVENC e NVDEC supporta sia la decodifica sia la codifica.
- HEVC 8-bit: decodificazione e codificazione a partire da Maxwell di seconda generazione (GM206) e versioni successive.
- HEVC 10-bit: decodificazione a partire da Maxwell di seconda generazione e versioni successive, ma codificazione solo a partire da Pascal e versioni successive.
- AV1: decodificazione a partire da Ampere e versioni successive, codificazione a partire da Ada Lovelace e versioni successive.
La distinzione relativa a HEVC 10-bit è quella che crea più problemi nella pratica. Una scheda della generazione Maxwell decodifica sulla GPU il file 4K HDR, ma non può codificare un output a 10-bit. Jellyfin codifica quindi un video H.264 a 8-bit. Il risultato viene comunque riprodotto correttamente ed è la scelta appropriata per la maggior parte dei client. Nel 2026 la codifica AV1 raramente è la scelta desiderata, indipendentemente dalla scheda utilizzata, perché il supporto alla decodifica AV1 lato client è ancora limitato e un transcode serve a raggiungere un client che aveva già difficoltà nella riproduzione.
Perché il tone mapping satura di nuovo la GPU senza segnalarlo
Il tone mapping da HDR (high dynamic range) a SDR (standard dynamic range) è l'impostazione che consuma silenziosamente il budget della GPU, per ragioni architetturali. La decodifica viene eseguita da NVDEC. La codifica viene eseguita da NVENC. Il tone mapping non viene eseguito da nessuno dei due: è un filtro CUDA che usa gli shader core, cioè la parte general purpose della GPU che esegue i carichi di calcolo. Di conseguenza, uno stream 4K HDR che richiede il tone mapping usa il decoder e l'encoder e, in più, carica gli shader.
Jellyfin documenta il tone mapping CUDA come disponibile su ogni GPU NVIDIA in grado di decodificare HEVC 10-bit. Questo significa che la casella di controllo viene visualizzata e funziona anche su schede che non riescono a gestirlo a 4K in modo continuativo. Il sintomo è uno stream che parte, entra in buffering e non si stabilizza mai, mentre nvidia-smi indica che l'encoder è utilizzato a malapena.
Per questo è utile monitorare separatamente il carico degli shader.
nvidia-smi dmon -s uIl comando stampa una riga al secondo con colonne separate per sm, enc e dec. Valori bassi per enc e dec accanto a un valore elevato per sm indicano che i blocchi a funzione fissa sono poco utilizzati e che il collo di bottiglia è costituito dagli shader. In questo caso, il costo è dovuto al tone mapping, allo scaling o all'incorporamento dei sottotitoli. Il percorso CUDA gestisce inoltre Dolby Vision profile 5 con zero copy. Questo è importante perché, senza zero copy, i frame vengono trasferiti nella memoria di sistema e poi riportati indietro tra un passaggio del filtro e l'altro, consumando banda a ogni singolo frame.
Il limite delle sessioni NVENC consumer: che cosa limita realmente
The data behind this chart
[
{
"label": "GeForce RTX 5090",
"nvenc_engines": 3,
"max_encode_sessions": 12
},
{
"label": "GeForce RTX 4090",
"nvenc_engines": 2,
"max_encode_sessions": 12
},
{
"label": "GeForce RTX 4060",
"nvenc_engines": 1,
"max_encode_sessions": 12
}
]Questi sono i valori pubblicati da NVIDIA nella matrice di compatibilità ad agosto 2026, non misurazioni eseguite in questa sede. Una scheda GeForce è limitata a 12 sessioni di codifica simultanee, indipendentemente dal modello. Il limite è imposto dal driver, non dal silicio, e NVIDIA lo ha aumentato più volte nel corso degli anni. Consultate quindi la matrice corrente, non una vecchia discussione sul forum. Il numero di motori è l'elemento che varia realmente in base alla scheda: GeForce RTX 5090 dispone di 3 motori NVENC, mentre GeForce RTX 4060 ne dispone di 1. Un numero maggiore di motori aumenta la velocità di codifica parallela, non il limite massimo di sessioni.
Il limite conta le sessioni di codifica, quindi riguarda soltanto i flussi sottoposti a transcoding. Direct play e remuxing non aprono mai una sessione di codifica. Le schede per data center, come L4, sono indicate come prive di limitazioni nella stessa matrice. Inoltre, un piano GPU VPS fornisce solitamente una scheda per data center. Il limite riguarda quindi soprattutto i server domestici.
Quando raggiungete il limite, il transcoding fallisce e il log di FFmpeg contiene OpenEncodeSessionEx failed: out of memory (10). Il messaggio cita la memoria, ma anche un rifiuto dovuto al limite delle sessioni restituisce lo stesso codice. Controllate quindi il numero di flussi simultanei prima di cercare una perdita di VRAM. Nella maggior parte dei casi, il limite del tone mapping o la larghezza di banda in upload vengono raggiunti molto prima della dodicesima sessione.
Verificare che la GPU esegua la transcodifica senza fidarsi della configurazione
Un’impostazione salvata non è una prova. Riproduci un file che sai obbligare la transcodifica, quindi esegui tre controlli.
- Apri Dashboard, quindi Playback. La sessione attiva dovrebbe indicare Transcoding e specificarne il motivo. Se indica Direct playing, non è in corso alcuna transcodifica e stai verificando il file sbagliato.
- Apri Dashboard, quindi Logs, e apri il log
FFmpeg.Transcodepiù recente. Una transcodifica hardware mostra-hwaccel cudae-hwaccel_output_format cudanella riga di comando, conh264_nvencohevc_nvenccome encoder. Se comparelibx264, la transcodifica viene eseguita via software, indipendentemente da quanto indicato dalla pagina delle impostazioni. - Esegui
nvidia-smisull’host mentre la riproduzione continua. Dovrebbe comparire un processo di/usr/lib/jellyfin-ffmpeg/ffmpegcon memoria GPU allocata envidia-smi dmon -s udovrebbe mostrare valori diversi da zero nelle colonne enc e dec.
Esegui il terzo controllo sull’host, non all’interno del container. nvidia-smi eseguito in un container mostra generalmente un elenco dei processi vuoto, perché non può vedere gli ID dei processi esterni al proprio namespace, mentre i valori di utilizzo vengono comunque letti correttamente. Un elenco dei processi vuoto all’interno del container non indica un problema.
Quando passa al software senza informarti
Jellyfin preferisce continuare la riproduzione. Quando un percorso hardware non è disponibile, passa al software invece di interrompere lo streaming. L'indicatore affidabile è quindi il carico della CPU e il log di FFmpeg, non un banner di errore.
Cannot load libnvcuvid.so.1 nel log della transcodifica indica che la libreria del decoder non è mai stata montata nel container. Imposta NVIDIA_DRIVER_CAPABILITIES=all e ricrea il container, perché una modifica dell'ambiente richiede docker compose up -d per ricostruirlo; un semplice riavvio mantiene le impostazioni precedenti.
No capable devices found da h264_nvenc indica che FFmpeg ha raggiunto la libreria dell'encoder, ma non ha trovato alcuna scheda utilizzabile. Controlla nuovamente docker compose exec jellyfin nvidia-smi, perché di solito significa che la prenotazione del dispositivo è stata rimossa oppure che il container è stato ricreato da un file obsoleto.
Un utilizzo elevato della CPU con una GPU poco utilizzata indica che la decodifica non funziona senza produrre errori visibili. Deseleziona i codec che la tua generazione hardware non è in grado di decodificare, quindi riproduci nuovamente lo stesso file e rileggi il log di FFmpeg per verificare se compare -hwaccel cuda.
Una transcodifica che si avvia e poi si blocca con contenuti 4K HDR, mentre 1080p funziona correttamente, indica il limite della gestione del tone mapping, non un'installazione danneggiata. Confermalo con la colonna sm di nvidia-smi dmon -s u, quindi riduci la risoluzione richiesta dal client oppure mantieni i file 4K HDR sui client in grado di riprodurli direttamente.
FAQ
Perché Jellyfin continua a usare la CPU dopo che ho abilitato NVENC?
Controlla il log FFmpeg.Transcode più recente in Dashboard, quindi Logs. Se mostra libx264, non è stato usato alcun percorso hardware. Di solito significa che il container non può accedere alla GPU, quindi esegui docker compose exec jellyfin nvidia-smi per verificarlo. Se mostra h264_nvenc ma la CPU è ancora sotto carico, la decodifica viene eseguita via software. Questo accade quando hai selezionato un codec che la scheda non può decodificare oppure quando hai lasciato disabilitata l'opzione Enable hardware encoding, spostando sulla GPU solo metà della pipeline.
La riga runtime: nvidia è ancora necessaria in Docker Compose?
No, se hai il blocco deploy.resources.reservations.devices e una versione aggiornata di Docker Compose. Questo blocco è la sintassi moderna per la richiesta dei dispositivi e svolge la stessa funzione. runtime: nvidia è il metodo precedente dell'epoca nvidia-docker2. È ancora supportato e l'esempio pubblicato da Jellyfin mantiene entrambe le configurazioni. Tenerle entrambe non crea problemi. Se mantieni soltanto runtime: nvidia, devi mantenere anche NVIDIA_VISIBLE_DEVICES=all, perché quel metodo non contiene una richiesta di dispositivi da analizzare e ricava l'elenco dei dispositivi dall'ambiente.
Quanti stream può transcodificare contemporaneamente una singola GPU NVIDIA?
La matrice pubblicata da NVIDIA limita le schede GeForce a dodici sessioni di codifica simultanee ad agosto 2026, mentre le schede per data center sono indicate come prive di limitazioni. Questo limite raramente è il fattore determinante. La conversione tone mapping da HDR a SDR viene eseguita dagli shader core, non da NVENC. Di conseguenza, pochi stream 4K HDR possono saturare gli shader molto prima che il numero di sessioni diventi rilevante. Misura il tuo caso con nvidia-smi dmon -s u e controlla la colonna sm, non il numero di sessioni.
Posso usare la transcodifica hardware su un VPS senza GPU?
No. La codifica richiede il blocco fisico NVENC e, su un VPS standard, lspci -nn | grep -Ei "3d|display|vga" mostra soltanto un adattatore video virtuale fornito dall'hypervisor. Su un piano senza GPU, la soluzione realistica è eliminare le transcodifiche: imposta la qualità del client su Auto, usa un'applicazione client nativa invece del browser e converti le tracce dei sottotitoli basate su immagini in testo, così non forzano una nuova codifica video.
Perché il video 4K HDR procede a scatti mentre la transcodifica 1080p funziona senza problemi?
I due carichi di lavoro usano componenti diversi della scheda. Una transcodifica 1080p SDR richiede soltanto decodifica e codifica, entrambe eseguite dall'hardware a funzione fissa. Uno stream 4K HDR aggiunge il tone mapping, che è un filtro CUDA eseguito dagli shader core, oltre a un frame molto più grande da ridimensionare. La presenza di nvidia-smi dmon -s u con valori bassi per enc e dec e un valore elevato per sm conferma questa situazione, perché indica che i blocchi a funzione fissa sono inattivi e che il limite è rappresentato dai core general purpose.