webm encoding - pituz/webm-thread GitHub Wiki

Основным (и в большинстве случаев достаточным) инструментом конвертирования видео в формат webm является ffmpeg. Здесь рассматриваются его параметры при использовании кодеков формата WebM.

Формат WebM позволяет использовать следующие форматы видео и аудио:

  • Видео:
    • VP8: устаревший формат, с выходом VP9 остался нужен только в тех случаях, когда важна скорость и наплевать на эффективность сжатия;
    • VP9 (-c:v libvpx-vp9, либо -c:v vp9, для WebM используется по умолчанию): основной формат для пиления WebM'ок; работает значительно медленнее, но сжимает в 1.5-2 раза лучше;
    • AV1 (-c:v libsvtav1, либо не рекомендуемые -c:v libaom-av1 или -c:v librav1e): лучший по качеству формат из числа поддерживаемых WebM на данный момент. Играется всеми современными браузерами. Из перечисленных энкодеров хорошую производительность имеет только SVT-AV1, остальные вы просто не дождётесь. Так как энкодер относительно новый, не всякий билд ffmpeg содержит его, и даже при наличии версия может быть старой и медленной. Рекомендуем скачать последний билд отсюда (ищите архивы с суффиксом -gpl.tar.xz).
  • Аудио:
    • Vorbis (-c:a libvorbis): хороший формат для аудио с высоким битрейтом (выше 128 кбит/с), но проигрывающий opus'у на низких;
    • Opus (-c:a libopus, для webm по умолчанию): лучший формат для низких битрейтов.

Примеры кодирования WebM с использованием ffmpeg

Уровень порнотреда

Пожать фрагмент animu.mkv с 1:10 по 1:50 в VP9/Opus одним проходом:

ffmpeg -i animu.mkv -ss 1:10 -t 40 -b:v 0 -crf 30 out.webm

либо замените -t 40 на -to 1:50.

Ускорить можно одним из двух способов:

  • с увеличением размера файла, указав кодек vp8 (-c:v vp8 перед out.webm);
  • -c:v libsvtav1 с более высоким значением -preset (в районе 8-10); моар тут.

Сжатие двумя проходами с подсчётом битрейта под лимит

Допустим, нужно пожать amv.mp4 длиной 4 минуты и разрешением 1280x720 целиком, попав при этом в лимит 10240 KiB.

  1. Считаем битрейт по длине фрагмента: 10240KiB * 8bit / (4m * 60s) == 341kbit/s, вычитаем из него желаемый битрейт звука (допустим, 64kbit/s): 341 - 64 == 277kbit/s.
  2. Оцениваем визуально, влезет ли вообще в этот битрейт видео с приемлемым качеством, и если влезет, то с каким разрешением. Для видео с высокой динамикой и сменой сцен на каждом такте такой битрейт явно мал: для такого бывает надо полмегабита, а то и больше. Допустим, наше amv должно влезать с разрешением 960x540px.
  3. Первый проход сжатия видео: кодек определяет сжимаемость кадров видео, сохраняя информацию о ней в файле ffmpeg2pass-0.log в текущем каталоге.

ffmpeg -i amv.mp4 -map 0:v -vf scale=-1:540 -c:v vp9 -pass 1 -f null -

  1. Второй проход сжатия видео: при этом, собственно, и происходит сжатие.

ffmpeg -i amv.mp4 -map 0:v -vf scale=-1:540 -pass 2 -b:v 277k video.webm

во время сжатия можно смотреть готовые кадры плеером и принимать решение об остановке кодирования (клавиша q) и разбивке видео на два фрагмента (удваиваем битрейт, переделываем второй проход) или смене разрешения (придётся переделать также первый проход).

  1. Смотрим размер результата, считаем оставшийся битрейт для звука, жмём звук и муксим с видео:

ffmpeg -i amv.mp4 -i video.webm -map 0:a -b:a 64k -map 1:v -c:v copy out.webm

  1. Смотрим размер результата, если он вышел за лимит — переделываем пт. 5 с корректировкой битрейта.

  2. Постим webm и наблюдаем чёрное превью.

AV1

Начиная с билдов ffmpeg примерно середины-конца 2023, во всех выше перечисленных командах энкодер можно заменить на libsvtav1, получив заметно более высокое качество при прежнем размере.

