SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor

Jellyfin : activer le transcodage NVIDIA dans Docker

Configurez Docker Compose pour NVENC et NVDEC dans Jellyfin, puis vérifiez avec nvidia-smi que le GPU transcode réellement les flux vidéo.

Ce que vous allez mettre en place

Le transcodage matériel de Jellyfin sur un GPU NVIDIA se déroule en quatre étapes, dans un ordre fixe. Seule la dernière étape s’effectue dans Jellyfin. Le conteneur ne peut pas voir un GPU dont le pilote n’est pas chargé sur l’hôte. Jellyfin ne peut pas utiliser un GPU que le conteneur ne voit pas. Respectez cet ordre : chaque échec aura ainsi un emplacement évident à vérifier.

  1. Installez le pilote NVIDIA sur l’hôte, puis vérifiez-le avec nvidia-smi.
  2. Installez NVIDIA Container Toolkit afin que Docker puisse attribuer un GPU à un conteneur.
  3. Réservez le GPU pour le service Jellyfin dans docker-compose.yml, puis vérifiez que le conteneur le voit.
  4. Activez NVENC et NVDEC dans les paramètres de lecture de Jellyfin, puis vérifiez qu’une lecture réelle les utilise.

NVENC (encodeur NVIDIA) et NVDEC (décodeur NVIDIA) sont des blocs à fonction fixe intégrés à la carte. Ils utilisent un circuit distinct des cœurs de shaders qui exécutent les tâches CUDA (compute unified device architecture). C’est la raison principale de cette configuration : un flux qui mobilise plusieurs cœurs CPU en logiciel ne consomme plus qu’une petite partie d’un cœur et un bloc matériel dédié du GPU.

Le Direct play est préférable à tout transcodage : commencez par vérifier ce point

Avant de configurer quoi que ce soit, vérifiez si vous transcodez pour une raison que vous pouvez simplement supprimer. Jellyfin transcode lorsque le client ne peut pas lire le fichier tel quel. La cause appartient toujours à une courte liste : le codec vidéo, le codec audio, le format du conteneur, des sous-titres sous forme d’images ou une limite de débit demandée par le client.

Ouvrez Dashboard, puis Playback, et surveillez une session active pendant la lecture. Une session indiquée comme Direct playing envoie le fichier sans modification et consomme presque aucun CPU. Une session indiquée comme Transcoding affiche la raison choisie par Jellyfin. Supprimez cette cause et le GPU n’aura jamais besoin de fonctionner.

Deux modifications suppriment la plupart des transcodages. Réglez la qualité de l’application cliente sur Auto ou sur la valeur maximale, car un client qui demande 4 Mbps force le réencodage d’un fichier à 20 Mbps, quel que soit le codec utilisé. Utilisez ensuite une application cliente native plutôt qu’un onglet de navigateur, car un navigateur est le lecteur le plus limité dont vous disposez et une application native installée sur le même téléviseur pourra souvent lire directement le même fichier.

Les sous-titres sous forme d’images sont l’exception qu’aucun réglage du client ne permet de résoudre. Les sous-titres PGS provenant d’un rip Blu-ray et les sous-titres VOBSUB provenant d’un rip DVD sont des images. Ils doivent donc être incrustés dans la vidéo elle-même, ce qui impose un réencodage complet du flux vidéo. Les sous-titres texte au format SRT sont envoyés au client comme une piste séparée et ne coûtent aucune ressource. Lorsque c’est possible, convertir les pistes de sous-titres en texte est plus utile qu’un GPU. Le reste de la configuration côté serveur est présenté dans le guide pour exécuter un serveur multimédia Jellyfin sur un VPS.

La plupart des offres VPS n’ont aucun GPU

Les offres VPS standard n’incluent pas de GPU. Exécutez cette commande sur le serveur avant toute autre étape.

lspci -nn | grep -Ei "3d|display|vga"

