SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor

Jellyfin: NVIDIA-транскодування в Docker

Налаштуйте NVIDIA GPU для Jellyfin через Docker Compose, увімкніть NVENC і NVDEC та перевірте реальне транскодування командою nvidia-smi.

Що ви налаштовуєте

Апаратне транскодування Jellyfin на GPU NVIDIA складається з чотирьох кроків у фіксованому порядку. Лише останній крок виконується в самому Jellyfin. Контейнер не бачить GPU, якщо драйвер на хості не завантажено. Jellyfin не може використовувати GPU, якого не бачить контейнер. Виконуйте кроки в такому порядку — тоді для кожної помилки буде очевидне місце перевірки.

  1. Встановіть драйвер NVIDIA на хості та підтвердьте його роботу за допомогою nvidia-smi.
  2. Встановіть NVIDIA Container Toolkit, щоб Docker міг передати GPU контейнеру.
  3. Зарезервуйте GPU для сервісу Jellyfin у docker-compose.yml, а потім перевірте, чи бачить його контейнер.
  4. Увімкніть NVENC і NVDEC у власних налаштуваннях відтворення Jellyfin, а потім перевірте, чи використовуються вони під час фактичного відтворення.

NVENC (кодер NVIDIA) і NVDEC (декодер NVIDIA) — це спеціалізовані апаратні блоки на відеокарті. Вони фізично відокремлені від shader cores, на яких виконуються завдання CUDA (compute unified device architecture). Саме тому це має сенс: потік, який під час програмної обробки завантажує кілька ядер CPU, використовує лише невелику частину одного ядра та окремий апаратний блок GPU.

Direct play випереджає будь-яке транскодування, тому спочатку перевірте саме його

Перш ніж налаштовувати будь-що з цього, з’ясуйте, чи є причина для транскодування, яку можна просто усунути. Jellyfin транскодує файл, коли клієнт не може відтворити його без змін. Причина завжди належить до короткого списку: відеокодек, аудіокодек, формат контейнера, субтитри на основі зображень або обмеження бітрейту, яке встановив клієнт.

Відкрийте Dashboard, потім Playback, і спостерігайте за активним сеансом під час відтворення. Сеанс зі статусом Direct playing передає файл без змін і майже не навантажує CPU. Сеанс зі статусом Transcoding показує причину, через яку Jellyfin вибрав транскодування. Усуньте цю причину — і GPU взагалі не доведеться запускати.

Дві зміни усувають більшість випадків транскодування. Встановіть якість у клієнтському застосунку на Auto або максимальне значення, оскільки запит клієнта на 4 Mbps змушує повторно кодувати файл із бітрейтом 20 Mbps незалежно від кодека. Потім використовуйте native client app замість вкладки браузера, оскільки браузер — найобмеженіший програвач, який у вас є, а native app на тому самому телевізорі часто зможе відтворити ідентичний файл у режимі Direct play.

Субтитри на основі зображень є винятком, який не усувається налаштуваннями клієнта. Субтитри PGS із Blu-ray rip і VOBSUB із DVD rip є зображеннями, тому їх потрібно накладати безпосередньо на відео. Це означає повне повторне кодування відеопотоку. Текстові субтитри у форматі SRT передаються клієнту як окрема доріжка й не створюють навантаження. Де можливо, конвертувати доріжки субтитрів у текст вигідніше, ніж купувати GPU. Інші серверні налаштування описано в посібнику із запуску медіасервера Jellyfin на VPS.

У більшості тарифів VPS взагалі немає GPU

Стандартні тарифи VPS не передбачають GPU. Виконайте цю команду на сервері, перш ніж планувати щось інше.

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

На типовому KVM VPS ця команда виводить віртуальний відеоадаптер від гіпервізора або не виводить нічого корисного. Такий пристрій не може кодувати відео. Фізичний GPU доступний лише тоді, коли провайдер передає фізичну відеокарту безпосередньо вашому інстансу або виділяє частину її ресурсів. Відповідні тарифи коштують дорожче. У розділі Які робочі навантаження справді виправдовують оплату VPS з GPU описано, кому GPU VPS потрібен, а кому — ні.

Якщо GPU немає, орієнтуйтеся на direct play і розглядайте програмне транскодування лише як винятковий випадок. Одне програмне транскодування 1080p H.264 створює значне навантаження, але кілька ядер CPU зазвичай можуть його обробити. Програмне транскодування 4K HDR із tone mapping не може виконуватися в реальному часі на невеликому VPS. Тому відтворення переривається, а завантаження CPU залишається на рівні 100 відсотків.

