Я пытаюсь преобразовать файл WebM в MP4, используя следующие параметры:

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    

Проблема в том, что выходной файл намного больше исходного. Как настроить размер так, чтобы два файла имели одинаковый размер / определение? Более того, я вижу это предупреждение и не знаю, нужно ли мне его бояться:

неизвестный тип данных стороны 10 (24 байта).

1 ответ1

3

С -crf вы не можете достичь того же размера. CRF означает "Коэффициент постоянной скорости" - это значение без единицы (то есть без%, без кбит / с, ...) между 0 (без потерь) и 51 (худшее качество) (значение по умолчанию для x264: 23). Целью CRF является достижение определенного визуального качества без определения скорости передачи. Руководство FFmpeg по H.264 гласит:

[...] субъективно вменяемый диапазон составляет 18-28. Считайте, что 18 визуально без потерь или почти так: он должен выглядеть [...] как входные данные, но не технически без потерь. Диапазон экспоненциальный, поэтому увеличение значения CRF +6 составляет примерно половину битрейта, в то время как -6 примерно вдвое больше битрейта.

(Обратите внимание, что разные кодировщики могут иметь разные диапазоны значений CRF: например, значение CRF по умолчанию для x265 равно 28, что должно быть визуально равно 23 для x264).

Конечно, вы можете возиться с -crf пока не получите желаемый размер файла, но это обычно означает много проб и ошибок.


Теперь можно спросить: «Но если качество такое же, а x264 считается хорошим кодировщиком, то почему CRF не сделает файл меньше?"

Ответ на этот вопрос прост: x264 (как и практически любой другой кодер на рынке) не может определить, насколько эффективно был закодирован входной файл. Возможно, он знает, что он имеет ABR (среднюю скорость передачи данных) 2 Мбит / с, но это ничего не говорит о качестве. И если ваш входной файл был плохо закодирован (низкий битрейт и / или очень быстрые настройки кодировщика), то он может иметь артефакты (блоки, ...). Вы можете видеть их, но x264 не может (действительно) сделать это [1] - поэтому, указав -crf , он предполагает, что вы хотите сохранить все артефакты в вашем новом файле в той степени, в которой это значение (0-51) в состоянии, что затем приводит к более высокой скорости передачи данных, потому что артефакты (например, шум) не легко предсказать.

[1] Представьте, что вы видите кирпичную стену - хотя вы можете распознать ее как таковую из-за красного цвета кирпичей квадратной формы и серого раствора между ними, все кодировщик видит красные и серые пиксели.


Таким образом, способ достижения определенного размера файла - через ABR, который является параметром -b:v в libx264 FFmpeg. ABR работает с переменными битрейтами (VBR), но пытается достичь средней битрейта, как указано для всего файла. Чтобы этот принцип работал хорошо, нужно использовать два прохода, чтобы FFmpeg мог сначала посмотреть на файл и вычислить битрейты, а затем кодировать его на втором шаге.

Если ваша цель - получить результирующий файл того же размера, что и входной файл, вы можете рассчитать свою скорость передачи данных следующим образом:

(<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]

Аннотации в [brackets] , значения для заполнения в <ANGLE_BRACKETS> и ваш результат в виде ___ строки подчеркивания.

С результирующим синтаксисом:

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>

В x264 CRF и ABR являются взаимоисключающими - вы можете использовать и то и другое, поэтому ваш выбор с x264 всегда будет с гарантированным качеством по сравнению с гарантированным размером файла. Насколько я знаю, другие кодеры (например, x265) могут использовать комбинацию ABR и CRF, поэтому вы можете указать скорость передачи и диапазон качества, которого кодировщик пытается достичь. Но у вас всегда может быть только один высший приоритет: либо визуальное качество, либо целевой размер файла (или скорость кодирования). Имея большой опыт, можно достичь "идеального баланса" для любой конкретной работы, но это все равно будет компромиссом.


Последний комментарий о параметрах в ffmpeg:

Если вам не нужны параметры (и во многих случаях они нужны), не указывайте их. -loglevel info является значением по умолчанию, так почему бы вы его указали? Лучшее, что он может сделать - это сломать ваш код, если в нем есть опечатка (то же самое относится и к -trellis). Кроме того, libx264 хорошо справляется с заданием GOP, так что -g может не понадобиться, если вам не нужно это для определенного механизма воспроизведения /... (то же самое касается -cmp и -csubcmp).

Разработчики кодировщиков обычно стараются упростить использование своих продуктов, и поэтому значения по умолчанию в большинстве случаев гораздо лучше, чем вслепую вводить случайные параметры, которые кто-то в Интернете нашел 10 лет назад в первой доступной документации.

Хотя, конечно, если вы провели свое исследование и у вас есть опыт (или вы просто хотите испытать его), я бы ни за что не захотел помешать вам перейти к ограничению символов командной консоли с помощью ffmpeg!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .