Микширование видеопотоков — достаточно популярный инструмент для разных стримеров.
Микшер может прятаться под капотом многих продуктов, самые распространенные из которых чаты, системы видеоконференций или простые системы видеонаблюдения.
Один из самых частых вопросов, связанных с микшерами, мы вынесли в заголовок статьи. Раньше мы уже обсуждали, что самым оптимальным вариантом для конечного пользователя, который пользуется системой конференций или видеочатом будут решения на основе микшера. В этом случае пользователь отправляет серверу свой аудио-видео поток и получает от сервера один поток-мозаику с аудио-видео потоками других участников:
Микширование производится на стороне сервера и значительно нагружает ресурсы CPU и RAM, поэтому возникает вопрос:
Так сколько же все-таки может быть микшеров (читай комнат для чата или конференции) на сервере?
В теории, нет никакого ограничения. Микшеров на сервере может быть сколько угодно. И потоков в один микшер тоже можно добавить сколько угодно. То есть нет никаких ограничений, кроме здравого смысла и производительности серверного железа.
Давайте убедимся в этом на практике и опытным путем найдем ответ на этот вопрос.
Тестирование
Теоретические расчёты
Начнем тестирование с проверки пропускной способности канала связи между серверами с помощью Iperf. Пропускная способность канала связи между серверами в нашем случае 8.7 Gbps
В этом тестировании мы публикуем потоки с разрешением 720p. Один такой поток занимает примерно 2 Mbps канала. Для того, чтобы качество потока оставалось стабильным, канал не должен быть загружен более чем на 80% . Исходя из измеренной пропускной способности теоретически мы можем опубликовать 4000 потоков 720p без потери качества.
В качестве тестируемого сервера мы используем сервер со следующими техническими характеристиками
- Intel(R) Xeon(R) CPU E5-2696 v2 @ 2.50GHz (24 ядра, 48 гипертрейдинговых потоков);
- 128 GB RAM;
- 10 Gbps.
При работе микшеров используется транскодинг. Рекомендуется планировать серверные мощности из расчета 2 ядра CPU на 1 микшер т.е. для нашего 48 поточного сервера теоретически можно запустить 24 микшера.
В тестах мы будем использовать видеоролик с разрешением 720р. Подробнее параметры ролика на скриншоте ниже:
Настройки серверов
Для тестирования нам понадобится один установленный и настроенный экземпляр WCS. Предполагаем, что у вас он уже есть. Если нет, то устанавливаем по этой инструкции.
Готовим сервер к тестированию и подключаем к мониторингу Prometheus+Grafana как в этой статье с небольшой разницей:
1. Для большей наглядности разделим графики открытых декодеров и энкодеров. Число декодеров = число потоков в микшерах. Число энкодеров = число микшеров. Метрики для Grafana:
1 | native_resources{instance= "demo.flashphoner.com:8081" , job= "flashphoner" , param= "native_resources.video_decoders" } |
и
1 | native_resources{instance= "demo.flashphoner.com:8081" , job= "flashphoner" , param= "native_resources.video_encoders" } |
2. При первом тестировании мы будем считать не исходящие WebRTC, а входящие RTMP подключения. Метрика для Grafana:
1 | streams_stats{instance= "demo.flashphoner.com:8081" , job= "flashphoner" , param= "streams_rtmp_in" } |
3. В процессе второго тестирования нам пригодится число существующих VOD на WCS сервере. т.к. на момент написания статьи эта информация была доступна только по REST запросу, модифицируем скрипт для получения кастомных метрик.
В скрипт «custom_stats.sh» добавим следующие команды:
1 2 3 | curl -X POST -H "Content-Type: application/json" http: //localhost :8081 /rest-api/vod/find_all > vod.txt vod_stream=$( head -n 1 vod.txt | grep -o "localMediaSessionId" | wc -l) echo "vod-stream-qty=$vod_stream" |
Здесь мы с помощью REST запроса получаем информацию о всех VOD потоках на сервере и подсчитываем их количеству по числу открытых медиасессий. Количество VOD потоков выводится на страницу статистики в переменную «vod-stream-qty», откуда ее считывает Prometheus. Пример файла «custom_stats.sh» можно скачать в разделе «Полезные файлы» в конце статьи.
Метрика для Grafana:
1 | custom_stats{instance= "demo.flashphoner.com:8081" , job= "flashphoner" , param= "vod-stream-qty" } |
В разделе «Полезные файлы» вы можете скачать панели для Grafana со всеми нужными для тестирования метриками.
4. Оптимизируем настройки микшера. Как правило, микшер кодирует один видео поток и множество аудио, по два потока на каждого участника плюс один общий аудио поток. Поэтому рекомендуется задавать число процессорных потоков для кодирования аудио больше, чем для кодирования видео.
Многопоточное микширование и количество процессорных потоков для микширования аудио и видео задаются следующими настройками в файле flashphoner.properties (файл настроек flashphoner.properties можно скачать в разделе «Полезные файлы»):
1 2 3 | mixer_type=MULTI_THREADED_NATIVE mixer_audio_threads=10 mixer_video_threads=4 |
5. Включаем или отключаем ZGC. В зависимости от задачи нужно решить, использовать новый Z Garbage Collector или классический CMS. CMS менее требователен к ресурсам сервера, не занимает большой процессорной мощности, но и паузы для его работы могут быть существенными. Мы рекомендуем использовать CMS на средних по мощности серверах и в случаях, когда требуется большое число не-реалтаймовых микшеров. Например, когда микшеры используются для записи потоков.
Для реалтайма и MCU лучше использовать ZGC. Число микшеров в этом случаем может быть меньше, чем в случае использования CMS, но и паузы в работе Garbage Collector будут значительно меньше, что позволит добиться более плавного воспроизведения выходного потока в случаях использования микшера для проведения различных конференций, видеочатов или вебинаров.
Тип используемого Garbage Collector задается в файле wcs-core.properties. Подробнее в документации.
Тестирование первое
Если в имени публикуемого RTMP-потока есть символ ‘#’, сервер рассматривает все, что написано после этого символа, как имя микшера, который будет создан автоматически при публикации потока. Для первого тестирования на другом сервере с помощью ffmpeg создаем RTMP-потоки, которые будут ретранслироваться на тестируемый сервер и затем автоматически собраны в микшеры.
Публикацию запускаем при помощи скрипта:
1 2 3 4 5 6 7 8 | #! /bin/bash mixer=24 stream=2 for i in ` seq 1 $mixer`; do for j in ` seq 1 $stream`; do ffmpeg -re -i /root/test .mp4 -acodec copy -vcodec copy -g 24 -strict -2 -f flv "rtmp://172.16.40.21:1935/live/test$j#mixer$i" -nostdin -nostats < /dev/null > /dev/null 2>&1 & done done |
где:
mixer — количество создаваемых микшеров
stream — число потоков в каждом микшере.
Опытным путем подберем максимальное количество микшеров и потоков в них, чтобы качество воспроизведения выходного потока микшера было оптимальным.
Начнем тестирование с 4 микшеров по 15 потоков:
В этом тестировании нагрузка на тестируемый сервер была не большой, Load Averrage 1 (зеленая линия на графике)15-20 единиц. Деградации потоков не выявлено. Визуально выходной поток микшера проигрывался с приемлемым качеством.
В следующей итерации увеличим число микшеров до 8 при тех же 15 потоках на микшер:
В этом случае сервер не справился с нагрузкой. Load Averrage 1 (зеленая линия на графике) в пике около 150 единиц. С первых минут теста зафиксирована деградация стримов. В контрольном потоке наблюдаются фризы.
Попробуем уменьшить количество микшеров.
6 микшеров по 15 потоков:
Картина немногим лучше — все признаки того, что сервер не справляется сохранены — высокий Load Averrage 1 (более 100 единиц) и деградация стримов.
5 микшеров по 15 потоков:
Теперь все в порядке — Load Averrage 1 менее 40 единиц и нет деградировавших стримов. Контрольный поток тоже проигрывается правильно, без артефактов и фризов:
Как видите, число микшеров для 15 потоков (читай «комнат для конференций») получилось достаточно скромным. Протестируем второй вариант использования микшера — комнаты для видеочата один на один:
Начнем тестирование с 12 микшеров по 2 потока:
Этот тест сервер прошел успешно. Load Averrage 1 менее 10 пунктов (зеленая линия на графике). Отсутствие деградировавших стримов. Контрольный поток воспроизводился гладко:
Теперь добавим еще 12 микшеров. Как вы помните, выше мы говорили, что из расчета 2 ядра CPU на 1 микшер для нашего 48 поточного сервера 24 микшера это максимальное количество. Тест 24 микшера по 2 потока:
Этот тест не пройден. Сервер не справился с нагрузкой (пик Load Averrage 1 75 единиц) и наблюдалась деградация стримов.
Итак, искомое максимальное число микшеров для 2 потоков находится где-то между 12 и 24 микшерами. Чтобы минимизировать число тестов используем стратегию, похожую на бинарный поиск.
Тест 18 микшеров по 2 потока:
Тест пройден. Load Averrage 1 в пике чуть больше 20 пунктов и отсутствие деградировавших стримов. К контрольному потоку тоже замечаний нет:
Тест 21 микшер по 2 потока:
Тест пройден. Пик Load Averrage 1 составил около 50 пунктов. Деградировавших стримов так же не зафиксировано.
Тест 23 микшера по 2 потока:
Тест не пройден. Регистрируется деградация стримов.
Остается проверить последний вариант — 22 микшера по 2 потока:
К сожалению, ближе к завершению теста была зафиксирована деградация 40% стримов, поэтому тест нельзя считать успешным.
Следовательно, максимальное число микшеров по 2 потока на нашем сервере — 21 микшер.
Результаты тестирования микшеров в таблице:
Число микшеров | Число потоков в каждом микшере | Результат теста |
4 | 15 | Пройден |
5 | 15 | Пройден |
6 | 15 | Не пройден |
8 | 15 | Не пройден |
12 | 2 | Пройден |
18 | 2 | Пройден |
21 | 2 | Пройден |
22 | 2 | Не пройден |
23 | 2 | Не пройден |
24 | 2 | Не пройден |
Тестирование второе
В этом варианте тестирования мы исключаем из теста сеть. Потоки будем публиковать локально по технологии VOD (Video on Demand). Для захвата используем тот же ролик 720р, что и в предыдущем тесте.
Для работы с VOD добавим следующие настройки в файл flashphoner.properties
1 2 | vod_live_loop= true vod_stream_timeout=14400000 |
где:
vod_live_loop=true — циклический захват потока, после окончания файла захват начинается сначала
vod_stream_timeout=14400000 — настройка продолжительности публикации VOD потока после отключения подписчиков. Задается в мс, по умолчанию 30 сек, мы указали 4 часа.
Скрипт для запуска тестирования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #! /bin/bash contentType= "Content-Type:application/json" mixer=24 stream=2 for i in ` seq 1 $mixer`; do data= '{"uri":"mixer://mixer' $i '", "localStreamName":"mixer' $i '", "hasVideo":"true", "hasAudio":"true"}' curl -X POST -H "$contentType" --data "$data" "http://localhost:8081/rest-api/mixer/startup" -nostdin -nostats < /dev/null > /dev/null 2>&1 & for j in ` seq 1 $stream`; do dataj= '{"uri":"vod-live://test.mp4", "localStreamName":"test' $i '-' $j '"}' datai= '{"uri":"mixer://mixer' $i '", "remoteStreamName":"test' $i '-' $j '", "hasVideo":"true", "hasAudio":"true"}' curl -X POST -H "$contentType" --data "$dataj" "http://localhost:8081/rest-api/vod/startup" -nostdin -nostats < /dev/null > /dev/null 2>&1 & sleep 1s curl -X POST -H "$contentType" --data "$datai" "http://localhost:8081/rest-api/mixer/add" -nostdin -nostats < /dev/null > /dev/null 2>&1 & done done |
В этом варианте тестирования мы исключили сеть, но часть процессорных ресурсов теперь занята обработкой VOD. Повторим тесты и посмотрим на результаты.
Подбор количества микшеров для 15 потоков.
Начнем с максимума в прошлом тестировании. 5 микшеров по 15 VOD потоков:
Тест пройден. Деградация стримов не зафиксирована. Контрольный поток воспроизведен успешно:
Попробуем увеличить число микшеров. 6 микшеров по 15 VOD потоков:
Как и для RTMP потоков, тест 6 микшеров по 15 потоков не пройден. На графике видно, что присутствует деградация стримов и в контрольном потоке наблюдается подвисание картинки:
Теперь протестируем 24 микшера по 2 VOD потока. Это, как вы помните, максимальное количество микшеров для нашего 48 поточного сервера.
К сожалению, этот тест провалился. Обработка VOD потоков на том же сервере, что и микшеры, нагружает процессор, поэтому такой результат теста вполне ожидаем. Значение Load Averrage 1 около 80 единиц (зеленая линия на графике) свидетельствует о высокой нагрузке на процессор. Были зарегистрированы деградировавшие стримы. Контрольный поток так же показал фризы:
Проверим 12 микшеров по 2 VOD потока:
Этот тест пройден. Деградации стримов не зафиксировано, контрольный выходной поток случайного микшера воспроизводился без артефактов и фризов:
Значит, искомое максимальное число микшеров по 2 потока находится между 24 и 12.
Тест 18 микшеров по 2 VOD потока:
Тест пройден. Деградации стримов не зафиксировано, контрольный поток воспроизводился без потерь качества.
Идем дальше. Тест 21 микшер по 2 потока. В прошлом тестировании 21 микшер с RTMP потоками был максимальным числом микшеров для нашего сервера, посмотрим, на результаты с VOD потоками:
Тест пройден. Деградации стримов снова не зафиксировано, контрольный поток воспроизводился без потерь качества.
Тест 23 микшера по 2 потока:
Этот тест не пройден. Отмечается деградация стримов.
У нас остался еще один вариант теста между 21 и 23 микшерами. Тест 22 микшера по 2 VOD потока
В этом случае тест не пройден. Снова зафиксирована деградация стримов.
Значит, максимально число микшеров для двух VOD потоков на нашем сервере составляет 21 микшер — 21 чат комната для двух участников.
Результаты тестирования микшеров с VOD потоками в таблице ниже:
Число микшеров | Число потоков в каждом микшере | Результат теста |
5 | 15 | Пройден |
6 | 15 | Не пройден |
12 | 2 | Пройден |
18 | 2 | Пройден |
21 | 2 | Пройден |
22 | 2 | Не пройден |
23 | 2 | Не пройден |
24 | 2 | Не пройден |
Тестирование третье — аудиомикшер
В двух предыдущих тестах мы тестировали микшеры к котором добавлялись полноценные видеопотоки — с видео и аудио компонентами. А что, если у нас не видео, а голосовой чат? Давайте посмотрим, сколько чат комнат мы сможем разместить на нашем сервере в этом случае.
Для этого теста будем использовать файл без видео с аудиодорожкой. На скриншоте ниже подробные параметры файла для теста:
Аудио потоки для микшера будем публиковать по технологии VOD (Video on Demand).
Скрипт для запуска тестирования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #! /bin/bash contentType= "Content-Type:application/json" mixer=24 stream=2 for i in ` seq 1 $mixer`; do data= '{"uri":"mixer://mixer' $i '", "localStreamName":"mixer' $i '", "hasVideo":"false", "hasAudio":"true"}' curl -X POST -H "$contentType" --data "$data" "http://localhost:8081/rest-api/mixer/startup" -nostdin -nostats < /dev/null > /dev/null 2>&1 & for j in ` seq 1 $stream`; do dataj= '{"uri":"vod-live://audio-only.mp4", "localStreamName":"test' $i '-' $j '"}' datai= '{"uri":"mixer://mixer' $i '", "remoteStreamName":"test' $i '-' $j '", "hasVideo":"false", "hasAudio":"true"}' curl -X POST -H "$contentType" --data "$dataj" "http://localhost:8081/rest-api/vod/startup" -nostdin -nostats < /dev/null > /dev/null 2>&1 & sleep 1s curl -X POST -H "$contentType" --data "$datai" "http://localhost:8081/rest-api/mixer/add" -nostdin -nostats < /dev/null > /dev/null 2>&1 & done done |
Обратите внимание, что для этого теста мы отключаем создание видео потока при создании микшера и создание видеопотоков при добавлении потоков в микшер.
1 | "hasVideo" : "false" |
Для отображения на графиках данных относительно аудиосоставляющей потоков добавим следующие метрики:
1 | native_resources{instance= "demo.flashphoner.com:8081" , job= "WCS_metrics_statistic" , param= "native_resources.audio_codecs" } |
и
1 | native_resources{instance= "demo.flashphoner.com" , job= "WCS_metrics_statistic" , param= "native_resources.audio_resamplers" } |
Скрипты и панели для Grafana можно скачать в разделе «Полезные файлы»
Начнем тестирование с 24 микшеров по 2 потока. Тестировать большее число потоков в микшере можно, но не совсем удобно в плане оценки воспроизведения контрольного стрима.
Для нашего сервера 24 микшера с видео — это, теоретически, максимальное количество, и прошлые тесты показали, что с таким количеством микшеров сервер не справляется. В тестировании «Только аудио» видим, что сервер работает в нормальном режиме. Load Averrage 1 во время теста не превысил 10 единиц. Контрольный поток так же воспроизводился без слышимых ухудшений звука — без «кваканья» прерываний, ускорений и т.п.
Не будем вас утомлять долгими тестами. Для audio-only потоков нам удалось поднять 240 микшеров по 2 потока без деградации стримов и снижения качества выходных потоков. Для нашего сервера это 5 аудио микшеров на одно ядро CPU:
Результаты тестирования микшеров с audio-only потоками в таблице ниже:
Число микшеров | Число потоков в каждом микшере | Результат теста |
24 | 24 | Пройден |
48 | 48 | Пройден |
240 | 240 | Пройден |
Подводя итог
Сводные результаты трех тестов в таблице ниже:
Число микшеров | Число потоков в каждом микшере | Результат теста с RTMP потоками | Результат теста с VOD потоками | Результат теста с Audio-only потоками |
4 | 15 | Пройден | — | — |
5 | 15 | Пройден | Пройден | — |
6 | 15 | Не пройден | Не пройден | — |
8 | 15 | Не пройден | — | — |
12 | 2 | Пройден | Пройден | — |
18 | 2 | Пройден | Пройден | — |
21 | 2 | Пройден | Пройден | — |
22 | 2 | Не пройден | Не пройден | — |
23 | 2 | Не пройден | Не пройден | — |
24 | 2 | Не пройден | Не пройден | Пройден |
48 | 2 | — | — | Пройден |
240 | 2 | — | — | Пройден |
Итак, максимальное количества микшеров для потоков с видео — 21 микшер по 2 потока. Основная работа сервера приходится на транскодинг видео потоков внутри микшера и сам процесс микширования. Транскодирование аудио тратит намного меньше ресурсов сервера, поэтому и количество микшеров для audio-only потоков на порядок больше, чем для видео.
В этой статье мы наглядно показали три сходных методики тестирования работы и подбора максимального числа микшеров в зависимости от задач и серверных мощностей.
Мы тестировали «классические» микшеры. В случае использования MCU результат тестирования будет отличаться, потому что в режиме MCU на каждый микшер создается столько дополнительных микшеров, сколько потоков входят в этот микшер.
Например, один микшер с 10 входящими потоками породит в случае MCU 10 микшеров по 9 потоков в каждом. Итого будет 10×9 плюс 1×10 итого 11 микшеров.
На своих серверах вы можете получать другие значения, отличающиеся от наших тестов как в лучшую, так и в худшую сторону. На результаты тестирования могут влиять такие факторы, как:
- качество, разрешение и битрейт потоков входящих в микшер;
- состояние сети — скорость соединения, стабильность соединения, наличие широковещательного трафика и т.п.;
- состояние серверного железа — тактовая частота процессора, количество реальных и/или «гипертрейдинговых» ядер, объем оперативной памяти и т.п.;
- удаленность датацентра в котором размещены серверы от конечных пользователей (паблишеров и зрителей).
Сочетание всех этих факторов может влиять на результаты тестирования, поэтому при выборе сервера для продакшена рекомендуем обратить на это внимание и провести тестирование в условиях приближенных к вашей задаче.
Хорошего стриминга!
Полезные файлы
Панели для Grafana:
Настройки WCS:
Скрипт для получения кастомных метрик:
Скрипты для тестов:
Бонус «Как использовать панели для Grafana»
1. Скачайте и сохраните файлы .json из раздела выше.
2. Откройте файл на редактирование и замените IP адрес нашего сервера (172.16.40.23) на свой. Сохраните изменения в файле.
3. Откройте веб-интерфейс Grafana. Выберите из меню в левой части страницы пункт «Import»:
4. На открывшейся странице нажмите кнопку «Upload JSON file» :
5. Выберите ранее отредактированный файл .json на вашем компьютере, затем нажмите кнопку «Import» на открывшейся странице: