Transcodificação de vídeo e áudio do Intel i5 Kaby Lake, permitida por hardware, para VP9 e FLAC usando ffmpeg


1

Tenho cerca de 30 gigabytes de vídeo (principalmente MP4, alguns MKV e webm) que preciso transcodificar para VP9 de 8 bits com áudio FLAC (Free Lossless Audio Codec) em um contêiner MKV de vários codecs de entrada (áudio AAC; H264, VP8, H265 / HEVC e provavelmente alguns outros codecs de vídeo). No meu sistema mais poderoso, a transcodificação de vídeos de baixa resolução leva o dobro do tempo da duração do vídeo. Eu uso ffmpegno Linux com os argumentos ffmpeg -i input -c:v libvpx-vp9 -lossless 1 -c:a FLAC -preset veryslow output.mkvpara transcodificar vídeos sem assistência de hardware. Recentemente, no entanto, um amigo meu conseguiu uma CPU Intel i5 Kaby Lake para seu PC e se ofereceu para transcodificar os vídeos para mim. De acordo com a Wikipedia e suas referências, as novas CPUs Kaby Lake suportam decodificação de hardware de todos os meus codecs de entrada e codificação do VP9 de 8 bits. Então, eu tenho duas perguntas:

  1. Quais ffmpegargumentos meu amigo pode usar para transcodificar os vídeos para VP9 e o áudio para FLAC em um contêiner MKV? Eles funcionam com o Windows? Caso contrário, tudo bem, pois ele possui uma inicialização dupla do Windows 10-Linux.

  2. A veryslowpredefinição ainda é necessária para obter a melhor compactação?

Tentei encontrar a resposta para essa pergunta em outro lugar, mas só consegui encontrar exemplos para codificação de codecs como H264 e JPEG.

Respostas:


3

ATUALIZAÇÃO EM 3 DE AGOSTO DE 2017: De acordo com uma resposta mais recente do usuário f, o ffmpeg agora tem suporte para a codificação VP9 através do VAAPI. Ainda não tenho o hardware necessário para testar isso, então minha resposta será de ajuda limitada. Deixarei minha resposta original sobre como codificar o VP9 no software abaixo.


Por alguma razão, o FFmpeg não suporta a codificação VP9 no codificador de hardware QuickSync da Intel, mesmo que eles suportem H.264 e HEVC . Uma pesquisa no repositório de código-fonte do FFmpeg mostra que nem se trata de ser desativado, mas o recurso ainda não foi implementado. Mas se ele estiver disponível em algum momento no futuro, deverá ser utilizado de maneira semelhante aos outros codificadores QuickSync: um comutador como em -c:v vp9_qsvvez de -c:v libvpx-vp9deve fazer o trabalho.

O uso da linha de comando FFmpeg é o mesmo em todas as plataformas, com a exceção notável que conheço de usuários do Windows que precisam usar em NULvez de /dev/nullsaída durante a primeira passagem de uma codificação de 2 passagens. Mas como você está fazendo 1 passe e sem perdas, isso não deve afetá-lo.

Se você deseja acelerar seus códigos, a coisa mais óbvia que você deve tentar é definir um valor de velocidade de codificação com o -speedcomutador. Os valores recomendados são números de 0 a 4, com 0 sendo muito, muito lento (pense -preset placeboem x264, mas pior), mas com alta qualidade e 4 sendo rápidos, sendo de qualidade inferior. O ffmpeg usa -speed 1por padrão o que é uma boa opção de velocidade para qualidade para codificação com perdas. No entanto, fiz um teste rápido de codificação sem perdas com valores de velocidade diferentes e notei uma redução de 32% no tamanho do arquivo ao passar -speed 1para -speed 0a codificação sem perdas. O tempo de codificação triplicou, portanto, se usar 0 vale a pena, é com você. O arquivo produzido por -speed 4foi apenas 1,1% maior que o produzido por-speed 1no entanto, e foi codificado 43% mais rápido. Então, eu diria que se você estiver sem perdas e -speed 0for muito lento, poderá usar -speed 4.

