Живое кодирование с VP9 с использованием FFmpeg

Параметры кодирования

VP9 предоставляет ряд параметров для оптимизации живого кодирования. Некоторые общие принципы обсуждаются в разделе «Режимы битрейта» .

Пример кодирования FFmpeg VP9

В таблице ниже описаны параметры примера вызова ffmpeg для кодирования VP9.

Параметр Описание
-quality realtime realtime необходим для потоковой передачи в реальном времени и для скоростей выше 5 .
-speed 6 Для кодирования в реальном времени следует использовать скорости 5 до 8 Более низкие значения ( 5 или 6 ) обеспечивают более высокое качество, но требуют большей мощности процессора. Более высокие значения ( 7 или 8 ) обеспечивают более низкое качество, но более удобны для использования в сценариях с низкой задержкой и на устройствах с низким энергопотреблением процессора, таких как мобильные устройства.
-tile-columns 4 Тайлинг разбивает видео на прямоугольные области, что позволяет использовать многопоточную обработку при кодировании и декодировании. Количество тайлов всегда равно степени двойки. 0 = 1 тайл, 1 = 2, 2 = 4, 3 = 8, 4 = 16, 5 = 32.
-frame-parallel 1 Включить функции параллельного декодирования.
-threads 8 Максимальное количество используемых потоков.
-static-thresh 0 Порог обнаружения движения.
-max-intra-rate 300 Максимальный битрейт i-кадра (проценты)
-deadline realtime Альтернативная (устаревшая) версия -quality realtime
-lag-in-frames 0 Максимальное количество кадров для задержки
-qmin 4 -qmax 48 Минимальное и максимальное значения квантизатора. Приведённые здесь значения являются лишь рекомендацией, и их изменение поможет улучшить/ухудшить качество видео за счёт снижения эффективности сжатия.
-row-mt 1 Включить многопоточность строк. Позволяет использовать до двух потоков в качестве столбцов плитки. 0 = выкл., 1 = вкл.
-error-resilient 1 Включить функции устойчивости к ошибкам.

Выбор параметров кодирования

В приведенной ниже информации используется кодирование с постоянным битрейтом (CBR) для потоковой передачи в реальном времени с адаптивным битрейтом (ABR), где каждый целевой битрейт явно задан в манифесте упаковщика. Это обеспечит более плавное переключение между скоростями для клиентов. Кодирование с переменным битрейтом (VBR) и режим CQ также доступны, если битрейт может быть более гибким или кодирование выполняется фрагментами. Режим Q может испытывать трудности с кодированием в реальном времени, необходимым для живого видео. Подробнее см. в разделе «Режимы битрейта» .

Для получения более подробной информации о том, как манипулировать VP9, также стоит обратиться к прилагаемой статье о настройках VOD , но с учетом акцента на CBR.

Советы и рекомендации

Помните, что при прямой трансляции всё ограничено минимальной скоростью кодирования в реальном времени 1x (FFmpeg сообщает о скорости кодирования по мере её выполнения). Если скорость кодирования падает ниже 1x, процесс кодирования не будет справляться с потоком видео, и пользователи столкнутся с буферизацией, а прерывания передачи сделают трансляцию непригодной для использования во время прямой трансляции (хотя архив в целом останется пригодным для использования).

Примеры параметров кодирования в действии

Ниже показана загрузка ЦП при 25 кадрах в секунду для различных размеров кадров на настольном компьютере с четырехъядерным процессором i5 3,6 ГГц под управлением Linux:

Разрешение цели Параметры FFmpeg VP9 Процессор / Скорость (пример)
3840x2160 (2160p) -r 30 -g 90 -s 3840x2160 -качество в реальном времени -скорость 5 -потоки 16 -строки-метры 1 -столбцы-плитки 3 -параллельные кадры 1 -qmin 4 -qmax 48 -b:v 7800k ~88% 0,39x
2560x1440 (1440p) -r 30 -g 90 -s 2560x1440 -качество в реальном времени -скорость 5 -потоки 16 -строки-метры 1 -столбцы-плитки 3 -параллельные кадры 1 -qmin 4 -qmax 48 -b:v 6000k ~86% 0,68x
1920x1080 (1080p) -r 30 -g 90 -s 1920x1080 -качество в реальном времени -скорость 5 -потоки 8 -строки-метры 1 -столбцы-плитки 2 -параллельные кадры 1 -qmin 4 -qmax 48 -b:v 4500k ~82% 1,04x
1280x720 (720p) -r 30 -g 90 -s 1280x720 -качество в реальном времени -скорость 5 -потоки 8 -строки-метры 1 -столбцы-плитки 2 -параллельные кадры 1 -qmin 4 -qmax 48 -b:v 3000k ~78% 1,77x
854x480 (480p) -r 30 -g 90 -s 854x480 -качество в реальном времени -скорость 6 -потоки 4 -строки-метры 1 -столбцы-плитки 1 -параллельные кадры 1 -qmin 4 -qmax 48 -b:v 1800k ~64% 3,51x
640x360 (360p) -r 30 -g 90 -s 640x360 -качество в реальном времени -скорость 7 -потоки 4 -строки-метры 1 -столбцы-плитки 1 -параллельные кадры 0 -qmin 4 -qmax 48 -b:v 730k ~62% 5,27x
426x240 (240p) -r 30 -g 90 -s 426x240 -качество в реальном времени -скорость 8 -потоки 2 -строки-метры 1 -столбцы-плитки 0 -параллельные-кадры 0 -qmin 4 -qmax 48 -b:v 365k ~66% 8,27x

Пример FFmpeg может выглядеть так:

ffmpeg -stream_loop 100 -i /home/id3as/Videos/120s_tears_of_steel_1080p.webm \
  -r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 \
  -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k -c:v libvpx-vp9 \
  -b:a 128k -c:a libopus -f webm pipe1

