ffmpeg conversão de WebM para MP4 - como manter o tamanho do arquivo?

0

Estou tentando converter um arquivo WebM para MP4, usando os seguintes parâmetros:

ffmpeg -loglevel info -i 2017-05-01-122851.webm -c:v libx264 -preset slower -crf 20 -bf 2 -trellis 2 -cmp 2 -subcmp 2 -g 45 -c:a aac -strict experimental -ab 32k ../renamed-video/2017-05-01-122851.mp4

ffmpeg version 3.0.7-0ubuntu0.16.10.1 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 6.2.0 (Ubuntu 6.2.0-5ubuntu12) 20161005
  configuration: --prefix=/usr --extra-version=0ubuntu0.16.10.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librubberband --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-chromaprint --enable-libx264
  libavutil      55. 17.103 / 55. 17.103
  libavcodec     57. 24.102 / 57. 24.102
  libavformat    57. 25.100 / 57. 25.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 31.100 /  6. 31.100
  libavresample   3.  0.  0 /  3.  0.  0
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
  libpostproc    54.  0.100 / 54.  0.100
Input #0, matroska,webm, from '2017-05-01-122851.webm':
  Metadata:
    encoder         : GStreamer matroskamux version 1.8.3
    creation_time   : 2017-05-01 10:28:51
  Duration: 00:04:32.88, start: 0.000000, bitrate: 3160 kb/s
    Stream #0:0(eng): Video: vp8, yuv420p, 1280x720, SAR 1:1 DAR 16:9, 250 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      title           : Video
    Stream #0:1(eng): Audio: vorbis, 44100 Hz, mono, fltp (default)
    Metadata:
      title           : Audio
File '../renamed-video/2017-05-01-122851.mp4' already exists. Overwrite ? [y/N] y
[libx264 @ 0x55d5e57dde80] using SAR=1/1
[libx264 @ 0x55d5e57dde80] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2
[libx264 @ 0x55d5e57dde80] profile High, level 5.1
[libx264 @ 0x55d5e57dde80] 264 - core 148 r2699 a5e06b9 - H.264/MPEG-4 AVC codec - Copyleft 2003-2016 - http://www.videolan.org/x264.html - options: cabac=1 ref=8 deblock=1:0:0 analyse=0x3:0x133 me=umh subme=9 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=0 trellis=2 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=2 b_pyramid=2 b_adapt=2 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=45 keyint_min=4 scenecut=40 intra_refresh=0 rc_lookahead=45 rc=crf mbtree=1 crf=20.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to '../renamed-video/2017-05-01-122851.mp4':
  Metadata:
    encoder         : Lavf57.25.100
    Stream #0:0(eng): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], q=-1--1, 250 fps, 16k tbn, 250 tbc (default)
    Metadata:
      title           : Video
      encoder         : Lavc57.24.102 libx264
    Side data:
      unknown side data type 10 (24 bytes)
    Stream #0:1(eng): Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, mono, fltp, 32 kb/s (default)
    Metadata:
      title           : Audio
      encoder         : Lavc57.24.102 aac
Stream mapping:
  Stream #0:0 -> #0:0 (vp8 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (vorbis (native) -> aac (native))
Press [q] to stop, [?] for help
frame=  768 fps= 32 q=-1.0 Lsize=    2573kB time=00:00:03.20 bitrate=6576.7kbits/s dup=676 drop=0 speed=0.136x    

O problema é que o arquivo de saída é muito maior que o arquivo de origem. Como posso ajustar o tamanho para que os dois arquivos tenham o mesmo tamanho / definição? Além disso, vejo esse aviso, e não sei se tenho que ter medo dele:

unknown side data type 10 (24 bytes).

    
por liv913 02.07.2017 / 19:17

1 resposta

3

Com -crf , você não consegue atingir o mesmo tamanho. CRF significa "Fator de Taxa Constante" - é um valor sem unidade (ou seja, sem%, sem kb / s, ...) entre 0 (sem perda) e 51 (pior qualidade) (valor padrão para x264: 23). O objetivo do CRF é alcançar uma certa qualidade visual sem precisar definir taxas de bits. O Guia H.264 do FFmpeg afirma:

[...] a subjectively sane range is 18-28. Consider 18 to be visually lossless or nearly so: it should look the same [...] as the input but it isn't technically lossless. The range is exponential, so increasing the CRF value +6 is roughly half the bitrate while -6 is roughly twice the bitrate.