Outro aumento importante no desempenho da codificação é ativar o multiencadeamento com o -threadsswitch; A libvpx não usa automaticamente vários threads, portanto, isso deve ser definido manualmente pelo usuário. Você também deve definir o número de colunas de bloco com a -tile-columnsopção Essa opção faz com que a libvpx divida o vídeo em vários blocos e codifique esses blocos em paralelo para melhor multiencadeamento. Você pode encontrar os números recomendados para a quantidade de colunas e segmentos de bloco na seção "Recomendações de lado a lado e de encadeamento" do guia de codificação VP9 do Google. Como você pode ver, o número de threads usados ​​aumenta com o número de blocos, o que significa que, dependendo do número de núcleos de CPU disponíveis, seu processador pode não estar totalmente saturado ao codificar vídeo com resolução sub HD. Se você codifica principalmente vídeos de baixa resolução, convém codificar vários arquivos ao mesmo tempo.

No entanto, existe ainda outra maneira de acelerar a codificação VP9: multiencadeamento em um único bloco de coluna que pode ser ativado com -row mt 1. A partir de 4 de abril de 2017, olá pessoal do futuro), não faz parte de uma versão lançada da libvpx, mas provavelmente estará na libvpx 1.6.2. Se você quiser experimentá-lo antes do próximo lançamento, precisará compilar versões recentes do libvpx e ffmpeg do git. Basta seguir o guia de compilação do FFmpeg para sua distribuição preferida, mas em vez de baixar e extrair um tarball de lançamento, faça o mesmo git pull https://chromium.googlesource.com/webm/libvpx.

Quanto à veryslowpredefinição, usada apenas em x264 e x265. A libvpx usa o -speedswitch e, adicionalmente -quality best, as opções ,, -quality goodou -quality realtimepara definir quanto tempo o codificador pode gastar codificando um quadro. O padrão é que, -quality goodpor -quality bestser tão lento, é inutilizável e -quality realtimedeve ser usado para aplicativos de tempo crítico, como chamadas de vídeo e transmissão ao vivo.


Excelente redação e bem-vindo ao Super Usuário!
slhck

Obrigado pela resposta. Quais argumentos do FFmpeg posso usar para codificar o VP9 com VA-API? Vi que a fonte FFmpeg tem um arquivo chamado 'vaapi_vp9.c'. Vou tentar o que você sugeriu acima para acelerar o processo.
Billy

A VA-API pode ser usada para fornecer codificação e decodificação acelerada por hardware e, neste caso, infelizmente é apenas decodificação. Um fato menos conhecido sobre o FFmpeg é que ele também possui a funcionalidade de reprodução de vídeo; O Google Chrome e a versão Linux do Firefox o utilizam para reproduzir vídeo e áudio. O FFmpeg binário prevê a reprodução é ffplay. (Além disso, eu corrigido um erro no meu comentário: os interruptores de qualidade são, na verdade -quality good, -quality realtimeetc, e não apenas -goodou -realtime.)
veikk0

Na verdade, eu retiro isso. Existem artigos de notícias que indicam que o suporte à codificação VP9 está presente na VA-API, mas não consigo encontrar nada definido e não posso me pedir para pesquisar o código-fonte no momento. Você provavelmente deveria dar uma olhada aqui e aqui . Eu começaria verificando se o FFmpeg foi construído com --enable-vaapie, se sim, executando ffmpeg -decoders | grep vaapie ffmpeg -h encoder=<encodername>. Eu tenho uma CPU AMD, então não posso testar isso sozinho.
veikk0

Ok obrigado. Vou investigar isso amanhã.
Billy

4

Atualmente, é possível criar o FFmpeg com o VAAPI, que, em sistemas suportados, permite codificar o VP9 na GPU integrada da Intel.

O novo codificador, quando o ffmpeg é compilado com o suporte VAAPI , é chamado vp9_vaapi.

Para ver as opções disponíveis para usar ao ajustar o codificador, execute:

ffmpeg -hide-banner -h encoder=vp9_vaapi

Resultado:

Encoder vp9_vaapi [VP9 (VAAPI)]:
    General capabilities: delay 
    Threading capabilities: none
    Supported pixel formats: vaapi_vld
