Pull to refresh

Отладка и оптимизация скриптов gstreamer на примере онлайн трансляции (live streaming)

Reading time 4 min
Views 15K
Gstreamer — самая популярная *nix библиотека для работы с видео, которая является основой для большинства популярных приложений (основной список можно найти здесь).

image

Однако, столь гибкий инструмент требует тонкого подхода для стабильной и эффективной работы.
Все действия будут рассмотрены на примере онлайн HD трансляции с HDMI входа по RTMP с помощью blackmagic intensity pro, Debian Linux, gstreamer и Nginx.

Отладка (debugging) (manual)


У gstreamer есть встроенная возможность отладки, справку можно получить командой:
gst-launch --gst-debug-help

Сам вывод отладочной информации включается добавлением в команду:
--gst-debug-level=LEVEL
, где LEVEL — число от 0 (без вывода отладочной информации) до 9 (выводить всё).

Очень полезным является параметр
--gst-debug=GST_CAPS:4
, который будет выводить список возможных форматов элементов конвейера, если два элемента не могут найти подходящие друг другу форматы.

Однако, основной проблемой является огромное количество информации, которую требуется каким-то образом интерпретировать с целью дальнейшей оптимизации.
В данной ситуации есть прекрасная возможность генерации схем конвейера gstreamer, которая позволит наглядно увидеть порядок работы вашего конвейера:
  • Для генерации .DOT файла и дальнейшей конвертации требуется установить пакет graphviz.
    apt-get install graphviz
    
  • Далее требуется создать переменную окружения:
    export GST_DEBUG_DUMP_DOT_DIR=/tmp/dot
    mkdir -p $GST_DEBUG_DUMP_DOT_DIR
    
  • Запустите Gstreamer с вашим конвейером, в папке /tmp/dot будут созданы .dot файлы для каждого состояния конвейера.
  • Сконвертируйте полученные файлы в удобный вам формат:
    dot -Tpng input.dot > output.png
    dot -Tsvg input.dot > output.svg
    
    Использование SVG позволит бесконечно масштабировать полученную схему, так как информации на ней присутствует достаточно.
    Пример схемы.

По полученным данным можно будет найти узкие места вашего конвейера и добиться стабильной работы.

Оптимизация


В рамках примера оптимизации будет рассмотрены следующие требования:
  • 1920x1080 Full HD разрешение потока
  • 30 кадров в секунду
  • H264 кодек с битрейтом 768kbit/s
  • flv контейнер, передающийся по RTMP

Цель — работа системы в режиме реального времени без потерь кадров и синхронизации звука/видео.

Кадры/сек (fps)

Очень важно сразу выяснить, сколько кадров в секунду требуется и сколько может выдать ваше оборудование.
Оптимальным для динамического изображения является 30fps, но для передачи статичного контента (например, презентации) есть смысл уменьшать fps до минимально комфортного.

Многопоточность (использование queue)

В Gstreamer существует элемент queue, который оправдывает своё название — это очередь (поток) данных.
Использование queue позволит распараллелить вычисления и буферизировать информацию в автоматическом режиме для передачи между элементами.
Данный элемент является одним из ключевых наравне с queue2 (аналог queue с буферизацией на жесткий диск) и tee (разделение потока на несколько, например, для параллельной записи потока на диск), и они все достойны отдельной статьи.

Настройка элементов конвейера

Конечно же, ключевым моментом является настройка элементов конвейера (декодера звука и видео и т.д.).
  • По возможности избегайте копирования буферов
    v4l2src always-copy=false
    filesink enable-last-buffer=false
  • Настройка видео энкодера на работу в режиме реального времени
    Критично для онлайн трансляций
    x264enc tune=zerolatency
    dmaienc_h264 encodingpreset=2

  • Использование переменного битрейта для быстрой работы энкодера
    Выигрыш в производительности — до 3х раз
    x264enc pass=17
    dmaienc_h264 ratecontrol=2



Практика


Пример оптимизированного минимального конвейера:
gst-launch \
audiotestsrc ! queue ! audioresample ! voaacenc bitrate=64 ! audio/mpeg,rate=22050,channels=1 ! \
flvmux streamable=1 name=mux \
videotestsrc ! queue ! videorate ! videoscale ! x264enc bitrate=768 tune=zerolatency pass=17 ! \
mux. mux. ! \
rtmpsink location="rtmp://localhost/live/test"

В данном случае мы готовим поток с видео битрейтом 768 и одно канальным аудио битрейтом 64 кбит/сек соответственно, используем queue и конвертируем видео с переменным битрейтом.
Посмотреть схему конвейера можно здесь.

Вышеприведенный пример не учитывает некоторые требования поставленной задачи, итоговый конвейер:
gst-launch \
audiotestsrc ! queue ! audioresample ! audio/x-raw-int,width=16,depth=16,channels=2,rate=22050 ! \
audioconvert ! voaacenc bitrate=64 ! audio/mpeg,rate=22050,channels=1 ! \
flvmux streamable=1 name=mux \
videotestsrc ! queue ! videorate ! videoscale !  ffmpegcolorspace ! \
'video/x-raw-yuv, format=(fourcc)UYVY, framerate=(fraction)30/1' ! \
ffmpegcolorspace ! x264enc bitrate=768 tune=zerolatency pass=17 ! \
mux. mux. ! \
rtmpsink location="rtmp://localhost/live/test"

В данном конвейере предполагается, что videotestsrc отдаёт 1080p.
Данный пример является реальным и используется на сервере с 16 ядерным процессором и pci-платой Blackmagic intensity pro, итоговая нагрузка составляет 0,5 LA.
В обоих примерах веб-сервером использовался Nginx с прекрасным модулем пользователя rarutyunyan nginx-rtmp-module

Конечно же, существует множество других инструментов и возможностей для отладки и оптимизации Gstreamer,
буду рад вашим примерам!

Непрерывных трансляций вам, коллеги!

Источники и ссылки:


Tags:
Hubs:
+13
Comments 15
Comments Comments 15

Articles