(Observe que diferentes codificadores podem ter diferentes faixas de valores de CRF: por exemplo, CRF padrão do x265 -value é 28 , que deve ser visualmente igual a 23 de x264.

É claro que você pode mexer com -crf até obter o tamanho de arquivo desejado, mas isso geralmente significa muito teste & erro.

Agora pode-se perguntar "mas se a qualidade for a mesma e x264 for um bom codificador, então por que o CRF não tornará o arquivo menor? "

A resposta para essa pergunta é fácil: o x264 (como praticamente todos os outros codificadores do mercado) não tem como detectar a eficiência do arquivo de entrada codificado. Pode saber que tem um ABR (Average Bit Rate) de 2 Mb / s, mas isso não diz nada sobre a qualidade. E se o seu arquivo de entrada foi codificado de forma insatisfatória (baixa taxa de bits e / ou configurações de codificador muito rápidas), então ele pode ter artefatos (blocos, ...). Você pode vê-los, mas o x264 não pode (realmente) fazê-lo [1] - portanto, ao declarar -crf , ele supõe que você deseja conservar todos os artefatos em seu novo arquivo na extensão seu valor (0-51) é capaz, o que leva a taxas de bits mais altas porque os artefatos (como o ruído) não são fáceis de prever.

[1] Imagine que é como ver uma parede de tijolos - enquanto você pode reconhecê-la assim por causa da cor vermelha dos tijolos em forma de quadrado e do argamassa cinza entre eles, tudo o que o codificador vê são vermelho e cinza pixels.

Assim, a maneira de obter um determinado tamanho de arquivo é via ABR , que é o -b:v -parameter no libx264 do FFmpeg. A ABR trabalha com taxas de bits variáveis (VBR), mas tenta alcançar uma taxa de bits média conforme especificado em todo o arquivo. Para fazer com que esse princípio funcione bem, deve-se usar dois passos para que o FFmpeg possa primeiro olhar para o arquivo, calcular as taxas de bits e depois codificá-lo em uma segunda etapa.

Se o seu objetivo é ter um arquivo resultante com o mesmo tamanho do arquivo de entrada, você pode Calcule sua taxa de bits dessa maneira :

(<FILESIZE_INPUT-FILE> [MiB] * 8192) / <DURATION_INPUT-FILE> [seconds] = ~XYZ [kBit/s total bitrate]
XYZ [kBit/s total bitrate] - <DESIRED_AUDIO_BITRATE> [kBit/s] = ___ [kBit/s video bitrate]

Anotações em [brackets] , valores para você preencher em <ANGLE_BRACKETS> e seu resultado como ___ linha de sublinhados.

Com a sintaxe resultante:

ffmpeg -y -i <INPUT-FILE-PATH> -c:v libx264 -b:v ___k -preset slower <OTHER_COMMANDS_LIKE_AUDIO> -pass 1 -f <OUTPUT-FILE-FORMAT> /dev/null && \
ffmpeg -y -i <INPUT-FILE-PATH> -c:v libx264 -b:v ___k -preset slower <OTHER_COMMANDS_LIKE_AUDIO> -pass 2 <OUTPUT-FILE-PATH>

Em x264, o CRF e o ABR são mutuamente exclusivos - você pode usar um ou outro, portanto, sua escolha com x264 sempre terá qualidade garantida x tamanho de arquivo garantido. Tanto quanto eu sei, outros codificadores ( como x265 ) pode usar uma combinação de ABR e CRF, para que você possa especificar uma taxa de bits e uma faixa de qualidade que o codificador tente alcançar. Mas você sempre pode ter apenas uma prioridade mais alta: qualidade visual ou tamanho do arquivo de destino (ou velocidade de codificação). Com muita experiência, pode-se atingir "o equilíbrio perfeito" para qualquer trabalho, mas ainda assim seria um compromisso.

Um último comentário sobre os parâmetros no ffmpeg:

Se você não precisa de parâmetros ( e há muitas ocasiões em que alguém precisaria deles ), não os especifique. -loglevel info é o padrão, então por que você especificou? O melhor que pode fazer é quebrar seu código se você tiver um erro de digitação (o mesmo vale para -trellis ). Além disso, libx264 faz um bom trabalho ao especificar GOPs, portanto, -g pode não ser necessário, a menos que você precise de um mecanismo específico de reprodução / ... (o mesmo vale para -cmp e -csubcmp ). p>

Os desenvolvedores de codificadores geralmente tentam facilitar o uso de seus produtos e, portanto, valores padrão na maioria das vezes são muito melhores do que digitar cegamente em parâmetros aleatórios que alguém na internet encontrou há 10 anos na primeira documentação disponível. .

Apesar de, claro, se você fez sua pesquisa e você tem a experiência (ou simplesmente quer experimentá-la), não há como eu impedir que você vá para o limite de caracteres do console de comando com ffmpeg!

    
por 02.07.2017 / 20:54