Встановлення драйвера NVIDIA на хості

Jellyfin 10.11 вказує мінімальну версію драйвера NVIDIA 520.56.06 для Linux. Ubuntu має допоміжну утиліту, яка підбирає відповідний пакет.

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

--gpgpu вибирає серверний варіант драйвера без графічного інтерфейсу. Саме він потрібен медіасерверу, оскільки на цьому хості немає робочого столу. Команда list виводить доступні гілки драйвера. Потрібну гілку можна зафіксувати за назвою, наприклад sudo ubuntu-drivers install --gpgpu nvidia:570-server. Використовуйте гілку, яку фактично вивела команда, а не ту, що наведена тут.

Серверний варіант не завжди встановлює nvidia-smi. Установіть відповідний пакет utils для вибраної гілки, наприклад sudo apt install nvidia-utils-570-server. Потім перевірте драйвер.

nvidia-smi

Якщо все працює, у заголовку таблиці буде вказано версії драйвера та CUDA, ваша відеокарта відобразиться за назвою, а список процесів буде порожнім. Тут часто виникають дві помилки. nvidia-smi: command not found означає, що пакет utils відсутній, а не що відсутній драйвер. NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver означає, що модуль ядра не завантажено. На щойно встановленій системі це майже завжди означає, що сервер ще не перезавантажено або Secure Boot не дозволяє завантажити непідписаний модуль. Перевірте наявність модуля за допомогою lsmod | grep nvidia.

Встановіть NVIDIA Container Toolkit

Драйвер дає змогу хосту використовувати GPU. Docker все одно не передаватиме його в контейнер, оскільки контейнер не має ні вузлів пристроїв, ні бібліотек драйвера. NVIDIA Container Toolkit додає обидва компоненти під час запуску контейнера. Нижче наведено власні команди NVIDIA для встановлення в Debian і 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

Встановити пакет недостатньо, оскільки Docker потрібно повідомити про наявність runtime.

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

nvidia-ctk runtime configure записує запис runtime nvidia у /etc/docker/daemon.json. Перезапуск — це крок, який часто пропускають. Його пропуск спричиняє найпоширенішу помилку в усій цій конфігурації. Перевірте взаємодію компонентів, перш ніж переходити до Jellyfin.

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

Ця команда має вивести ту саму таблицю, що й на хості. Якщо натомість з’являється помилка про неможливість вибрати драйвер пристрою з можливостями gpu, Docker daemon не знає про nvidia runtime. Знову виконайте команду налаштування та перезапустіть daemon.

Передайте GPU контейнеру Jellyfin у Docker Compose

Це сучасний синтаксис Compose, який відповідає прикладу, опублікованому 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]

Запустіть контейнер і виконайте перевірку безпосередньо в ньому.

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

Якщо команда виведе таблицю драйвера з контейнера, GPU передається правильно, а всі подальші проблеми пов’язані з налаштуваннями Jellyfin.

Чотири рядки в цьому файлі потребують пояснення. capabilities: [gpu] потрібен самому Compose. Якщо його не вказати, Compose відмовиться запускати сервіс, а не запустить його без GPU. NVIDIA_DRIVER_CAPABILITIES=all важливий, оскільки toolkit монтує відеобібліотеки в контейнер лише тоді, коли запитано відеоможливість. У документації Jellyfin цю змінну також вказано як обов’язкову для офіційного образу. Без неї CUDA працює, а NVDEC — ні, і журнал транскодування містить Cannot load libnvcuvid.so.1. network_mode: host використовується у власному прикладі Jellyfin, оскільки автоматичне виявлення клієнтів через UDP-порт 7359 не працює через bridge network.

user: 1000:1000 — останній параметр, і він не пов’язаний із GPU. Він визначає, які файли Jellyfin може читати в змонтованому каталозі з медіафайлами. Якщо значення не відповідає власнику файлів, бібліотека буде порожньою, а не виникне помилка доступу. У статті Як PUID і PGID зіставляють користувача контейнера з файлами на диску пояснено цю нумерацію. Це та сама нумерація, яку ви вже налаштували, якщо запускаєте стек Sonarr і Radarr у Docker Compose поруч із цим контейнером.

Чому в більшості посібників досі вказують runtime: nvidia