Sur un VPS KVM classique, cette commande affiche un adaptateur graphique virtuel fourni par l’hyperviseur, ou rien d’utile. Ce périphérique ne peut pas encoder de vidéo. Un véritable GPU n’est disponible que si le fournisseur affecte une carte physique à votre instance ou vous en attribue une partition. Ces offres sont facturées en conséquence. Quelles charges justifient réellement le prix d’un VPS avec GPU explique quels utilisateurs en ont besoin et lesquels peuvent s’en passer.

En l’absence de GPU, privilégiez le direct play et considérez le transcodage logiciel comme un cas exceptionnel. Un transcodage logiciel unique en 1080p H.264 est exigeant, mais reste possible avec quelques cœurs CPU. Un transcodage logiciel 4K HDR avec tone mapping ne peut pas être réalisé en temps réel par un petit VPS. Le flux saccade alors que le CPU reste bloqué à 100 percent.

Installer le pilote NVIDIA sur l’hôte

Jellyfin 10.11 indique un pilote NVIDIA Linux minimal en version 520.56.06. Ubuntu fournit un utilitaire qui sélectionne automatiquement un paquet compatible.

sudo ubuntu-drivers list --gpgpu
sudo ubuntu-drivers install --gpgpu
sudo reboot

--gpgpu sélectionne la variante du pilote destinée aux serveurs headless. C’est celle qui convient à un serveur multimédia, car la machine n’a pas d’environnement de bureau. La commande list affiche les branches disponibles. Vous pouvez en choisir une par son nom, par exemple sudo ubuntu-drivers install --gpgpu nvidia:570-server. Utilisez une branche effectivement affichée par la liste, et non celle indiquée ici.

La variante serveur n’installe pas toujours nvidia-smi. Installez le paquet utils correspondant à la branche choisie, par exemple sudo apt install nvidia-utils-570-server. Vérifiez ensuite le pilote.

nvidia-smi

Un résultat correct affiche dans l’en-tête un tableau contenant la version du pilote et la version de CUDA, votre carte sous son nom, ainsi qu’une liste des processus vide. Deux erreurs sont fréquentes. nvidia-smi: command not found signifie que le paquet utils est manquant, et non que le pilote est absent. NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver signifie que le module du noyau n’est pas chargé. Sur une installation récente, cela signifie presque toujours que vous n’avez pas encore redémarré la machine ou que Secure Boot refuse de charger un module non signé. Vérifiez que le module est présent avec lsmod | grep nvidia.

Installer NVIDIA Container Toolkit

Le driver permet à l’hôte d’utiliser le GPU. Docker ne le transmet toutefois pas encore au conteneur, car celui-ci ne possède ni les nœuds de périphériques ni les bibliothèques du driver. NVIDIA Container Toolkit injecte ces deux éléments au démarrage du conteneur. Voici les commandes d’installation fournies par NVIDIA pour Debian et 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-toolkit

Installer le package ne suffit pas, car Docker doit savoir que ce runtime existe.

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

nvidia-ctk runtime configure écrit une entrée de runtime nvidia dans /etc/docker/daemon.json. Le redémarrage est l’étape souvent oubliée. Si vous l’oubliez, vous obtenez l’erreur la plus fréquente de toute cette configuration. Testez l’intégration avant de configurer Jellyfin.

sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi

La commande doit afficher le même tableau que celui affiché par l’hôte. Si elle échoue avec une erreur indiquant qu’il est impossible de sélectionner un device driver disposant de capacités GPU, le daemon Docker ne connaît pas le runtime nvidia. Relancez donc la commande de configuration, puis redémarrez le daemon.

Donnez le GPU au conteneur Jellyfin dans Docker Compose

C’est la syntaxe Compose moderne, conforme à l’exemple publié par 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]

Démarrez la stack, puis interrogez directement le conteneur.

docker compose up -d
docker compose exec jellyfin nvidia-smi

Si cette commande affiche la table des pilotes depuis le conteneur, le GPU est correctement exposé et tous les problèmes restants concernent un réglage de Jellyfin.