Минимальный пример:

ffmpeg -i animu.mkv libsvtav1 -crf 38 -preset 6 out.webm`
  • -crf влияет на соотношение размер/качество — есть смысл использовать значения в диапазоне 38-50; чем ниже значение — тем выше качество результата и выше размер.
  • -preset 6 заставляет ffmpeg тратить чуть больше времени на энкод в обмен на заметное улучшение результата.

Разбор параметров кодеков

Видео

Контроль ширины потока

Ширина потока — это, другими словами, битрейт — количество информации, производимое кодеком за единицу времени дорожки.

Для контроля ширины потока у libvpx есть 4 основных параметра:

  • -crf, по умолчанию -1;
  • -b:v (устар. -vbitrate), по умолчанию 200k;
  • -qmin, по умолчанию -1;
  • -qmax, по умолчанию -1.

Они приведены в порядке повышения приоритета: значения -qmin/-qmax важнее всех и будут соблюдены в любом случае, даже если это приведёт к превышению указанного битрейта.

Параметры -crf, -qmin и -qmax управляют т.н. фактором квантизации — числом, которым указывается уровень снижения детализации картинки. Оно может принимать значения от 0 (потерь нет) и до 63. По умолчанию все эти параметры имеют значение -1, т.е. не используются. VP8 не может без потерь, его минимальный фактор квантизации — 4. Значение -crf должно находиться между -qmin и -qmax, иначе кодек откажется работать.

Грубо говоря, ширина потока для каждого кадра определяется по следующему алгоритму:

  1. считается битрейт для кадра с квантизацией по -crf;
  2. если битрейт превысил допустимый (указанный параметром -b:v), то уровень квантизации повышается так, чтобы битрейт остался в пределах лимита;
  3. если уровень квантизации вышел за пределы -qmin/-qmax, то он корректируется до ближайшей находящейся в допустимом диапазоне величины.

Битрейт здесь фигурирует не напрямую, а опосредованно: не использованный в одних кадрах битрейт может быть распределён на другие. Чтобы распределение битрейта происходило адекватно изменению динамики картинки, нужно жать её двумя проходами.

Управление соотношением скорость/качество

Для этого есть два параметра:

  • -deadline 0..over9000 (синоним: -quality) — допустимое кол-во микросекунд на кодирование одного кадра; специальные значения и константы:

    • 0 (best): без ограничений, максимальное качество;
    • 1 (realtime): завершить кодирование как можно быстрее;
    • 1000000 (good): 1 секунда, значение по умолчанию.

    При значениях больше единицы:

    • в однопроходном режиме опаздывающие кадры кодируются в режиме realtime, укладывающиеся в указанный лимит времени — по профилю -cpu-used;
    • в двухпроходном режиме всегда используется профиль -cpu-used.

Ещё.

  • -cpu-used 0..8 (синоним: -speed, по умолчанию 1) — профили энкодера для -quality good, от более ресурсоёмких и эффективных к менее, см. vp9/encoder/vp9_speed_features.c.

Звук

Opus

Тут всё элементарно: ставишь битрейт (-b:a, значения от 4k до 510k) и кодируешь, все дополнительные параметры по умолчанию имеют адекватные кодированию вебмок значения.

  • -frame_duration: длина кадра в миллисекундах, от 2.5 до 60, по умолчанию 20. Имеет смысл увеличивать на крайне низких битрейтах (ниже 24кбпс);
  • -application: профиль кодека (audio/voip/lowdelay), по умолчанию audio;
  • -vbr: переменный битрейт, по умолчанию включено.

Firefox имеет особенность зацикливать вебмки с Opus не с первого кадра, а с последнего ключевого. Для создания лупов лучше использовать Vorbis.

Vorbis

ffmpeg имеет две реализации энкодера vorbis'а: встроенную (-c:a vorbis) и через специализированную библиотеку libvorbis (-c:a libvorbis). Имеет смысл использовать только второй вариант.

У libvorbis'а есть неприятная особенность: при указании битрейта (-b:a) он включает режим CBR (постоянный битрейт), что сильно снижает его эффективность и, соответственно, качество звука. Для режима VBR (переменный битрейт) следует указывать качество (-q:a), его значения можно посмотреть тут

tl,dr: -c:a libvorbis -q:a 0..10