Старий варіант є майже в кожному посібнику, який ви знайдете, і він не є неправильним. Це історична причина. Початковий пакет nvidia-docker2 реєстрував OCI runtime з назвою nvidia, тому єдиним способом додати GPU до контейнера були --runtime=nvidia і NVIDIA_VISIBLE_DEVICES. У Docker 19.03 з’явився прапорець --gpus і повноцінний API для запитів до пристроїв. Compose адаптувався пізніше. Коли це сталося, запит до пристрою розмістили в ключі deploy.resources.reservations.devices. Більшість користувачів звикли його ігнорувати, оскільки раніше deploy означав Docker Swarm.

У результаті сьогодні працюють обидва варіанти, а опублікований приклад для Jellyfin містить їх одночасно. Наявність runtime: nvidia нічого не коштує та забезпечує сумісність файлу зі старішими версіями Compose. Якщо залишити лише runtime: nvidia і видалити блок deploy, потрібно зберегти NVIDIA_VISIBLE_DEVICES=all. Цей застарілий спосіб використовує змінну середовища, щоб визначити, які пристрої потрібно додати до контейнера, і не має іншого запиту до пристрою, який можна було б прочитати.

Увімкнення апаратного транскодування NVIDIA у Jellyfin

Поки що Jellyfin не налаштовано на використання відеокарти. Відкрийте Dashboard, перейдіть до Playback, а потім Transcoding. Для параметра Hardware acceleration виберіть Nvidia NVENC. Увімкніть Enable hardware encoding. Інакше Jellyfin декодуватиме відео на GPU, а кодуватиме на CPU. Це заплутаний проміжний стан: GPU показує активність, але CPU усе одно працює з високим навантаженням.

Увімкніть Enable enhanced NVDEC decoder. Цей параметр перемикає між поточним шляхом NVDEC і старішим шляхом CUVID. Залиште його увімкненим. Для обробки Dolby Vision цей параметр потрібен, щоб узагалі використовувати NVDEC.

У розділі Enable hardware decoding for виберіть лише ті кодеки, які ваша відеокарта справді може декодувати. Саме цей параметр часто налаштовують неправильно. Якщо вибрати AV1 на відеокарті без декодера AV1, повідомлення про помилку не з’явиться. Jellyfin запитує апаратне декодування, не отримує його й переходить до програмного декодування. У результаті CPU має високе навантаження, а GPU майже простоює. Це виглядає так, ніби passthrough взагалі не працює.

Для всієї цієї сторінки діє ще одне обмеження: апаратне прискорення працює лише з комплектною збіркою jellyfin-ffmpeg. Якщо вказати шлях до системного FFmpeg, апаратне прискорення працюватиме частково або не працюватиме взагалі.

Які кодеки може декодувати та кодувати ваше покоління GPU

Це обмеження, які Jellyfin документує для NVENC і NVDEC. Декодування та кодування — окремі можливості, тому відеокарта може підтримувати одну з них без підтримки іншої.

  • H.264 8-bit: кожен GPU NVIDIA із NVENC і NVDEC декодує та кодує цей формат.
  • HEVC 8-bit: декодування та кодування підтримуються починаючи з Maxwell другого покоління (GM206) і новіших.
  • HEVC 10-bit: декодування підтримується починаючи з Maxwell другого покоління і новіших, але кодування — лише з Pascal і новіших.
  • AV1: декодування підтримується з Ampere і новіших, а кодування — з Ada Lovelace і новіших.

Саме відмінність для HEVC 10-bit найчастіше створює проблеми на практиці. Відеокарта покоління Maxwell декодує файл 4K HDR на GPU, але не може кодувати 10-bit вихідний потік, тому Jellyfin кодує його в 8-bit H.264. Такий потік усе одно відтворюється, і для більшості клієнтів це правильний вибір. Кодування AV1 у 2026 році рідко виправдане незалежно від відеокарти, оскільки підтримка декодування AV1 на стороні клієнта все ще обмежена, а транскодування потрібне саме для клієнта, який і без того мав проблеми з відтворенням.

Чому tone mapping непомітно знову створює навантаження на GPU

Tone mapping із HDR (high dynamic range) у SDR (standard dynamic range) — це налаштування, яке непомітно вичерпує ваш бюджет GPU. Причина полягає в архітектурі. Декодування виконується на NVDEC. Кодування виконується на NVENC. Tone mapping не використовує жоден із них: це фільтр CUDA, який працює на shader cores — тій самій універсальній частині GPU, що виконує обчислювальні задачі. Тому потік 4K HDR, якому потрібен tone mapping, використовує декодер і кодер та додатково навантажує shader cores.

