Estou tentando gravar minha tela sem perdas (ou com qualidade quase sem perdas) com aceleração de hardware em um 6700 XT com ffmpeg. Estou executando o Linux Mint com o 5.14.14-051414-generic
kernel.
Eu tentei:
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 2560x1440 -i :0 -r 60 -vf 'hwupload,scale_vaapi=format=nv12' -c:v h264_vaapi -qp 0 output.mp4
ffmpeg
diz que está gravando a 60 fps, mas a gravação está instável e ligeiramente descolorida. Presumo que o problema de cor seja do formato de cor nv12, mas rgb
ou rgb8
dá um erro.
Eu também tentei usar o kmsgrab:
ffmpeg -device /dev/dri/card0 -f kmsgrab -i - -vf 'hwmap=derive_device=vaapi,scale_vaapi=w=2560:h=1440:format=nv12' -c:v h264_vaapi -qp 0 output.mp4
Mas dá o erro:
[kmsgrab @ 0x558f001c8d80] Using plane 65 to locate framebuffers.
[kmsgrab @ 0x558f001c8d80] Failed to get framebuffer 127: Invalid argument.
pipe:: Invalid argument
O número depois Failed to get framebuffer
é geralmente 127
ou algo entre 134
até 136
.
Eu tenho esses comandosaqui.
Responder1
A codificação verdadeiramente sem perdas só pode ser feita em software, eu acho, mas com taxas de bits mais altas pode parecer boa o suficiente.
Além disso, o wiki do ffmpeg diz que VAAPI é compatível apenas parcialmente com GPUs AMD.
Mas suspeito que você esteja usando a GPU integrada da CPU de qualquer maneira, o que pode levar a problemas de desempenho:
Se você tiver vários dispositivos utilizáveis na mesma máquina (por exemplo, uma GPU integrada Intel e uma placa gráfica discreta AMD), eles poderão ser usados simultaneamente para decodificar diferentes fluxos:
ffmpeg -init_hw_device vaapi=intel:/dev/dri/renderD128 -init_hw_device vaapi=amd:/dev/dri/renderD129 -hwaccel vaapi -hwaccel_device intel -i ... -hwaccel vaapi -hwaccel_device amd -i ...
Você já verificou se há mais de um dispositivo de hardware disponível?
Tentarls /dev/dri/para ver quais dispositivos estão disponíveis.
Não importa se você usou o dispositivo certo ou não, o-qp 0provavelmente não funcionará como esperado, então tente com os comandos exatos fornecidos e veja se eles dão melhores resultados:
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 1920x1080 -i :0 -vf 'hwupload,scale_vaapi=format=nv12' -c:v h264_vaapi -qp 24 output.mp4
ou
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 1920x1080 -i :0 -vf 'format=nv12,hwupload' -c:v h264_vaapi -qp 24 output.mp4
Com apenas a resolução alterada, e se você encontrou outro dispositivo de hardware, você pode tentar alterar isso também.
Estaria interessado se você pudesse obter boa qualidade com taxas de bits/tamanho de arquivo razoáveis, então, por favor, deixe-me saber se você teve sucesso.
A propósito, o seguinte não está usando aceleração hw, mas codificação sem perdas, então você também pode tentar esta:https://trac.ffmpeg.org/wiki/Capture/Desktop#lossless-recording
Para acelerar o processo de codificação, você pode usar a codificação sem perdas e desativar as opções avançadas do codificador, por exemplo:
ffmpeg -video_size 1920x1080 -framerate 30 -f x11grab -i :0.0 -c:v libx264rgb -crf 0 -preset ultrafast -color_range 2 output.mkv
-crf 0 diz ao x264 para codificar no modo sem perdas; -preset ultrafast aconselha fazê-lo rapidamente. Observe o uso de libx264rgb em vez de libx264; o último faria uma conversão com perdas de RGB para yuv444p (yuv444p de 8 bits não é suficiente para preservar RGB de 8 bits, é necessário YCbCr de 10 bits). ...
O codificador deve ser rápido o suficiente na maioria dos hardwares modernos para gravar sem queda de quadros e até mesmo deixar espaço de CPU suficiente para outros aplicativos.
Se você for arquivar a gravação ou estiver preocupado com o tamanho do arquivo, codifique-o novamente sem perdas, mas com uma predefinição mais lenta. ...
Responder2
TL, DR: Acho que você encontrou principalmente bugs no ffmpeg e/ou outras partes da pilha que parecem estar corrigidas agora.
Seu primeiro comando:
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 2560x1440 -i :0 -r 60 -vf 'hwupload,scale_vaapi=format=nv12' -c:v h264_vaapi -qp 0 output.mp4
Funciona para mim, no Debian Bookworm com ffmpeg 5.1 (só mudei o tamanho para combinar com meu monitor), sem problema de cor e 60 fps, na mesma GPU (6700 XT). Então talvez houvesse (na época) um bug em algum lugar na sua versão do ffmpeg ou nos drivers VA-API ou algo assim.
Ele não usa a mais alta qualidade, -qp 0
pode estar fora da faixa suportada por este codificador e posteriormente ignorado, aparentemente ele volta para um valor padrão:
No quality level set; using default (20).
Valores tão baixos quanto -qp 1
parecem aceitos, podendo trazer qualidade suficiente para suas necessidades.
Em relação ao kmsgrab, observe que usá-lo requer execução como root ou ter o recurso CAP_SYS_ADMIN definido. Esta pode muito bem ser a causa do seu erro, e uma correção é definir a capacidade no ffmpeg:
setcap cap_sys_admin=ep /usr/bin/ffmpeg
Isso não é ideal para segurança e irá falhar quando o ffmpeg for atualizado, mas funciona, e sua linha de comando também funciona bem para mim.
Observe também que o uso do kmsgrab durante a gravação de áudio causou problemas de sincronização de áudio/vídeo até pelo menos o ffmpeg 5.1:
https://trac.ffmpeg.org/ticket/8377
Se você quiser usá-lo, provavelmente desejará atualizar para o ffmpeg 6, que na minha experiência corrigiu o último problema.
Responder3
Isso foi perguntado ontem e a resposta permanece a mesma: codecs de vídeo HW não suportam alteração do fator de quantização, ou seja, crf
e mais ainda, eles não suportam codificação sem perdas.
Dehttps://trac.ffmpeg.org/wiki/Hardware/VAAPI
Opções de mapeamento da libx264
Nenhum modo semelhante ao CRF é suportado atualmente. O único modo de qualidade constante é o CQP (parâmetro de quantização constante), que não possui adaptabilidade ao conteúdo da cena. No entanto, permite diferentes configurações de qualidade para diferentes tipos de quadros, para melhorar a compactação gastando menos bits em quadros B não referenciados - consulte as opções (i|b)_q(factor|offset). O modo CQP não pode ser combinado com uma taxa de bits ou tamanho de buffer máximo.