Intel Quick Sync (VAAPI) num VPS Linux: comandos ffmpeg que funcionam
O Intel Quick Sync é o motor de vídeo das GPU Intel. Em Linux, o ffmpeg
controla-o através do VAAPI (h264_vaapi, hevc_vaapi, scale_vaapi…).
Esta página é uma cábula de comandos que usamos numa Intel UHD 770; os
comandos de codificação, transcodificação e AV1 são os do nosso
teste de carga da GPU partilhada,
onde correram durante 20 minutos sem uma única falha.
Nas nossas VM, o ffmpeg e os controladores VAAPI vêm pré-instalados e a GPU é o
render node /dev/dri/renderD128. Noutra máquina, ajuste o caminho do
dispositivo.
O que a UHD 770 faz por hardware
| Codec | Descodificação | Codificação |
|---|---|---|
| H.264 | sim | sim (h264_vaapi) |
| HEVC 8 bits e 10 bits | sim | sim (hevc_vaapi, -profile:v main10 para 10 bits) |
| VP9 | sim | sim |
| AV1 | sim | não: só descodificação |
1. Verificar o dispositivo
ls -l /dev/dri/ # renderD128 deve aparecer
vainfo --display drm --device /dev/dri/renderD128
Na saída do vainfo, cada linha associa um perfil a um entrypoint:
VAEntrypointVLD: descodificação por hardware;VAEntrypointEncSlice: codificação clássica por hardware;VAEntrypointEncSliceLP: codificação low-power (-low_power 1no ffmpeg).
Para AV1 (VAProfileAV1Profile0) só verá VAEntrypointVLD: descodificação, sem
codificação.
Se o vainfo falhar com um erro de permissões como utilizador normal,
adicione-se ao grupo render e volte a iniciar sessão:
sudo usermod -aG render "$USER"
2. Testar sem ficheiro de vídeo
O ffmpeg consegue gerar um padrão de teste, útil para confirmar que a codificação funciona antes de mexer em ficheiros reais:
ffmpeg -vaapi_device /dev/dri/renderD128 \
-f lavfi -i testsrc2=size=1920x1080:rate=30 -t 60 \
-vf format=nv12,hwupload -c:v h264_vaapi -b:v 8M -f null -
-f null - descarta a saída: mede apenas o codificador. Sem -nostats, o
ffmpeg mostra speed=…x durante a execução; acima de 1x significa mais
depressa do que o tempo real.
3. Codificação H.264 por hardware
A entrada é descodificada na CPU, as imagens são enviadas para a GPU
(hwupload) e depois codificadas pelo Quick Sync:
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 \
-vf 'format=nv12,hwupload' \
-c:v h264_vaapi -b:v 8M -c:a copy output.mp4
Modo low-power, um bloco de codificação separado na GPU:
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 \
-vf 'format=nv12,hwupload' \
-c:v h264_vaapi -low_power 1 -b:v 8M -c:a copy output.mp4
Os dois modos funcionam nas nossas VM. Se um deles der erro noutra máquina,
verifique se o vainfo lista o entrypoint correspondente (EncSlice ou
EncSliceLP).
4. Codificação HEVC (H.265) por hardware
O mesmo esquema, com outro codificador:
# clássico
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 \
-vf 'format=nv12,hwupload' -c:v hevc_vaapi -b:v 6M -c:a copy output.mkv
# low power
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 \
-vf 'format=nv12,hwupload' -c:v hevc_vaapi -low_power 1 -b:v 6M -c:a copy output.mkv
5. HEVC 10 bits (Main10)
O 10 bits usa o formato de píxel p010 e o perfil main10:
ffmpeg -vaapi_device /dev/dri/renderD128 -i input-10bit.mkv \
-vf 'format=p010,hwupload' \
-c:v hevc_vaapi -profile:v main10 -b:v 20M -c:a copy output-main10.mkv
O comando que usámos para criar um ficheiro de teste 4K Main10 (30 s, 40 Mbit/s):
ffmpeg -vaapi_device /dev/dri/renderD128 \
-f lavfi -i testsrc2=size=3840x2160:rate=30 -t 30 \
-vf format=p010,hwupload -c:v hevc_vaapi -profile:v main10 -b:v 40M -y src.mkv
6. Transcodificação inteiramente na GPU (o que fazem o Plex e o Jellyfin)
Descodificar, redimensionar e codificar, tudo na GPU: as imagens nunca voltam à memória do sistema, por isso a CPU fica quase parada.
ffmpeg -vaapi_device /dev/dri/renderD128 \
-hwaccel vaapi -hwaccel_output_format vaapi -i movie-4k.mkv \
-vf 'scale_vaapi=w=1920:h=1080:format=nv12' \
-c:v h264_vaapi -b:v 8M -c:a copy movie-1080p.mkv
-hwaccel vaapi -hwaccel_output_format vaapi: descodifica na GPU e mantém lá as imagens;scale_vaapi=…:format=nv12: redimensiona na GPU e converte de 10 para 8 bits, porque a saída H.264 é de 8 bits;- acrescente
-low_power 1depois deh264_vaapipara usar o codificador low-power.
No nosso teste de carga, este mesmo pipeline (HEVC 4K 10 bits → H.264 1080p) correu a cerca de 1,3× o tempo real por servidor com a GPU partilhada saturada. Com a GPU livre e o codificador low-power, o nosso guia Jellyfin e Plex mediu 12× o tempo real numa transcodificação 4K HDR → 1080p.
7. AV1: descodificação por hardware, saída HEVC ou H.264
A UHD 770 descodifica AV1 mas não tem codificador AV1: o av1_vaapi não
funciona nesta GPU. Descodifique o AV1 na GPU e volte a codificar em HEVC ou
H.264:
ffmpeg -vaapi_device /dev/dri/renderD128 \
-hwaccel vaapi -hwaccel_output_format vaapi -i input-av1.mkv \
-vf scale_vaapi=w=1920:h=1080 -c:v hevc_vaapi -b:v 6M -c:a copy output-hevc.mkv
Se precisar de saída AV1, codifique-a na CPU (por exemplo com libsvtav1), que
foi como criámos o nosso ficheiro de teste AV1:
ffmpeg -f lavfi -i testsrc2=size=3840x2160:rate=30 -t 10 \
-c:v libsvtav1 -preset 12 -y src.mkv
Para medir só a velocidade de descodificação, envie as imagens para o muxer null:
ffmpeg -vaapi_device /dev/dri/renderD128 \
-hwaccel vaapi -hwaccel_output_format vaapi -i input-av1.mkv -f null -
8. Dentro do Docker
Passe o render node e o respetivo grupo ao contentor:
docker run --rm -it \
--device /dev/dri/renderD128 \
--group-add "$(stat -c %g /dev/dri/renderD128)" \
-v "$PWD":/work -w /work \
your-ffmpeg-image ffmpeg -vaapi_device /dev/dri/renderD128 ...
A imagem precisa do seu próprio controlador VAAPI (Intel media driver) e de um ffmpeg compilado com VAAPI.
9. Confirmar que a GPU está mesmo a trabalhar
- O
nvtopfunciona dentro das nossas VM: carga da GPU para a VM e por processo. - O
intel_gpu_topnão funciona na GPU virtual de uma VM: depende dos contadores PMU do i915, que não são expostos à VM. Só funciona no anfitrião físico. - O
gpu-check(pré-instalado nas nossas VM) testa VAAPI, Vulkan, OpenCL e OpenVINO num só comando. - Depois de uma tarefa pesada, procure erros de GPU no log do kernel:
journalctl -k -b | grep -iE "gpu hang|context reset|reset.*engine|guc.*fail"
Uma saída vazia significa que não foi registado nenhum hang desde o arranque.
Erros frequentes
| Sintoma | Causa provável |
|---|---|
vainfo ou ffmpeg: permission denied em /dev/dri/renderD128 | utilizador fora do grupo render (ou contentor arrancado sem --group-add) |
Impossible to convert between the formats | as imagens estão na memória do sistema mas o codificador espera imagens na GPU: acrescente hwupload (com -vaapi_device) |
| CPU elevada durante uma transcodificação “GPU” | falta -hwaccel_output_format vaapi, ou há um filtro de CPU (scale, em vez de scale_vaapi) na cadeia |
| A codificação AV1 falha | é normal: a UHD 770 não tem codificador AV1 |
Artigos relacionados
- Intel UHD 770 partilhada em carga máxima: teste de stress GPU de 20 minutos
- Transcodificação de vídeo acelerada: não precisa de uma GPU de 500 €/mês
- Benchmarks UHD 770 vs HD Graphics 530
Experimente
Uma VM Linux com uma Intel UHD 770 lá dentro, alojada na Alemanha: ffmpeg,
VAAPI, OpenCL e nvtop pré-instalados, SSH root, IPv6 dedicado.
Planos a partir de 14,99 € s/ IVA/mês, preço fixo.