transcodificação de áudio e vídeo do Intel i5 Kaby Lake para VP9 e FLAC usando ffmpeg

1

Tenho cerca de 30 gigabytes de vídeo (principalmente MP4, alguns MKV e webm) 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 tamanho do vídeo. Eu uso ffmpeg no Linux com os argumentos ffmpeg -i input -c:v libvpx-vp9 -lossless 1 -c:a FLAC -preset veryslow output.mkv para transcodificar vídeos sem assistência de hardware. Recentemente, no entanto, um amigo meu adquiriu uma CPU Intel i5 Kaby Lake para o seu PC e ofereceu-se para transcodificar os vídeos para mim. De acordo com Wikipedia e seu referências as novas CPUs Kaby Lake suportam decodificação de hardware de todos os meus codecs de entrada e codificação de VP9 de 8 bits. Então eu tenho duas perguntas:

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

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

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

    
por Billy 31.03.2017 / 01:28

2 respostas

3

ATUALIZAÇÃO EM 3 DE AGOSTO DE 2017: De acordo com uma nova resposta do usuário 林正浩, o ffmpeg agora tem suporte para codificação do VP9 por meio do VAAPI. Eu 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 algum motivo, 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 através do repositório de código fonte do FFmpeg mostra que não é mesmo uma questão de ser desativado, o recurso ainda não foi implementado ainda. Mas se ele estiver disponível em algum momento no futuro, ele deverá ser utilizável de maneira semelhante aos outros codificadores QuickSync: um switch como -c:v vp9_qsv em vez de -c:v libvpx-vp9 deve fazer o trabalho.

O uso da linha de comando do FFmpeg é o mesmo em todas as plataformas, com a exceção notável de que usuários do Windows devem usar NUL em vez de /dev/null para a saí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ê quiser acelerar suas codificações, a coisa mais óbvia que deve tentar é definir um valor de velocidade de codificação com a opção -speed . Os valores recomendados são números de 0 a 4, com 0 sendo muito, muito lento (pense em -preset placebo em x264, mas pior), mas alta qualidade e 4 são rápidos e de baixa qualidade. O ffmpeg usa -speed 1 por padrão, o que é uma boa troca de velocidade por qualidade para codificação com perdas. No entanto, acabei de fazer um teste de codificação sem perda rápida com diferentes valores de velocidade e notei uma redução de 32% no tamanho do arquivo quando passava de -speed 1 para -speed 0 com codificação sem perdas. O tempo de codificação triplicou, portanto, se usar 0 vale a pena, depende de você. O arquivo produzido por -speed 4 foi apenas 1,1% maior que o produzido por -speed 1 , e foi codificado 43% mais rápido. Então, eu diria que, se você estiver sem perdas e -speed 0 estiver muito lento, é melhor usar -speed 4 .

Outro importante aumento de desempenho de codificação está ativando o multiencadeamento com a opção -threads ; A libvpx não usa automaticamente vários encadeamentos, portanto, isso deve ser definido manualmente pelo usuário. Você também deve definir o número de colunas de blocos com a opção -tile-columns . Essa opção faz com que a libvpx divida o vídeo em vários blocos e codifique esses blocos em paralelo para melhor multitarefa. Você pode encontrar números recomendados para a quantidade de colunas e segmentos de blocos na seção "Recomendações para ladrilhos e encadeamentos" do VP9 do Google guia de codificação . Como você pode ver, o número de encadeamentos usados sobe 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 enquanto codifica vídeo de resolução sub-HD. Se você codifica principalmente vídeos de baixa resolução, convém considerar a codificação de vários arquivos ao mesmo tempo.

No entanto, há mais uma outra maneira de acelerar a codificação do VP9: multi-threading em um único bloco de coluna que pode ser ativado com -row mt 1 . A partir de 4 de abril (2017, hello future people), não faz parte de uma versão lançada do libvpx, mas provavelmente estará no libvpx 1.6.2. Se você quiser experimentá-lo antes do próximo lançamento, você precisa compilar as versões git recentes do libvpx e do ffmpeg a partir do código-fonte. Apenas siga o guia de compilação do FFmpeg para sua distribuição, mas em vez de baixar e extrair um tarball de lançamento, faça git pull https://chromium.googlesource.com/webm/libvpx

Quanto ao veryslow predefinido, isso é usado apenas em x264 e x265. A libvpx usa a opção -speed e, além disso, as opções -quality best , -quality good ou -quality realtime para definir quanto tempo o codificador pode gastar codificando um quadro. O padrão é -quality good porque -quality best é tão lento que é inutilizável e -quality realtime deve ser usado para aplicativos de tempo crítico, como vídeo chamadas e livestreaming.

    
por 04.04.2017 / 09:43
4

A partir de hoje, é possível construir o FFmpeg com o VAAPI, que, nos sistemas suportados, permite codificar o VP9 na GPU integrada da Intel.

O novo codificador, quando o ffmpeg é compilado com o suporte do VAAPI , chama-se vp9_vaapi .

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

ffmpeg -hide-banner -h encoder=vp9_vaapi

Saída:

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 um hardware não suportado, diz Skylake?

Veja o exemplo 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 que estão ausentes nesta plataforma específica, como confirmado pela saída do 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 VLD (para decodificação de comprimento variável) para o perfil VP9 0 é o mais distante que o Skylake chega em termos de aceleração de hardware VP9.

Estes com bancos de testes do Kabylake, executam esses testes de codificação e reportam de volta: -)

    
por 26.06.2017 / 04:59