Советы и рекомендации

  • Обратите внимание, что здесь мы выводим данные в канал FIFO («pipe1»), который необходимо создать перед выполнением команды FFmpeg. Для этого выполните команду mkfifo pipe1 в вашем рабочем каталоге. При использовании Shaka Packager этот канал будет использоваться в качестве источника входных данных для заданного потока. Для других моделей упаковки может потребоваться другой метод.

  • Чтобы команды -row-mt распознавались, используйте последнюю стабильную версию FFmpeg (в настоящее время 3.3.3) с сайта https://www.ffmpeg.org/download.html

Пример набора адаптивных битрейтов

В зависимости от мощности компьютера, на котором выполняется кодирование FFmpeg, может быть или не быть возможным обеспечить одновременную доставку всех следующих кодировок, поэтому из списка следует выбрать подмножество, соответствующее имеющимся у вас ресурсам и целевой аудитории.

Полный набор ABR для FFmpeg

В идеальном сценарии мы объединяем примеры кодирования, описанные в предыдущем разделе, чтобы создать единую команду, которая выдает их все одновременно:

ffmpeg -stream_loop 100 -i lakes1080p.mp4 \
  -y -r 25 -g 75 -s 3840x2160 -quality realtime -speed 5 -threads 8 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 7800k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe1 \
  -y -r 25 -g 75 -s 2560x1440 -quality realtime -speed 5 -threads 8 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 6000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe2 \
  -y -r 25 -g 75 -s 1920x1080 -quality realtime -speed 5 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 4500k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe3 \
  -y -r 25 -g 75 -s 1280x720 -quality realtime -speed 5 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 3000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe4 \
  -y -r 25 -g 75 -s 854x480 -quality realtime -speed 6 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 2000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe5 \
  -y -r 25 -g 75 -s 640x360 -quality realtime -speed 7 -threads 2 \
  -tile-columns 1 -frame-parallel 0 \
  -b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe6 \
  -y -r 25 -g 75 -s 426x240 -quality realtime -speed 8 -threads 2 \
  -tile-columns 1 -frame-parallel 0 \
  -b:v 365k -c:v libvpx-vp9 -b:a 64k -c:a libopus -f webm pipe7

Однако для полного набора вышеперечисленных функций потребуется очень мощный процессор или, возможно, поддержка аппаратной разгрузки графического процессора, которую всё чаще предлагают некоторые чипсеты. Intel Kabylake (и более поздние версии) имеют полноценный аппаратный конвейер кодирования. (Обратите внимание, что графический процессор Kabylake может кодировать VP9 с разрядностью 8 бит, но не 10 бит).

Практический пример использования Shaka Packager на рабочем столе

Более практичным примером для обычных настольных компьютеров может быть использование Shaka Packager . Простой способ установки Shaka — установить его в контейнер Docker, используя образ DockerHub от Google. Инструкции можно найти здесь:

https://github.com/google/shaka-packager#using-docker-for-testing--development

Для этого примера мы использовали машину следующей конфигурации:

Система Хост: obs Ядро: 4.4.0-91-lowlatency x86_64 (64 бит)
Рабочий стол Дистрибутив Xfce 4.12.3: ОС: https://ubuntustudio.org/2016/10/ubuntu-studio-16-10-released/
Процессор Четырехъядерный процессор Intel Core i5-6500 (-MCP-)
кэш: 6144 КБ
Тактовые частоты: макс.: 3600 МГц 1: 800 МГц 2: 800 МГц 3: 800 МГц 4: 800 МГц
Видеокарта Интегрированная графика Intel Skylake
Память 8 ГБ ОЗУ

На практике эта машина может оптимально производить следующий диапазон кодирований ABR, при этом FFmpeg постоянно сообщает о скорости кодирования 1x:

ffmpeg -stream_loop 100 -i 120s_tears_of_steel_1080p.webm \
  -y -r 30 -g 90 -s 1920x1080 -quality realtime -speed 7 -threads 8 \
  -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 4500k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe1 \
  -y -r 30 -g 90 -s 1280x720 -quality realtime -speed 8 -threads 6 \
  -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 3000k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe2 \
  -y -r 30 -g 90 -s 640x360 -quality realtime -speed 8 -threads 2 \
  -row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe3

Обратите внимание, что настройки -speed довольно высокие. Эти настройки были установлены экспериментально и могут различаться в зависимости от модели.

Накладные расходы Shaka Packager

Упаковка не слишком нагружает процессор. Shaka Packager можно настроить на прослушивание всех выходных данных, даже если FFmpeg доставляет только часть из них. Вот настройки упаковщика, протестированные на машине, описанной выше:

packager \
  in=pipe1,stream=audio,init_segment=livehd-audio-1080.webm,segment_template=livehd-audio-1080-\$Number\$.webm \
  in=pipe1,stream=video,init_segment=livehd-video-1080.webm,template=livehd-video-1080-\$Number\$.webm \
  in=pipe2,stream=audio,init_segment=livehd-audio-720.webm,segment_template=livehd-audio-720-\$Number\$.webm \
  in=pipe2,stream=video,init_segment=livehd-video-720.webm,template=livehd-video-720-\$Number\$.webm \
  in=pipe3,stream=audio,init_segment=livehd-audio-360.webm,segment_template=livehd-audio-360-\$Number\$.webm \
  in=pipe3,stream=video,init_segment=livehd-video-360.webm,template=livehd-video-360-\$Number\$.webm \
  --mpd_output livehd.mpd --dump_stream_info --min_buffer_time=10 --time_shift_buffer_depth=300 \
  --segment_duration=3 --io_block_size 65536