Quatre lignes de ce fichier nécessitent une explication. capabilities: [gpu] est requis par Compose lui-même. Si vous l’omettez, Compose refuse le service au lieu de le démarrer sans GPU. NVIDIA_DRIVER_CAPABILITIES=all est important, car le toolkit ne monte les bibliothèques vidéo dans le conteneur que lorsque la capability vidéo est demandée. La documentation de Jellyfin indique également cette variable comme requise pour l’image officielle. Sans elle, CUDA fonctionne, mais pas NVDEC, et le journal de transcodage signale Cannot load libnvcuvid.so.1. network_mode: host est utilisé dans l’exemple de Jellyfin, car la découverte automatique des clients sur le port UDP 7359 ne fonctionne pas sur un bridge network.

user: 1000:1000 est le dernier paramètre. Il n’a aucun rapport avec le GPU. Il détermine les fichiers que Jellyfin peut lire sur votre montage de médias. En cas de discordance, la bibliothèque reste vide au lieu de générer une erreur de permissions. Comment PUID et PGID associent un utilisateur de conteneur aux fichiers sur le disque explique cette numérotation. Il s’agit de la même numérotation que celle que vous avez déjà définie si vous exécutez la stack Sonarr et Radarr dans Docker Compose à côté de ce conteneur.

Pourquoi la plupart des tutoriels utilisent encore runtime: nvidia

L’ancienne syntaxe apparaît dans presque tous les guides que vous trouverez, et elle n’est pas incorrecte. C’est un héritage historique. Le package nvidia-docker2 d’origine enregistrait un runtime OCI nommé nvidia. La seule manière d’ajouter un GPU à un conteneur était donc d’utiliser --runtime=nvidia avec NVIDIA_VISIBLE_DEVICES. Docker 19.03 a ajouté le flag --gpus et une véritable API de demande de périphérique. Compose a mis plus longtemps à suivre. Lorsque cela a été fait, la demande de périphérique a été placée sous deploy.resources.reservations.devices, une clé que la plupart des utilisateurs avaient appris à ignorer, car deploy désignait auparavant Docker Swarm.

Les deux syntaxes fonctionnent donc aujourd’hui, et l’exemple publié par Jellyfin les utilise simultanément. Conserver runtime: nvidia ne coûte rien et permet au fichier de fonctionner avec les anciennes versions de Compose. Si vous conservez uniquement runtime: nvidia et supprimez le bloc deploy, vous devez conserver NVIDIA_VISIBLE_DEVICES=all, car ce chemin hérité lit la variable d’environnement pour déterminer les périphériques à injecter et ne dispose d’aucune demande de périphérique à lire à la place.

Activer le transcodage matériel NVIDIA dans Jellyfin

Jusqu’à présent, rien n’a indiqué à Jellyfin d’utiliser la carte. Ouvrez Dashboard, puis Playback, puis Transcoding. Définissez Hardware acceleration sur Nvidia NVENC. Cochez Enable hardware encoding. Sinon, Jellyfin décode sur le GPU, puis encode sur le CPU. Vous obtenez alors un état intermédiaire difficile à comprendre : le GPU est sollicité, mais le CPU reste fortement utilisé.

Activez enhanced NVDEC decoder. Cette option permet de choisir entre le chemin NVDEC actuel et l’ancien chemin CUVID. Laissez-la activée. La prise en charge de Dolby Vision en dépend pour utiliser NVDEC.

Dans Enable hardware decoding for, cochez uniquement les codecs que votre carte peut réellement décoder. C’est l’option qui pose le plus souvent problème. Cocher AV1 sur une carte dépourvue de décodeur AV1 ne génère aucun message d’erreur. Jellyfin demande un décodage matériel, ne l’obtient pas, puis repasse au décodage logiciel. Vous vous retrouvez donc avec un CPU fortement utilisé et un GPU presque inactif. Cela ressemble exactement à un échec du passthrough.

