Jellyfin com transcodificação NVIDIA no Docker
Configure NVENC e NVDEC no Jellyfin com Docker Compose, valide o acesso à GPU no contentor e confirme a transcodificação real usando nvidia-smi.
O que você está a configurar
A transcodificação de hardware do Jellyfin numa GPU NVIDIA tem 4 etapas, sempre pela mesma ordem. Apenas a última ocorre dentro do Jellyfin. O contentor não consegue ver uma GPU cujo controlador não tenha sido carregado pelo host. O Jellyfin não consegue usar uma GPU que o contentor não consiga ver. Siga esta ordem. Assim, cada falha terá um local claro para investigação.
- Instale o controlador NVIDIA no host e confirme a instalação com
nvidia-smi. - Instale o NVIDIA Container Toolkit para que o Docker possa disponibilizar uma GPU a um contentor.
- Reserve a GPU para o serviço Jellyfin em
docker-compose.ymle confirme depois que o contentor consegue vê-la. - Ative o NVENC e o NVDEC nas definições de reprodução do próprio Jellyfin e confirme que uma reprodução real os utiliza.
O NVENC (codificador NVIDIA) e o NVDEC (descodificador NVIDIA) são blocos de função fixa da placa. São circuitos separados dos núcleos de shaders que executam tarefas CUDA (compute unified device architecture). Esta separação é a razão principal para utilizar esta configuração: um fluxo que consome vários núcleos da CPU por software passa a consumir apenas uma pequena fração de um núcleo e um bloco de hardware dedicado da GPU.
A reprodução direta é melhor do que qualquer transcodificação, por isso verifique-a primeiro
Antes de configurar qualquer uma destas opções, descubra se está a transcodificar por uma razão que pode simplesmente remover. O Jellyfin transcodifica quando o cliente não consegue reproduzir o ficheiro no formato original. A razão pertence sempre a uma lista curta: o codec de vídeo, o codec de áudio, o formato do contentor, as legendas baseadas em imagens ou um limite de bitrate solicitado pelo cliente.
Abra o Dashboard, depois Playback, e monitorize uma sessão ativa enquanto algo é reproduzido. Uma sessão marcada como Direct playing envia o ficheiro sem alterações e consome praticamente CPU nenhuma. Uma sessão marcada como Transcoding mostra a razão escolhida pelo Jellyfin. Remova essa razão e a GPU nunca terá de ser utilizada.
Duas alterações eliminam a maioria das transcodificações. Defina a qualidade da aplicação cliente como Auto ou para o valor máximo, porque um cliente que solicita 4 Mbps força a recodificação de um ficheiro de 20 Mbps, independentemente do codec utilizado. Depois, use uma aplicação cliente nativa em vez de um separador do navegador, porque um navegador é o reprodutor mais limitado que tem e uma aplicação nativa no mesmo televisor reproduz diretamente, muitas vezes, o mesmo ficheiro.
As legendas baseadas em imagens são a exceção que nenhuma definição do cliente resolve. As legendas PGS de uma cópia de Blu-ray e as VOBSUB de uma cópia de DVD são imagens. Por isso, têm de ser desenhadas sobre o próprio vídeo, o que implica uma recodificação completa do fluxo de vídeo. As legendas de texto em SRT são enviadas para o cliente como uma faixa separada e não têm custo relevante. Quando possível, converter as faixas de legendas para texto é mais vantajoso do que instalar uma GPU. O restante da configuração no lado do servidor está descrito em guia para executar um servidor multimédia Jellyfin numa VPS.
A maioria dos planos VPS não tem GPU
Os planos VPS standard não incluem GPU. Execute isto no servidor antes de planear qualquer outra coisa.
lspci -nn | grep -Ei "3d|display|vga"Num VPS KVM típico, este comando apresenta um adaptador de vídeo virtual fornecido pelo hypervisor, ou não apresenta nada útil. Esse dispositivo não consegue codificar vídeo. Só existe uma GPU real quando o fornecedor faz passthrough de uma placa física para a sua instância ou lhe atribui uma parte dela. Esses planos têm preços ajustados a essa capacidade. Que cargas de trabalho justificam realmente pagar por um VPS com GPU explica quem deve ou não deve escolher essa opção.
Se não houver GPU, privilegie o direct play e considere a transcodificação por software uma exceção. Uma única transcodificação H.264 1080p por software exige muitos recursos, mas pode funcionar com alguns núcleos de CPU. Uma transcodificação 4K HDR por software com tone mapping não é algo que um VPS pequeno consiga concluir em tempo real. Por isso, o stream fica intermitente enquanto a CPU permanece a 100 percent.
Instalar o driver NVIDIA no host
O Jellyfin 10.11 documenta o driver NVIDIA 520.56.06 como requisito mínimo no Linux. O Ubuntu inclui um auxiliar que seleciona automaticamente um pacote compatível.
sudo ubuntu-drivers list --gpgpu
sudo ubuntu-drivers install --gpgpu
sudo reboot--gpgpu seleciona a variante headless do driver, adequada para um servidor multimédia porque não existe um ambiente de desktop no servidor. O comando de listagem apresenta as branches disponíveis. Pode fixar uma pelo nome, por exemplo sudo ubuntu-drivers install --gpgpu nvidia:570-server. Use uma branch que tenha sido efetivamente apresentada na lista, não a indicada aqui.
A variante de servidor nem sempre instala nvidia-smi. Instale o pacote de utilitários correspondente à branch escolhida, por exemplo sudo apt install nvidia-utils-570-server. Em seguida, verifique o driver.
nvidia-smiUm resultado correto apresenta uma tabela com as versões do driver e do CUDA no cabeçalho, a placa identificada pelo nome e uma lista de processos vazia. São comuns duas falhas neste ponto. nvidia-smi: command not found significa que falta o pacote de utilitários, não o driver. NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver significa que o módulo do kernel não está carregado. Numa instalação nova, isto quase sempre significa que o servidor ainda não foi reiniciado ou que o Secure Boot está a impedir o carregamento de um módulo não assinado. Confirme se o módulo está presente com lsmod | grep nvidia.
Instale o NVIDIA Container Toolkit
O driver permite que o host utilize a GPU. O Docker ainda não a disponibiliza num contentor, porque o contentor não tem os nós de dispositivo nem as bibliotecas do driver. O NVIDIA Container Toolkit injeta ambos no arranque do contentor. Estes são os comandos de instalação da NVIDIA para 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-toolkitInstalar o pacote não é suficiente, porque é necessário informar o Docker de que o runtime existe.
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart dockernvidia-ctk runtime configure escreve uma entrada de runtime nvidia em /etc/docker/daemon.json. O reinício é a etapa que muitas pessoas ignoram. Ignorá-la produz o erro mais comum de toda esta configuração. Teste a integração antes de configurar o Jellyfin.
sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smiIsto deve mostrar a mesma tabela apresentada pelo host. Se, em vez disso, falhar com um erro que indique que não foi possível selecionar um driver de dispositivo com capacidades de GPU, o daemon do Docker não conhece o runtime nvidia. Execute novamente o comando de configuração e reinicie o daemon.
Conceder a GPU ao container Jellyfin no Docker Compose
Esta é a forma moderna do Compose, de acordo com o exemplo publicado pelo 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]Inicie o serviço e consulte diretamente o container.
docker compose up -d
docker compose exec jellyfin nvidia-smiSe isso imprimir a tabela de drivers dentro do container, a GPU foi encaminhada corretamente e todos os problemas restantes estão nas definições do Jellyfin.
Quatro linhas desse ficheiro precisam de explicação. capabilities: [gpu] é exigido pelo próprio Compose. Se for omitido, o Compose recusa o serviço em vez de o iniciar sem uma GPU. NVIDIA_DRIVER_CAPABILITIES=all é importante porque o toolkit só monta as bibliotecas de vídeo no container quando a capacidade de vídeo é solicitada. A documentação do Jellyfin também lista esta variável como necessária para a imagem oficial. Sem ela, o CUDA funciona, mas o NVDEC não. O log de transcodificação regista Cannot load libnvcuvid.so.1. network_mode: host é usado no exemplo do próprio Jellyfin porque a descoberta automática de clientes na porta UDP 7359 não atravessa uma rede bridge.
user: 1000:1000 é a última. Não tem relação com a GPU. Define quais ficheiros o Jellyfin pode ler no volume montado para os media. Um valor incompatível aparece como uma biblioteca vazia, não como um erro de permissões. Como PUID e PGID associam um utilizador do container aos ficheiros no disco explica a numeração. É a mesma numeração que já definiu se executar a stack Sonarr e Radarr no Docker Compose ao lado desta.
Por que a maioria dos tutoriais ainda escreve runtime: nvidia
A forma mais antiga aparece em quase todos os guias que encontrará e não está errada. É uma questão histórica. O pacote nvidia-docker2 original registava um runtime OCI chamado nvidia, por isso a única forma de disponibilizar uma GPU num contentor era --runtime=nvidia com NVIDIA_VISIBLE_DEVICES. O Docker 19.03 adicionou a flag --gpus e uma API própria para pedidos de dispositivos. O Compose demorou mais tempo a acompanhar esta alteração. Quando o fez, o pedido de dispositivo foi introduzido em deploy.resources.reservations.devices, uma chave que a maioria das pessoas tinha aprendido a ignorar porque deploy costumava significar Docker Swarm.
O resultado é que ambas as formas funcionam atualmente, e o exemplo publicado do Jellyfin inclui as duas ao mesmo tempo. Manter runtime: nvidia não tem custos e faz com que o ficheiro funcione em versões mais antigas do Compose. Se mantiver apenas runtime: nvidia e remover o bloco deploy, terá de manter NVIDIA_VISIBLE_DEVICES=all, porque esse caminho legado lê a variável de ambiente para decidir que dispositivos deve injetar e não tem um pedido de dispositivo alternativo para consultar.
Ativar a transcodificação por hardware NVIDIA no Jellyfin
Até agora, nada indicou ao Jellyfin que deve usar a placa. Aceda a Dashboard, depois a Playback e, em seguida, a Transcoding. Defina Hardware acceleration como Nvidia NVENC. Ative Enable hardware encoding. Caso contrário, o Jellyfin descodifica na GPU e depois codifica na CPU. Esse é o estado intermédio confuso em que a GPU mostra atividade e a CPU continua sobrecarregada.
Ative enhanced NVDEC decoder. Esta opção alterna entre o caminho NVDEC atual e o caminho CUVID antigo. Deixe-a ativada. O tratamento de Dolby Vision precisa desta opção ativada para usar NVDEC.
Em Enable hardware decoding for, selecione apenas os codecs que a sua placa consegue realmente descodificar. Esta é a definição que costuma ser configurada incorretamente. Selecionar AV1 numa placa sem descodificador AV1 não gera uma mensagem de erro. O Jellyfin solicita a descodificação por hardware, não a obtém e recorre à descodificação por software. O resultado é uma utilização elevada da CPU e uma GPU quase inativa. Isto parece exatamente uma falha no passthrough.
Existe ainda uma restrição aplicável a toda a página: a aceleração por hardware só funciona com a compilação jellyfin-ffmpeg incluída. Se definiu o caminho do FFmpeg para um FFmpeg do sistema, terá aceleração parcial ou nenhuma aceleração.
Quais codecs a sua geração de GPU consegue descodificar e codificar
Estas são as limitações documentadas pelo Jellyfin para NVENC e NVDEC. A descodificação e a codificação são capacidades separadas, e uma placa pode ter uma sem ter a outra.
- H.264 8-bit: todas as GPUs NVIDIA com NVENC e NVDEC descodificam e codificam este formato.
- HEVC 8-bit: descodificação e codificação a partir da segunda geração do Maxwell (GM206) e versões posteriores.
- HEVC 10-bit: descodificação a partir da segunda geração do Maxwell e versões posteriores, mas codificação apenas a partir do Pascal e versões posteriores.
- AV1: descodificação a partir do Ampere e versões posteriores, codificação a partir do Ada Lovelace e versões posteriores.
A separação relativa ao HEVC 10-bit é a que causa problemas na prática. Uma placa da era Maxwell descodifica o seu ficheiro 4K HDR na GPU, mas não consegue codificar uma saída 10-bit. Por isso, o Jellyfin codifica H.264 8-bit. O resultado continua a ser reproduzido e é a escolha correta para a maioria dos clientes. A codificação AV1 raramente é o que pretende em 2026, independentemente da placa, porque o suporte para descodificação AV1 no cliente ainda é limitado e uma transcodificação é necessária para alcançar um cliente que já tinha dificuldades.
Por que o tone mapping volta a saturar a GPU silenciosamente
O tone mapping de HDR (high dynamic range) para SDR (standard dynamic range) é a configuração que consome a sua margem de GPU, e o motivo é arquitetural. A decodificação é executada no NVDEC. A codificação é executada no NVENC. O tone mapping não é executado por nenhum dos dois: é um filtro CUDA executado nos shader cores, a mesma parte de uso geral da GPU que executa tarefas de computação. Portanto, um fluxo 4K HDR que precisa de tone mapping utiliza o decoder e o encoder e, além disso, carrega os shaders.
A documentação do Jellyfin indica que o tone mapping CUDA está disponível em qualquer GPU NVIDIA capaz de decodificar HEVC 10-bit. Isso significa que a opção aparece e funciona em placas que não conseguem sustentá-la em 4K. O sintoma é um fluxo que inicia, entra em buffering e nunca estabiliza, enquanto nvidia-smi indica que o encoder está quase sem utilização.
Por isso, vale a pena monitorizar a carga dos shaders separadamente.
nvidia-smi dmon -s uEsse comando imprime uma linha por segundo, com colunas separadas para sm, enc e dec. Valores baixos de enc e dec junto de um valor alto de sm indicam que os blocos de função fixa estão subutilizados e que os shaders são o gargalo. Nesse caso, o custo vem do tone mapping, do scaling ou da sobreposição permanente de legendas. O caminho CUDA também trata o Dolby Vision profile 5 com zero copy. Isso é importante porque, sem zero copy, os frames são enviados para a memória do sistema e retornam entre as etapas de filtragem. Esse percurso de ida e volta consome largura de banda em cada frame.
O que o limite de sessões NVENC para consumidores realmente limita
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
}
]Estes são os valores publicados pela NVIDIA na matriz de agosto de 2026, não medições feitas aqui. Uma placa GeForce está limitada a 12 sessões de codificação simultâneas, independentemente do modelo. O limite está no driver, não no silício, e a NVIDIA já o aumentou várias vezes ao longo dos anos. Por isso, consulte a matriz atual em vez de uma discussão antiga num fórum. O número de engines é o aspeto que realmente varia entre placas: a GeForce RTX 5090 tem 3 engines NVENC, enquanto a GeForce RTX 4060 tem 1. Mais engines significam maior capacidade de codificação em paralelo, não um limite de sessões mais alto.
O limite conta sessões de codificação, portanto conta apenas streams transcodificados. O direct play e o remuxing nunca abrem uma sessão de codificação. As placas de data center, como a L4, aparecem como sem restrições na mesma matriz. Além disso, uma placa de data center é normalmente o que um plano de GPU VPS fornece. Por isso, este limite é sobretudo relevante em servidores domésticos.
Quando o limite é atingido, a transcodificação falha e o log do FFmpeg contém OpenEncodeSessionEx failed: out of memory (10). A mensagem menciona memória, mas uma recusa por limite de sessões devolve o mesmo código. Por isso, verifique o número de streams simultâneos antes de procurar uma fuga de VRAM. Na prática, a maioria dos utilizadores atinge o limite de tone mapping ou a largura de banda de upload muito antes da sessão 12.
Comprove que a GPU está a fazer a transcodificação; não confie na configuração
Uma configuração guardada não é uma prova. Reproduza um ficheiro que sabe que força uma transcodificação e faça três verificações.
- Abra Dashboard e, em seguida, Playback. A sessão ativa deve indicar Transcoding e apresentar o motivo. Se indicar Direct playing, nada está a ser transcodificado e está a testar o ficheiro errado.
- Abra Dashboard e, em seguida, Logs, e abra o log
FFmpeg.Transcodemais recente. Uma transcodificação por hardware apresenta-hwaccel cudae-hwaccel_output_format cudana linha de comandos, comh264_nvencouhevc_nvenccomo codificador. Selibx264aparecer nessa linha, a transcodificação está a ser feita por software, independentemente do que indicar a página de definições. - Execute
nvidia-smino host enquanto a reprodução continua. Deve aparecer um processo de/usr/lib/jellyfin-ffmpeg/ffmpegcom memória da GPU alocada, envidia-smi dmon -s udeve apresentar valores diferentes de zero nas colunas enc e dec.
Faça esta terceira verificação no host, não dentro do contentor. nvidia-smi dentro de um contentor normalmente apresenta uma lista de processos vazia, porque não consegue ver os IDs de processos fora do seu próprio namespace, embora os valores de utilização continuem a ser apresentados corretamente. Uma lista de processos vazia dentro do contentor não indica uma falha.
Quando recorre ao software sem o informar
O Jellyfin prefere continuar a reprodução. Quando um caminho de hardware não está disponível, passa para o processamento por software em vez de interromper o fluxo. Por isso, os sinais fiáveis são a carga da CPU e o log do FFmpeg, não uma mensagem de erro.
Cannot load libnvcuvid.so.1 no log de transcodificação significa que a biblioteca de descodificação nunca foi montada no contentor. Defina NVIDIA_DRIVER_CAPABILITIES=all e recrie o contentor, porque uma alteração de ambiente exige docker compose up -d para o reconstruir. Um simples reinício mantém as definições antigas.
No capable devices found de h264_nvenc significa que o FFmpeg chegou à biblioteca de codificação, mas não encontrou nenhuma placa utilizável. Verifique docker compose exec jellyfin nvidia-smi novamente, porque isto normalmente significa que a reserva do dispositivo foi removida ou que o contentor foi recriado a partir de um ficheiro desatualizado.
Uma utilização elevada da CPU com uma GPU inativa significa que o lado da descodificação está a falhar silenciosamente. Desmarque os codecs que a sua geração não consegue descodificar. Em seguida, reproduza o mesmo ficheiro e leia novamente o log do FFmpeg para verificar se -hwaccel cuda aparece.
Uma transcodificação que começa e depois bloqueia em 4K HDR, enquanto 1080p funciona, atingiu o limite do tone mapping. Não se trata de uma instalação danificada. Confirme-o com a coluna sm em nvidia-smi dmon -s u. Em seguida, reduza a resolução solicitada pelo cliente ou mantenha os ficheiros 4K HDR em clientes que consigam fazer direct play.
FAQ
Por que o Jellyfin continua a usar a CPU depois de ativar o NVENC?
Consulte o log mais recente de FFmpeg.Transcode em Dashboard e, depois, em Logs. Se mostrar libx264, não foi utilizado qualquer caminho de hardware, o que normalmente significa que o contentor não consegue aceder à GPU. Execute docker compose exec jellyfin nvidia-smi para confirmar. Se mostrar h264_nvenc mas a CPU continuar ocupada, a descodificação está a ser feita por software. Isto acontece quando selecionou um codec que a sua placa não consegue descodificar ou quando Enable hardware encoding ficou desativado, fazendo com que apenas metade do pipeline fosse transferida para a GPU.
Ainda preciso da linha runtime: nvidia no Docker Compose?
Não, se tiver o bloco deploy.resources.reservations.devices e uma versão atual do Docker Compose. Esse bloco é a forma moderna de solicitar dispositivos e executa a mesma função. runtime: nvidia é o método mais antigo, da época do nvidia-docker2. Continua a funcionar, e o exemplo publicado pelo próprio Jellyfin mantém ambos. Mantê-los não causa problemas. Se mantiver apenas runtime: nvidia, também terá de manter NVIDIA_VISIBLE_DEVICES=all, porque esse método não tem uma solicitação de dispositivo para consultar e obtém a lista de dispositivos a partir do ambiente.
Quantos streams uma GPU NVIDIA pode transcodificar em simultâneo?
A matriz publicada pela NVIDIA limita as placas GeForce a doze sessões de codificação simultâneas em agosto de 2026, enquanto as placas de data center são indicadas como sem limitações. Esse limite raramente é o fator que interrompe o processamento. O tone mapping de HDR para SDR é executado nos núcleos shader, e não no NVENC. Por isso, alguns streams 4K HDR podem esgotar os shaders muito antes de o contador de sessões ser relevante. Meça o seu caso com nvidia-smi dmon -s u e monitorize a coluna sm, não o número de sessões.
Posso utilizar transcodificação por hardware numa VPS sem GPU?
Não. A codificação precisa do bloco físico NVENC, e lspci -nn | grep -Ei "3d|display|vga" numa VPS comum mostra apenas um adaptador de vídeo virtual fornecido pelo hypervisor. Num plano sem GPU, a opção realista é eliminar as transcodificações. Aumente a definição de qualidade do cliente para Auto, use uma aplicação cliente nativa em vez de um browser e converta as faixas de legendas baseadas em imagens para texto, para que não forcem uma nova codificação de vídeo.
Por que razão o 4K HDR apresenta interrupções quando a transcodificação 1080p funciona corretamente?
As duas cargas de trabalho utilizam partes diferentes da placa. Uma transcodificação 1080p SDR usa apenas descodificação e codificação, ambas executadas em hardware de função fixa. Um stream 4K HDR adiciona tone mapping, que é um filtro CUDA executado nos núcleos shader, além de um frame muito maior para redimensionar. A saída de nvidia-smi dmon -s u, com enc e dec baixos junto de sm elevado, confirma esta situação. Esse padrão significa que os blocos de função fixa estão inativos e que o limite está nos núcleos de uso geral.