Jellyfin документує CUDA tone mapping як доступний на кожному GPU NVIDIA, який може декодувати HEVC 10-bit. Це означає, що прапорець відображається та працює на картах, які не здатні стабільно обробляти його в 4K. Ознака проблеми — потік запускається, буферизується й не переходить у стабільний стан, тоді як nvidia-smi показує мінімальне навантаження на кодер.

Тому навантаження на shader cores варто контролювати окремо.

nvidia-smi dmon -s u

Команда виводить один рядок на секунду з окремими стовпцями для sm, enc і dec. Низькі enc і dec за високого значення sm означають, що блоки з фіксованими функціями працюють із запасом, а вузьким місцем є shader cores. Отже, саме tone mapping, масштабування або вбудовування субтитрів створює навантаження. Шлях CUDA також обробляє Dolby Vision profile 5 без копіювання даних, що важливо: без zero copy кадри під час переходів між етапами фільтрації передаються до системної пам’яті й назад, а кожен такий обхід споживає пропускну здатність для кожного кадру.

Що насправді обмежує ліміт сесій NVENC для споживчих відеокарт

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
  }
]

Це опубліковані NVIDIA дані з матриці станом на August 2026, а не результати вимірювань, виконаних тут. Для будь-якої моделі GeForce встановлено обмеження 12 одночасних сесій кодування. Обмеження задається драйвером, а не апаратною частиною GPU. NVIDIA вже кілька разів змінювала його протягом років, тому перевіряйте актуальну матрицю, а не старе повідомлення на форумі. Кількість engine — це параметр, який справді залежить від відеокарти: GeForce RTX 5090 має 3 engine NVENC, а GeForce RTX 40601. Більша кількість engine збільшує пропускну здатність паралельного кодування, але не підвищує максимальну кількість сесій.

Обмеження поширюється на сесії кодування, тому воно враховує лише потоки транскодування. Direct play і remuxing не відкривають сесію кодування. У тій самій матриці карти для центрів обробки даних, наприклад L4, зазначені як такі, що не мають цього обмеження. Саме карту для центрів обробки даних зазвичай надає тариф GPU VPS, тому це обмеження переважно стосується домашніх серверів.

Якщо ліміт досягнуто, транскодування завершується помилкою, а журнал FFmpeg містить OpenEncodeSessionEx failed: out of memory (10). У повідомленні згадується пам’ять, але відмова через ліміт сесій повертає той самий код. Тому спочатку перевірте кількість одночасних потоків, перш ніж шукати витік VRAM. На практиці більшість користувачів стикається з обмеженням tone mapping або пропускною здатністю upload задовго до дванадцятої сесії.

Доведіть, що GPU виконує транскодування, а не покладайтеся на конфігурацію

Збережене налаштування не є доказом. Відтворіть файл, який гарантовано запускає транскодування, а потім виконайте три перевірки.

  1. Відкрийте Dashboard, а потім Playback. В активному сеансі має бути зазначено Transcoding і вказано причину. Якщо зазначено Direct playing, транскодування не виконується, і ви перевіряєте неправильний файл.
  2. Відкрийте Dashboard, а потім Logs, і відкрийте найновіший журнал FFmpeg.Transcode. Апаратне транскодування містить -hwaccel cuda і -hwaccel_output_format cuda у командному рядку, а h264_nvenc або hevc_nvenc — як encoder. Якщо там є libx264, транскодування виконується програмно, незалежно від того, що показує сторінка налаштувань.
  3. Виконайте nvidia-smi на хості, поки відтворення триває. Має з’явитися процес із /usr/lib/jellyfin-ffmpeg/ffmpeg із виділеною пам’яттю GPU, а nvidia-smi dmon -s u має показати ненульові значення у стовпцях enc і dec.

Третю перевірку виконуйте на хості, а не всередині контейнера. nvidia-smi усередині контейнера зазвичай показує порожній список процесів, оскільки контейнер не бачить ідентифікатори процесів за межами власного простору імен, тоді як значення використання ресурсів залишаються коректними. Порожній список процесів усередині контейнера не є помилкою.

Коли система непомітно переходить на програмне оброблення

Jellyfin намагається не переривати відтворення. Якщо апаратний шлях недоступний, він переходить на програмне оброблення, а не завершує потокову передачу з помилкою. Тому надійними ознаками є завантаження CPU і журнал FFmpeg, а не банер помилки.