Une autre contrainte s’applique à toute cette page : l’accélération matérielle fonctionne uniquement avec la build jellyfin-ffmpeg fournie. Si vous avez indiqué le chemin d’un FFmpeg système, l’accélération sera partielle ou inexistante.

Quels codecs votre génération de GPU peut décoder et encoder

Voici les limites documentées par Jellyfin pour NVENC et NVDEC. Le décodage et l’encodage sont deux capacités distinctes. Une carte peut prendre en charge l’une sans prendre en charge l’autre.

  • H.264 8 bits : tous les GPU NVIDIA équipés de NVENC et de NVDEC peuvent le décoder et l’encoder.
  • HEVC 8 bits : décodage et encodage pris en charge à partir de Maxwell de deuxième génération (GM206).
  • HEVC 10 bits : décodage pris en charge à partir de Maxwell de deuxième génération, mais encodage pris en charge uniquement à partir de Pascal.
  • AV1 : décodage pris en charge à partir d’Ampere, encodage pris en charge à partir d’Ada Lovelace.

La différence concernant le HEVC 10 bits est celle qui pose le plus souvent problème en pratique. Une carte de l’époque Maxwell décode votre fichier 4K HDR sur le GPU, puis ne peut pas encoder une sortie en 10 bits. Jellyfin encode donc en H.264 8 bits. La lecture fonctionne toujours, et c’est de toute façon le choix adapté à la plupart des clients. En 2026, l’encodage AV1 est rarement souhaitable, quelle que soit votre carte, car la prise en charge du décodage AV1 côté client reste limitée. De plus, un transcodage est justement nécessaire pour atteindre un client qui rencontrait déjà des difficultés.

Pourquoi le tone mapping recharge discrètement le GPU

Le tone mapping HDR (high dynamic range) vers SDR (standard dynamic range) est le réglage qui consomme votre budget GPU, pour une raison architecturale. Le décodage s’exécute sur NVDEC. L’encodage s’exécute sur NVENC. Le tone mapping ne s’exécute sur aucun des deux : c’est un filtre CUDA qui s’exécute sur les shader cores, la partie généraliste du GPU qui exécute les tâches de calcul. Un flux 4K HDR qui nécessite un tone mapping utilise donc le décodeur et l’encodeur, tout en chargeant les shaders.

Jellyfin indique que le tone mapping CUDA est disponible sur tous les GPU NVIDIA capables de décoder du HEVC 10-bit. La case à cocher apparaît donc et fonctionne sur des cartes qui ne peuvent pas le maintenir en 4K. Le symptôme est un flux qui démarre, passe en buffering, puis ne se stabilise jamais, tandis que nvidia-smi indique que l’encodeur est à peine sollicité.

C’est pourquoi il est utile de surveiller séparément la charge des shaders.

nvidia-smi dmon -s u

Cette commande affiche une ligne par seconde avec des colonnes distinctes pour sm, enc et dec. Des valeurs enc et dec faibles associées à une valeur sm élevée indiquent que les blocs à fonction fixe tournent au ralenti et que les shaders sont le goulot d’étranglement. Le tone mapping, le scaling ou l’incrustation des sous-titres est donc à l’origine de la charge. Le chemin CUDA gère également le profil 5 de Dolby Vision avec zero copy. C’est important, car sans zero copy, les images sont transférées vers la mémoire système, puis renvoyées entre les étapes de filtrage. Cet aller-retour consomme de la bande passante pour chaque image.

Ce que limite réellement le plafond de sessions NVENC des GPU grand public

ChartNVENC engines and concurrent encode session cap, NVIDIA published support matrix, August 2026
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
  }
]

Il s’agit des chiffres publiés par NVIDIA dans sa matrice en août 2026, et non de mesures effectuées ici. Une carte GeForce est limitée à 12 sessions d’encodage simultanées, quel que soit son modèle. Cette limite se trouve dans le pilote, et non dans le silicium. NVIDIA l’a relevée plusieurs fois au fil des ans. Consultez donc la matrice actuelle plutôt qu’un ancien sujet de forum. Le nombre de moteurs est le paramètre qui varie réellement selon la carte : la GeForce RTX 5090 possède 3 moteurs NVENC, tandis que la GeForce RTX 4060 en possède 1. Un nombre de moteurs plus élevé augmente le débit d’encodage parallèle, mais pas le nombre maximal de sessions.

La limite compte les sessions d’encodage. Elle concerne donc uniquement les flux transcodés. La lecture directe et le remuxing n’ouvrent aucune session d’encodage. Les cartes de data center, comme la L4, sont indiquées comme non limitées dans cette même matrice. Or les offres de GPU VPS fournissent généralement une carte de data center. Cette limite concerne donc surtout les serveurs personnels.

Lorsque vous l’atteignez, le transcodage échoue et le journal FFmpeg contient OpenEncodeSessionEx failed: out of memory (10). Le message mentionne la mémoire, mais un refus dû à la limite de sessions renvoie le même code. Vérifiez donc le nombre de flux simultanés avant de rechercher une fuite de VRAM. En pratique, la plupart des utilisateurs atteignent la limite du tone mapping ou celle de leur bande passante montante bien avant la douzième session.

Vérifiez que le GPU effectue le transcodage, sans vous fier à la configuration

Un paramètre enregistré ne constitue pas une preuve. Lisez un fichier dont vous savez qu’il force un transcodage, puis effectuez les trois vérifications suivantes.

  1. Ouvrez Dashboard, puis Playback. La session active doit indiquer Transcoding et préciser la cause. Si elle indique Direct playing, aucun transcodage n’est effectué et vous testez le mauvais fichier.
  2. Ouvrez Dashboard, puis Logs, et ouvrez le fichier journal FFmpeg.Transcode le plus récent. Un transcodage matériel affiche -hwaccel cuda et -hwaccel_output_format cuda sur la ligne de commande, avec h264_nvenc ou hevc_nvenc comme encodeur. Si libx264 apparaît, le transcodage est effectué par le CPU, quelles que soient les indications de la page de configuration.
  3. Exécutez nvidia-smi sur l’hôte pendant la lecture. Un processus provenant de /usr/lib/jellyfin-ffmpeg/ffmpeg doit apparaître avec de la mémoire GPU allouée, et nvidia-smi dmon -s u doit afficher des valeurs non nulles dans les colonnes enc et dec.

Effectuez cette troisième vérification sur l’hôte, et non dans le conteneur. nvidia-smi exécuté dans un conteneur affiche généralement une liste de processus vide, car il ne peut pas voir les PID situés en dehors de son propre namespace, alors que les valeurs d’utilisation restent correctes. Une liste de processus vide dans le conteneur n’indique pas une erreur.

Quand le service revient au logiciel sans vous le signaler

Jellyfin privilégie la continuité de la lecture. Lorsqu’une voie matérielle est indisponible, il bascule vers le logiciel au lieu d’interrompre le flux. Le signal fiable est donc la charge CPU et le journal FFmpeg, pas une bannière d’erreur.

Cannot load libnvcuvid.so.1 dans le journal de transcodage signifie que la bibliothèque de décodage n’a jamais été montée dans le conteneur. Définissez NVIDIA_DRIVER_CAPABILITIES=all, puis recréez le conteneur, car une modification de l’environnement nécessite docker compose up -d pour le reconstruire. Un simple redémarrage conserve les anciens paramètres.

No capable devices found provenant de h264_nvenc signifie que FFmpeg a atteint la bibliothèque d’encodage, mais n’a trouvé aucune carte utilisable. Vérifiez de nouveau docker compose exec jellyfin nvidia-smi, car cela signifie généralement que la réservation du périphérique a été supprimée ou que le conteneur a été recréé à partir d’un fichier obsolète.

Une charge CPU élevée avec un GPU peu sollicité indique que le décodage échoue silencieusement. Désélectionnez les codecs que votre génération ne peut pas décoder, puis relancez le même fichier et consultez de nouveau le journal FFmpeg pour vérifier si -hwaccel cuda apparaît.

