Для начала рассмотрим режимы управления битрейтом применительно к x264/x265/vpx.
Что такое "управление битрейтом" (rate control)? Это решения и действия кодера относительно того, сколько битов нужно выделить на данный кадр. Цель кодирования видео "с потерями" заключается в том, чтобы сэкономить как можно больше битов, уменьшив размер файла относительно оригинала и сохранив при этом как можно более высокое качество. Режимы управления битрейтом могут принимать различные формы: 1- и 2-проходное кодирование, “CBR” и “VBR”, быть может, вы слышали о “VBV” или “CRF”.
Почему это должно вас интересовать? Довольно часто вы видите примеры команд для кодирования видео, в которых применяется неправильный режим управления битрейтом или задаются неправильные битрейты. Этот пост представляет собой краткое руководство по различным режимам; в каких случаях лучше использовать тот или иной режим.
Переменный битрейт (VBR) против постоянного (CBR)
Многие из тех, кто еще помнит времена mp3, знакомы со способами управления битрейтом в аудиокодеках. Чтобы сделать рип компакт-диска, некоторое время использовался CBR, чуть позже появился VBR. Переменный битрейт гарантировал, что вы достигнете наименьшего возможного размера файла при максимально возможном качестве при заданных ограничениях (в соответствии с уровнем качества VBR).
Проще говоря, VBR позволяет кодеру использовать больше битов для материала, который сложно кодировать, и экономить биты в тех частях файла, которые кодировать легко. Что такое сложно и легко с точки зрения сжатия? Например, сцены, где много движения, требуют большего количества битов для кодирования, поскольку разница между соседними видеокадрами будет больше. Большие объекты с мелкими деталями и сложные текстуры также трудно кодировать.
Ваши намерения
Выбор режима управления битрейтом зависит от того, для чего вы кодируете файл:
1. Для архива. Вы хотите сжать файл для его хранения в своем архиве, например, на внешнем жестком диске или в вашем сетевом хранилище. Файл должен иметь максимально возможное качество при минимально возможном размере файла, но вам не важен точный размер.
2. Потоковая передача. Вы хотите передавать файл через Интернет, используя типичные решения для потокового видео по требованию (VoD), такие как HTTP progressive download или HTTP Adaptive Streaming. Вы должны быть уверены, что битрейт в файле не превышает определенной величины.
3. Прямая трансляция в реальном времени -- как и п.2, но нужно, чтобы кодирование выполнялось как можно быстрее.
4. Кодирование для устройств. Вы хотите поместить свой файл на DVD, Blu-ray и т.д. Вам надо получить файл определенного размера.
Примечание: такие кодеры, как x264, по умолчанию не заполняют кадры излишними битами. Это означает, что если у вас есть сцена, которую очень легко кодировать, ваш битрейт может оказаться ниже, чем тот, который вы указали. Не беспокойтесь об этом - просто имейте в виду, что нет смысла добиваться точного целевого битрейта, если он избыточен.
Постоянный параметр квантования (CQP)
Параметр квантования регулирует степень сжатия для каждого макроблока в кадре. Высокие значения означают более грубое квантование, большее сжатие и более низкое качество. Нижние значения означают противоположное. QP варьируется от 0 до 51 в H.264, и вы можете легко установить фиксированный QP для всего процесса кодирования с x264 и x265:
ffmpeg -i <input> -c:v libx264 -qp 23 <output>
ffmpeg -i <input> -c:v libx265 -x265-params qp=23 <output>
Если вы не знаете, что делаете, не используйте этот режим! Установка фиксированного QP означает, что результирующий битрейт будет жестко зависеть от сложности сцены, и входное видео будет кодироваться неэффективно. Вы можете зря потратить место и вы не контролируете фактический битрейт.
Хорош для: Исследования кодирования видео
Плохой выбор для: Почти всего остального
Средний битрейт (ABR)
Здесь мы задаем кодеру целевой битрейт и надеемся, что он сам решит, как достичь этого битрейта:
ffmpeg -i <input> -c:v libx264 -b:v 1M <output>
ffmpeg -i <input> -c:v libx265 -b:v 1M <output>
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M <output>
Избегайте использования этого режима! Один из главных разработчиков x264 говорит, что вы никогда не должны его использовать. Почему? Поскольку кодер не знает точно, что его ждет впереди, ему придется угадывать, как обеспечить этот средний битрейт. Это означает, что текущий битрейт будет сильно меняться, особенно в начале клипа, пока в какой-то момент не достигнет целевого. Особенно для потоковой передачи типа HAS это приводит к огромным колебаниям качества на коротких сегментах.
Это не режим постоянного битрейта! В то время как ABR технически является режимом VBR, он не намного лучше, чем указание постоянного битрейта (в смысле качества сжатия).
Хорошо подходит для: быстрого и грязного кодирования
Плохо для: почти всего
Постоянный битрейт (CBR)
Если это требуется в вашем случае, вы можете заставить кодер всегда использовать определенный битрейт, включив опцию nal-hrd:
ffmpeg -i <input> -c:v libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 1M -minrate 1M -maxrate 1M -bufsize 2M <output>
Выходной файл должен быть формата .ts (MPEG-2 TS), поскольку мр4 не поддерживает наложение NAL. Обратите внимание, что этот режим будет загружать сеть, даже если ваш источник легко кодировать, но он гарантирует, что битрейт остается постоянным по всему потоку. Использование этого режима может иметь смысл в некоторых приложениях, но, скорее всего, вы захотите разрешить кодеру использовать более низкий битрейт, когда это возможно.
Хороший выбор для: Поддержания постоянного битрейта (duh); видеостримминга (например, Twitch)
Плохой выбор для: Архива; эффективного использования полосы пропускания
2-проходное кодирование со средним битрейтом (2-Pass ABR)
Выполняя два (или более) прохода, кодер получает возможность оценить, что его ждет впереди. Он может рассчитать затраты на кодирование кадра в первом проходе, а затем, во втором проходе, более эффективно использовать доступные биты. Это гарантирует, что качество вывода будет наилучшим при определенном ограничении скорости передачи.
Для x264:
ffmpeg -i <input> -c:v libx264 -b:v 1M -pass 1 -f mp4 /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 1M -pass 2 <output>.mp4
Для x265:
ffmpeg -i <input> -c:v libx264 -b:v 1M -x265-params pass=1 -f mp4 /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 1M -x265-params pass=2 <output>.mp4
Для vp9:
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -pass 1 -f webm /dev/null
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -pass 2 <output>.webm
Это самый простой способ кодирования файла для потоковой передачи. С двумя оговорками: вы не знаете, каково будет итоговое качество, поэтому, чтобы убедиться, что ваш битрейт действительно достаточно высок для отдельных сложных участков, вам нужно будет проделать некоторые тесты. Другим недостатком этого режима является то, что в битрейте могут быть локальные пики, то есть вы можете отправлять больше, чем может получить ваш клиент. Что касается выбора битрейта, YouTube дает рекомендации по характеристикам загружаемых файлов, но имейте в виду, что они оптимизированы для загрузки файлов с хорошим качеством, поэтому на практике вы также можете выбрать более низкие битрейты.
Хорошо для: Достижения определенного целевого битрейта; кодирования для устройств
Плохо: Если вам нужно быстрое кодирование (например, прямая потоковая трансляция)
Постоянное качество (CQ) / Постоянный коэффициент скорости (CRF)
CRF обеспечивает постоянное качество сжатия в процессе кодирования. Это штука, которую можно «установить и забыть» - просто укажите crf и пусть кодер сделает все остальное. По своему принципу работы CRF является более совершенным методом, чем CQP, и обеспечивает эффективность сжатия лучше него. [CRF позволяет задействовать адаптивное квантование, т. е. сэкономить битрейт за счёт качества, в то время как CQP гарантирует кодирование с постоянной степенью сжатия для всех кадров и раздувает размер файла, но с шикарным качеством. CRF же действует подобно двухпроходному кодированию, пытаясь распределить битрейт в зависимости от сложности сцены. В итоге, при одинаковом размере выходного файла, в целом crf будет выглядеть качественнее.]
ffmpeg -i <input> -c:v libx264 -crf 23 <output>
ffmpeg -i <input> -c:v libx265 -crf 28 <output>
ffmpeg -i <input> -c:v libvpx-vp9 -crf 30 -b:v 0 <output>
В H.264 и H.265 CRF находится в диапазоне от 0 до 51 (подобно QP). 23 - значение по умолчанию для x264, а 28 - значение по умолчанию для x265. При crf=18 (или 24 для x265) результат визуально воспринимается как полное соответствие оригиналу; все, что ниже, скорее всего, будет попросту раздувать размер файла. Значения ± 6 приведут примерно к уполовиненному или удвоенному первоначальному битрейту. Для VP9 CRF может быть от 0 до 63.
Единственным недостатком этого режима является то, что вы не можете сказать заранее, каким будет окончательный размер файла.
Заметьте, что 2-проходный режим и однопроходное CRF-кодирование с одинаковым итоговым битрейтом будут одинаковыми по качеству. Основное отличие состоит в том, что с двухпроходным режимом вы можете контролировать размер файла (если это требуется), тогда как при CRF вы просто указываете качество кодирования, которое хотите получить.
Хороший выбор для: Архива; достижения наилучшего качества
Плохо для: Потоковой передачи; получения файла с определенным битрейтом / размером
Кодирование с ограничением битрейта (VBV)
Video Buffering Verifier (VBV) обеспечивает ограничение битрейта, чтобы он не превысил определенного максимума. Это полезно для потоковой передачи, так как теперь вы можете быть уверены, что в течение определенного отрезка времени не будете отправлять битов больше, чем обещали. VBV может использоваться как с двухпроходным VBR (используйте его в обоих проходах), либо с CRF-кодированием -- его можно «добавить» к уже представленным режимам управления битрейтом.
Задействуйте VBV с параметрами -maxrate и -bufsize для установки максимального битрейта и размера буфера:
ffmpeg -i <input> -c:v libx264 -crf 23 -maxrate 1M -bufsize 2M <output>
ffmpeg -i <input> -c:v libx265 -crf 28 -x265-params vbv-maxrate=1000:vbv-bufsize=2000 <output>
VP9 имеет аналогичный режим, не называемый VBV, но идея та же:
ffmpeg -i <input> -c:v libvpx-vp9 -crf 30 -b:v 2M <output>
Примечание. Если вы кодируете для потоковой передачи в реальном времени и хотите ускорить процесс кодирования, для x264 и x265 можно добавить опции -tune zerolatency и -preset ultrafast. Они снижают качество, которое вы получаете при определенном битрейте (эффективность сжатия), но значительно ускоряют процесс. Для libvpx-vp9 можно установить -quality realtime и -speed.
Использование этого режима:
x264:
ffmpeg -i <input> -c:v libx264 -b:v 1M -maxrate 1M -bufsize 2M -pass 1 -f mp4 /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 1M -maxrate 1M -bufsize 2M -pass 2 <output>
x265:
ffmpeg -i <input> -c:v libx265 -b:v 1M -x265-params pass=1:vbv-maxrate=1000:vbv-bufsize=2000 -f mp4 /dev/null
ffmpeg -i <input> -c:v libx265 -b:v 1M -x265-params pass=2:vbv-maxrate=1000:vbv-bufsize=2000 <output>
VP9:
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -maxrate 1M -bufsize 2M -pass 1 -f webm /dev/null
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -maxrate 1M -bufsize 2M -pass 2 <output>
Примечание. Здесь также может использоваться однопроходный метод, который, согласно разработчику x264, часто бывает не хуже двух проходов, но он не будет сжимать видео так же эффективно.
Как определить размер буфера bufsize? Это зависит от того, какие колебания битрейта вы допускаете. Хорошим значением по умолчанию является размер буфера в два раза больше максимальной скорости, но допуски могут отличаться в зависимости от настроек потоковой передачи. Если вы хотите строже ограничить скорость вашего потока, попробуйте настроить bufsize на половину максимальной скорости или меньше.
Когда вы применяете кодирование VBV в CRF, хитрость заключается в том, чтобы найти значение CRF, которое в среднем выдает нужный максимальный битрейт, но не более. Если ваш результат все время пытается превысить максимальный битрейт, CRF, вероятно, был слишком низким. В этом случае кодер пытается израсходовать биты, которых у него нет. С другой стороны, если у вас высокий CRF, при котором битрейт не достигает максимального значения, вы можете снизить его, чтобы улучшить качество. Например, вы кодируете с CRF=18, но без VBV. Ваше видео выходит со средним битрейтом 3,0 Мбит/с. Но вы хотите, чтобы ваши настройки VBV ограничивали видео на 1,5 Мбит/с, поэтому вам нужно увеличить CRF до 24, чтобы получить только половину битрейта.
Хорошо для: потоковой передачи с ограничениями полосы пропускания; прямой трансляции (с CRF, 1 проход); потоковой передачи VoD (с целевым битрейтом, 2-проходный)
Плохо для: людей, которые хотят поиграть; архив
Использованы материалы:
Understanding Rate Control Modes (x264, x265, vpx)