vp9_vaapi AVOptions:
  -loop_filter_level <int>        E..V.... Loop filter level (from 0 to 63) (default 16)
  -loop_filter_sharpness <int>        E..V.... Loop filter sharpness (from 0 to 15) (default 4)

O que acontece quando você tenta fazer isso em hardware não suportado, diz Skylake?

Veja a amostra de saída abaixo:

[Parsed_format_0 @ 0x42cb500] compat: called with args=[nv12]
[Parsed_format_0 @ 0x42cb500] Setting 'pix_fmts' to value 'nv12'
[Parsed_scale_vaapi_2 @ 0x42cc300] Setting 'w' to value '1920'
[Parsed_scale_vaapi_2 @ 0x42cc300] Setting 'h' to value '1080'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'video_size' to value '3840x2026'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'pix_fmt' to value '0'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'time_base' to value '1/1000'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'pixel_aspect' to value '1/1'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'sws_param' to value 'flags=2'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'frame_rate' to value '24000/1001'
[graph 0 input from stream 0:0 @ 0x42cce00] w:3840 h:2026 pixfmt:yuv420p tb:1/1000 fr:24000/1001 sar:1/1 sws_param:flags=2
[format @ 0x42cba40] compat: called with args=[vaapi_vld]
[format @ 0x42cba40] Setting 'pix_fmts' to value 'vaapi_vld'
[auto_scaler_0 @ 0x42cd580] Setting 'flags' to value 'bicubic'
[auto_scaler_0 @ 0x42cd580] w:iw h:ih flags:'bicubic' interl:0
[Parsed_format_0 @ 0x42cb500] auto-inserting filter 'auto_scaler_0' between the filter 'graph 0 input from stream 0:0' and the filter 'Parsed_format_0'
[AVFilterGraph @ 0x42ca360] query_formats: 6 queried, 4 merged, 1 already done, 0 delayed
[auto_scaler_0 @ 0x42cd580] w:3840 h:2026 fmt:yuv420p sar:1/1 -> w:3840 h:2026 fmt:nv12 sar:1/1 flags:0x4
[hwupload @ 0x42cbcc0] Surface format is nv12.
[AVHWFramesContext @ 0x42ccbc0] Created surface 0x4000000.
[AVHWFramesContext @ 0x42ccbc0] Direct mapping possible.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000001.
[AVHWFramesContext @ 0x42c3e40] Direct mapping possible.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000002.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000003.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000004.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000005.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000006.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000007.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000008.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000009.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x400000a.
[vp9_vaapi @ 0x409da40] Encoding entrypoint not found (19 / 6).
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
[AVIOContext @ 0x40fdac0] Statistics: 0 seeks, 0 writeouts
[aac @ 0x40fcb00] Qavg: -nan
[AVIOContext @ 0x409f820] Statistics: 32768 bytes read, 0 seeks
Conversion failed!

Os bits interessantes são os avisos de ponto de entrada para a codificação VP9 ausentes nesta plataforma específica, conforme confirmado pela saída de vainfo:

libva info: VA-API version 0.40.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/local/lib/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_0_40
libva info: va_openDriver() returns 0
vainfo: VA-API version: 0.40 (libva 1.7.3)
vainfo: Driver version: Intel i965 driver for Intel(R) Skylake - 1.8.4.pre1 (glk-alpha-71-gc3110dc)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Simple            : VAEntrypointEncSlice
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointEncSliceLP
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointEncSliceLP
      VAProfileH264MultiviewHigh      : VAEntrypointVLD
      VAProfileH264MultiviewHigh      : VAEntrypointEncSlice
      VAProfileH264StereoHigh         : VAEntrypointVLD
      VAProfileH264StereoHigh         : VAEntrypointEncSlice
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointEncPicture
      VAProfileVP8Version0_3          : VAEntrypointVLD
      VAProfileVP8Version0_3          : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileVP9Profile0            : VAEntrypointVLD

O ponto de entrada do VLD (para decodificação de comprimento variável) do perfil VP9 0 é o mais longe que a Skylake chega em termos de aceleração de hardware do VP9.

Estes com bancos de ensaio Kabylake, executam esses testes de codificação e relatam :-)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.