Un transcodage qui démarre puis se bloque en 4K HDR alors que le 1080p fonctionne correctement indique une limite du tone mapping, et non une installation défectueuse. Confirmez-le avec la colonne sm de nvidia-smi dmon -s u, puis réduisez la résolution demandée par le client ou réservez les fichiers 4K HDR aux clients capables de les lire directement.

FAQ

Pourquoi Jellyfin utilise-t-il encore le CPU après l’activation de NVENC ?

Consultez le journal FFmpeg.Transcode le plus récent dans Dashboard, puis Logs. S’il contient libx264, aucun chemin matériel n’a été utilisé. Cela signifie généralement que le conteneur ne voit pas le GPU. Exécutez donc docker compose exec jellyfin nvidia-smi pour le confirmer. S’il contient h264_nvenc mais que le CPU reste fortement sollicité, le décodage s’effectue en logiciel. Cela se produit lorsque vous avez activé un codec que votre carte ne peut pas décoder, ou lorsque Enable hardware encoding est resté désactivé : seule la moitié du pipeline a alors été déplacée vers le GPU.

La ligne runtime: nvidia est-elle encore nécessaire dans Docker Compose ?

Non, si vous avez le bloc deploy.resources.reservations.devices et une version récente de Docker Compose. Ce bloc utilise la syntaxe moderne de demande de périphérique et remplit le même rôle. runtime: nvidia correspond à l’ancienne méthode, issue de l’époque nvidia-docker2. Elle fonctionne toujours, et l’exemple publié par Jellyfin conserve les deux méthodes. Les conserver toutes les deux ne pose aucun problème. Si vous conservez uniquement runtime: nvidia, vous devez également conserver NVIDIA_VISIBLE_DEVICES=all, car cette méthode ne contient aucune demande de périphérique à interpréter et récupère la liste des périphériques depuis l’environnement.

Combien de flux un même GPU NVIDIA peut-il transcoder simultanément ?

La matrice publiée par NVIDIA limite les cartes GeForce à douze sessions d’encodage simultanées en août 2026. Les cartes pour data centers y sont indiquées comme non limitées. Cette limite est rarement le facteur bloquant. Le tone mapping HDR vers SDR s’exécute sur les cœurs shader, et non sur NVENC. Quelques flux 4K HDR suffisent donc à saturer les shaders bien avant que le compteur de sessions n’atteigne sa limite. Mesurez votre cas avec nvidia-smi dmon -s u et surveillez la colonne sm, pas le nombre de sessions.

Puis-je utiliser le transcodage matériel sur un VPS sans GPU ?

Non. L’encodage nécessite le bloc NVENC physique, et lspci -nn | grep -Ei "3d|display|vga" n’affiche sur un VPS standard qu’un adaptateur d’affichage virtuel fourni par l’hyperviseur. Sur une offre sans GPU, la solution réaliste consiste à supprimer les transcodages : augmentez le réglage de qualité du client à Auto, utilisez une application cliente native plutôt qu’un navigateur, et convertissez les pistes de sous-titres sous forme d’image en texte afin qu’elles ne forcent pas un réencodage vidéo.

Pourquoi la lecture 4K HDR saccade-t-elle alors que le transcodage 1080p fonctionne correctement ?

Les deux charges utilisent des composants différents de la carte. Un transcodage 1080p SDR utilise uniquement le décodage et l’encodage, tous deux pris en charge par le matériel à fonction fixe. Un flux 4K HDR ajoute un tone mapping, qui est un filtre CUDA exécuté sur les cœurs shader, ainsi qu’une image beaucoup plus grande à redimensionner. La sortie de nvidia-smi dmon -s u, avec des valeurs enc et dec faibles à côté d’une valeur sm élevée, le confirme : les blocs à fonction fixe sont inactifs et les cœurs généralistes constituent la limite.