Cannot load libnvcuvid.so.1 у журналі транскодування означає, що бібліотеку декодера не було змонтовано в контейнер. Задайте NVIDIA_DRIVER_CAPABILITIES=all і створіть контейнер повторно, оскільки для застосування зміни середовища потрібно виконати docker compose up -d. Звичайний перезапуск зберігає старі параметри.

No capable devices found з h264_nvenc означає, що FFmpeg досяг бібліотеки кодека, але не знайшов придатну відеокарту. Ще раз перевірте docker compose exec jellyfin nvidia-smi, оскільки зазвичай це означає, що резервування пристрою було скасовано або контейнер створили повторно зі застарілого файлу.

Високе завантаження CPU за низької активності GPU означає, що декодування завершується помилкою без явного повідомлення. Зніміть вибір із кодеків, які не підтримує ваше покоління обладнання, потім знову відтворіть той самий файл і перечитайте журнал FFmpeg, щоб перевірити, чи з’являється -hwaccel cuda.

Якщо транскодування запускається, а потім зупиняється для 4K HDR, тоді як 1080p працює нормально, це обмеження тонального відображення, а не помилка інсталяції. Підтвердьте це за стовпцем sm у nvidia-smi dmon -s u, після чого зменште запитану клієнтом роздільну здатність або залиште файли 4K HDR на клієнтах, які можуть відтворювати їх напряму.

FAQ

Чому Jellyfin продовжує використовувати CPU після ввімкнення NVENC?

Перевірте найновіший журнал FFmpeg.Transcode у розділах Dashboard і Logs. Якщо в ньому зазначено libx264, апаратний шлях взагалі не використовувався. Зазвичай це означає, що контейнер не бачить GPU, тому виконайте docker compose exec jellyfin nvidia-smi для перевірки. Якщо зазначено h264_nvenc, але CPU усе ще завантажений, декодування виконується програмно. Це трапляється, якщо вибрано кодек, який ваша відеокарта не може декодувати, або якщо параметр Enable hardware encoding залишився вимкненим і на GPU перенесено лише половину конвеєра.

Чи потрібен рядок runtime: nvidia у Docker Compose?

Ні, якщо у вас є блок deploy.resources.reservations.devices і актуальна версія Docker Compose. Цей блок є сучасною формою запиту пристрою та виконує ту саму функцію. runtime: nvidia — старіший спосіб часів nvidia-docker2. Він досі працює, а у власному опублікованому прикладі Jellyfin наведено обидва варіанти. Наявність обох варіантів не створює проблем. Якщо залишити лише runtime: nvidia, потрібно також залишити NVIDIA_VISIBLE_DEVICES=all, оскільки цей спосіб не містить запиту пристрою та отримує список пристроїв із середовища.

Скільки потоків одна NVIDIA GPU може транскодувати одночасно?

Згідно з опублікованою NVIDIA матрицею, станом на August 2026 для карт GeForce встановлено обмеження у twelve одночасних сеансів кодування, а карти для центрів обробки даних зазначено як необмежені. Це обмеження рідко стає вузьким місцем. Перетворення HDR у SDR виконується на shader cores, а не на NVENC, тому кілька потоків 4K HDR вичерпають ресурси shader cores задовго до досягнення ліміту сеансів. Перевірте власний сценарій за допомогою nvidia-smi dmon -s u і стежте за стовпцем sm, а не за кількістю сеансів.

Чи можна використовувати апаратне транскодування на VPS без GPU?

Ні. Для кодування потрібен фізичний блок NVENC, а lspci -nn | grep -Ei "3d|display|vga" на стандартному VPS показує лише віртуальний відеоадаптер від hypervisor. Реалістичний варіант для тарифного плану без GPU — усунути потребу в транскодуванні: підвищити параметр якості клієнта до Auto, використовувати native client app замість браузера та перетворити текстові доріжки субтитрів на зображення, щоб вони не змушували повторно кодувати відео.

Чому 4K HDR відтворюється ривками, хоча 1080p транскодується без проблем?

Ці два робочі навантаження використовують різні частини відеокарти. Транскодування 1080p SDR включає лише декодування та кодування, які виконуються на апаратних блоках із фіксованою функцією. Потік 4K HDR додає tone mapping — фільтр CUDA, що працює на shader cores, — а також значно більший кадр для масштабування. nvidia-smi dmon -s u із низькими значеннями enc і dec та високим sm підтверджує це, оскільки така картина означає, що блоки з фіксованою функцією простоюють, а обмеженням є універсальні обчислювальні ядра.