В Тензоре около 7 тысяч сотрудников и более 100 филиалов по всей стране - такой компании категорически необходима видеокоммуникация. Существует 2 соизмеримых по издержкам решения: использовать существующий продукт или реализовать свой.

В этой статье я, разработчик отдела вебинаров, расскажу, каким образом наша компания, выбрав когда-то второй путь, пришла к собственному сервису вебинаров. Пройдя несколько итераций развития, на сегодняшний день мы научились проводить видеоконференции буквально на всех наших сотрудников.

Дисклеймер: здесь и далее мы будем говорить про веб-решения видеосвязи, основанные на технологии WebRTC. Всё, что нужно о ней знать для понимания статьи: WebRTC - технология, позволяющая устанавливать P2P соединение между двумя браузерами и обмениваться данными: медиа-потоками, такими как изображение с камеры, звук с микрофона, демонстрацию вашего экрана и др, а также потоками любых других данных. Более подробно с ней можно ознакомиться на официальном сайте: https://webrtc.org/.

Позвольте начать с предыстории.

Отдел вебинаров. Начало (2017 год)

Собственная видеосвязь в Тензоре существовала уже несколько лет, позволяла собирать в одном звонке до 50-60 человек. Это покрывало все потребности компании, оставляя нерешёнными всего 2 проблемы:

  1. Проведение массовых конференций и онлайн-корпоративов.

В Тензоре всё чаще стала возникать потребность в видео-конференциях с большим количеством слушателей, разбросанных по всей стране. Очевидно, что собрать их всех в одном месте можно только в интернете.

  1. Постепенный рост отделов и среднего числа участников совещаний.

К концу 2016 года эта проблема становиться особенно острой, так как созвонов где одновременно вещают 50-60 человек становится недостаточно. Компания расширяется, появляются новые отделы, старые увеличиваются и делятся на подотделы… И всем по-прежнему нужно проводить планёрки с максимальной явкой, а сервера уже работают на пределе возможностей.

Могли ли мы тогда просто масштабироваться? Давайте посчитаем.

Что такое полноценный видеозвонок? Видеосовещание, в котором каждый участник, с одной стороны, должен иметь возможность показывать свою камеру, а с другой - видеть всех остальных.

Как бы ни была организована обработка потоков на сервере, от каждого участника идёт хотя бы 1 поток и каждому нужно отправлять хотя бы n-1 потоков (по одному от каждого другого). Иначе говоря, рост потребляемых ресурсов был квадратичным по отношению к увеличению числа участников.

Таким образом, потенциал для масштабирования был, но был он небольшой и очень дорогой: потратить круглую сумму, чтобы отсрочить проблему на 1-2 года.

Очень быстро стало понятно, что на этом далеко не уехать, необходимо принципиально новое решение, если мы хотим преодолеть барьер по числу участников. Именно тогда наш доблестный теперь уже сеньор-разработчик (Влад, привет!) предлагает амбициозный проект сервиса вебинаров.

Действительно, ведь чем вебинар принципиально отличается от звонка? Теперь только некоторая группа участников в совещании являются активными, все остальные наблюдают за их разговором. По сути вебинар - это звонок, который транслируется на максимально возможное количество зрителей. Ключевой особенностью была механика запроса голоса: любой зритель мог запросить слово и - с разрешения ведущего - стать спикером, установив с сервером WebRTC соединение.

В конце лета того же года было принято судьбоносное решение в компании: сформировать команду, которая в кратчайшие сроки должна предоставить прототип сервиса. Так появляется наш отдел Вебинаров!

Рецепт первых вебинаров

Глобально, сервис должен состоять, как минимум, из трёх частей:

  1. Модуль приёма видеопотока от ведущего (ведущих) по WebRTC.

  2. Модуль отправки этого потока зрителям.

  3. Модуль управления трансляцией.

С первым модулем задача уже была решена в звонках, нам нужно было лишь перенять от них опыт - подготовить медиа-сервер для приёма потоков.

Всё самое интересное предстояло решить со вторым:

  1. Что модуль отправки получал на вход? Открываем спецификацию WebRTC и видим, что поток сжимается видеокодеком VP8 и аудиокодеком Vorbis - всё это оборачивается в контейнер .webm.

  2. В каком виде этот поток следует отправлять зрителям? Как бы сильно нам ни хотелось отправлять «в таком же» формате, увы, вышеупомянутые кодеки не поддерживались IE и Safari (нам важна была поддержка и первого, и второго браузера). По этой причине у нас сразу же появляется задача конвертации .webm (VP8/Vorbis) в .mp4 (H264/AAC). Для этого, очевидно, понадобится одноимённый компонент конвертор. При этом видео для отправки необходимо будет разбивать на сегменты (чанки), что и послужит в дальнейшем названием микросервиса.

  3. А как именно отправлять поток зрителям? Очевидный ответ - по WebRTC. Догадаетесь, откуда полетят палки в колёса?… Если Apple уже летом 2017 анонсирует поддержку технологии в 11-м сафари, то IE… без шансов. Поэтому для такого случая модуль должен уметь отправлять поток резервным способом - мы выбрали для этого websocket.

Что касается третьего модуля, здесь всё просто: у ведущего должна быть возможность начинать/завершать трансляцию, ставить её на паузу. Сервер обработки сигналов с клиента мы так и назвали - сигналлер (signaller).

Таким образом, у нас уже намечалась следующая микросервисная архитектура:

Интерактивность

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

С трансляцией последних двух нас здорово выручал canvas: его механизм захватывал всё происходящее, и этот стрим можно было отправлять вместе со стримом ведущего.

Иными словами, браузерное API до неприличия непринуждённо закрывало нам все вопросы со стримами:

  • getUserMedia() - метод захвата стрима с микрофона и камеры

  • getDisplayMedia() - метод захвата стрима с окна или экрана

  • canvas.captureStream() - метод захвата стрима с канваса

Наконец, какой вебинар может пройти без чата зрителей? С этим оказалось всё намного проще: функционал уже был в звонках, им занимался другой отдел, и нам любезно предоставили ту же возможность, дав сконцентрироваться именно на трансляции :)

Запрос голоса

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

Что по трафику?

Как видно, в нашей первоначальной схеме чанкер честно отдаёт видеопоток (стрим) каждому зрителю. Вместе с ростом их числа назревал вопрос: а как себя почувствует корпоративная сеть в филиалах, когда все сотрудники одного офиса единовременно начнут смотреть вебинар, т.е. загружать из внешней сети FullHD стрим?

Нужно было разработать решение, которое бы снизило трафик внутри локальной сети. К счастью, на помощь пришёл сам WebRTC: тот факт, что мы можем устанавливать прямое соединение между двумя клиентами, позволил реализовать т.н. P2P-дерево доставки контента.

При таком подходе зритель, получая контент от чанкера, может сам выступать в роли отправляющего другим участникам. Безусловно, каждое дополнительное WebRTC соединение повышало нагрузку на него, поэтому один участник мог раздавать стрим максимум трём другим. Последние могли раздавать следующим - отсюда и получалось дерево.

Вебинары. Первый релиз (лето 2017 года)

Итак, нашей команде понадобилось всего полгода, чтобы на свет появилась первая полноценная версия сервиса!

Пока компания привыкала к вебинарам, у нас стояла только одна задача: исследовать нагрузку с реальных зрителей, понять текущий максимум, определить направления оптимизации.

Результат первых «боевых» испытаний: 450 зрителей в одном вебинаре. Позже мы смогли зафиксировать рекорд в 500 человек, дальше чанкер начинает умирать.

Это, конечно, был колоссальный результат на фоне предыдущего барьера звонков. Но, очевидно, что потенциал вебинаров был совсем не раскрыт. Нужно двигаться в направлении оптимизации - просто масштабировать систему пока рано.

Во что мы упирались? Однозначно в раздачу контента.

Как разгрузить чанкер?

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

Решили взять эту идею в основу дальнейшей оптимизации. Зритель по-прежнему раздавал стрим не более трём другим участникам. Но что, если сделать микросервис, который был бы готов раздавать большему числу зрителей?

Так у нас появился репитер (repeater).

Репитер (лето 2018 - 2019)

Микросервис разворачивался внутри локальной сети филиала. Технически он ничем не отличался от обычного зрителя кроме одного: на нём не было лимита подключений для P2P.

При этом мы скорректировали изначальный алгоритм работы дерева, и теперь каждый зритель сначала пытался подключиться именно к репитеру и только в случае неудачи искал другого «раздающего».

Таким образом, получилось снизить нагрузку и на чанкер, и на каждого клиента в среднем. Трафик локальной сети сконцентрировали в одном направлении, а главное - открыли перспективу масштабирования: гораздо проще увеличивать теоретический пул репитеров в филиале, чем создавать тот же пул чанкеров и систему обмена контентом между ними.

Первая тысяча

Сразу после внедрения репитера мы фиксируем на вебинаре первую тысячу участников! В тот момент - грандиозный успех! Руководители секторов становились смелее и начинали планировать вебинары на 1500-2000 человек - и такое количество нам тоже удавалось держать!

Помните 2 проблемы в начале статьи? Уже на этом этапе они были решены: крупные совещания прекрасно проводились в рамках вебинара, а большие корпоративные конференции, пусть не на всю компанию, но на треть, тоже были возможны!

Разумеется, на этом никто не собирался останавливаться, но спросите нас тогда - что мешало сервису держать на несколько тысяч человек больше? Мы бы ответили - дайте чуть больше железок… Увеличим чуть больше репитеров, нарастим мощность, и всё - весь Тензор в одном вебинаре.

Необходимости такой не было, решение временно отложили…

Свободное развитие (2019)

Безусловно, это самый спокойный период в истории нашей команды. Основная проблема в то время - баги, которые периодически находили тестировщики. Естественно, мы их исправляли.

Вебинарами в компании пользовались всё чаще: у сотрудников уже появлялись идеи для внутренних тренингов, проводились в том числе и развлекательные мероприятия (Впервые провели новогодний 5-тичасовой эфир Тензор ТВ на всю компанию).

В сравнении с бурным стартом мы действительно спокойно развивали продукт:

1. Во всю улучшали фронтенд.

Компания активно использовала свой фреймворк Wasaby (https://wasaby.dev), - у нас была возможность внедрять новые фишки в числе первых отделов.

2. Добавили демонстрацию видеофайлов.

Функционал демонстрации презентаций уже был, почему бы не сделать то же самое с видео? Технически их реализации мало чем отличались: компонент video имеет точно такой же метод captureStream(), как и canvas, т.е. трансляция велась с плеера ведущего.

3. Делали ресёрч.

Было достаточно ресурсов для ресёрча повышения доступности вебинаров: на тот момент для бесперебойного просмотра нужен был стабильный быстрый интернет-канал, но как сделать трансляцию, например, для 3G?

На тот момент набирали популярность технологии адаптивной потоковой передачи данных (Adaptive Bitrate Streaming, ABR) - открытая MPEG-DASH и проприетарная HLS от Apple. Идея механизма заключалась в раздаче стримов сразу в нескольких аудио и видео дорожках (качествах): от 240p до 1080p. Зритель мог бы сам переключаться между ними или довериться алгоритму плеера для выбора оптимального качества (недавно у нас вышла статья на эту тему - ABR для живых трансляций).

Пожалуй, самый неудобный вопрос к нашему сервису в то время был следующий: хорошо, репитер действительно закрыл проблемы нагрузки в филиалах, но как быть с удалёнными сотрудниками? Им ведь приходится подключаться напрямую к чанкеру? Что, если их количество увеличится?

К 2019 году доля удалённых сотрудников компании была невелика. Именно к этому мы и апеллировали: в Тензоре абсолютное большинство очных работников, предпосылок к изменениям в этом никаких не наблюдается.

В конце концов, что такого должно произойти в мире, чтобы количество дистанционных сотрудников стало на порядок больше обычных?…

2020

Разумеется, не только "мы", а весь мир
Разумеется, не только "мы", а весь мир

«That would be funny. If it weren't so sad.» Выбора не было – с приходом тотальной удалёнки в репитере исчез смысл, P2P-дерево не работало.

По возможностям мы откатились не просто к моменту старта, всё было ещё хуже - в лучшем случае чанкер выдерживал 200 человек. Это была катастрофа!

Обнаружилось ещё и то, что не у всех сотрудников хороший домашний интернет. Поэтому помимо проблемы с нагрузкой чанкера актуальной стала задача адаптивного стриминга, ресёрчем чего мы, к счастью, уже занимались.

В вебинарах предстояло много инноваций.

Рождение ориджина

С самого начала наша архитектура предполагала наличие активного соединения со зрителем - непосредственная отправка стрима по WebRTC или websocket.

Однако существовал принципиально другой подход: складывать чанки на ресурсе и отправлять зрителям ссылку на них. В этом случае, клиент будет скачивать его по HTTP, как статику с кеш-сервера. Ключевой момент: нет никакого постоянного соединения между ориджином и клиентом.

Эта фишка идеально сочеталась с ABR: зритель получал ссылку на плейлист чанков (.mpd файл в случае MPEG-DASH и .m3u8 в случае HLS), внутри которого содержалась информация о всех вариантах качества стрима, а также ссылки, по которым их можно загружать.

Основное преимущество такого микросервиса - простейшая масштабируемость: чанки складываются на основном (origin) сервере, пользователи же обращаются к edge серверам. Если у edge сервера отсутствует конкретный чанк, он загружает его с ориджина и отдаёт зрителю. Следующим зрителям он сразу отдаст этот сегмент.

Стало ясно, что с чанкером пора прощаться. Осталось только из WebRTC-потока ведущего научиться делать ABR.

От конвертера к транскодеру

Одно дело - конвертировать .webm в .mp4, совсем другое - делать из потока сразу несколько дорожек по стандарту ABR. Это уже задача транскодирования, ввиду чего нужен был новый сервис - транскодер (transcoder).

От сигналлера к бизнес-логике (БЛ)

Зрители как-то должны получать ссылку на стрим. Если раньше у них было активное соединение с чанкером, теперь хотелось бы дать API для получения информации о стримах. Так мы трансформировали сигналлер в бизнес-логику.

Вебинары. Второе поколение (2020 год)

Спустя первую половину этого кошмарного года архитектура стала выглядеть следующим образом:

Но это того стоило!

Результаты после релиза второго поколения, 2000 зрителей. Вернулись к показателям прошлого года. Только теперь сотрудники были «разбросаны по интернету».

Догадываетесь, какая приоритетная задача стала у нас следующей?

Проект «10к зрителей на один вебинар» (2021 год)

Очевидно, что нашей следующей задачей становится полное покрытие штата компании. Так появился проект с говорящим названием.

Суть выражалась кратко: всё оптимизировать и масштабироваться, - что может быть проще? Тем не менее, вот три важных момента:

  1. Минимизация расходов на железо. Нужно было пройтись шлифовкой по всем микросервисам: где-то устранить неоправданно высокий жор ресурсов, где-то просто оптимизировать работу.

  2. Масштабирование кеша. Ориджин отлично справлялся со своей работой раздачи стримов, но оказалось, что более выгодно купить внешний CDN, чем разворачивать дополнительные мощности у себя.

  3. P2P. Сотрудники потихоньку возвращаются в офис, а значит, становится актуальным знакомый механизм. Необходимо по максимуму оптимизировать его алгоритмы.

Указанное число зрителей бралось с приличным запасом: на момент старта проекта число сотрудников компании только-только приближалось к отметке 6000. И понятно: для проверки достижения именно этого числа понадобится нагрузочное тестирование с применением зрителей-ботов.

Как вы думаете, что в этом проекте было самым сложным? Вы правы - провести это самое нагрузочное тестирование! Продемонстрировать, что мы достигли цели, и можем собрать всех сотрудников на один вебинар!

Оказалось, что раньше, не имея такой возможности, никто и не планировал никаких всеобщих конференций - они просто не предусматривались!

Компания уже проводила стабильные трансляции, на которых присутствовали по 3-4 тысячи человек, но для сдачи проекта всё равно нужно было набрать 10 тысяч.

На момент 2021 года мы не нашли сервис ботов, который бы предоставил их в таком количестве - максимум 4 тысячи. Следовательно, нам точно нужны были все компьютеры компании. Сначала хотели, чтобы одним вечером все сотрудники всех филиалов под конец рабочего дня не выключали машины, чтобы мы могли их использовать в нашем нагрузе, но многие всё равно этого не сделали. В конце концов, безопасники фокус не оценили, сказали «небезопасно» (и, в общем-то, были правы) – фокус не удался :) Далее в компании был объявлен день единого вебинара - день, когда все сотрудники всех подразделений должны зайти на вебинар и посмотреть, функционирует ли он конкретно в их браузере на их компьютере.

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

Вебинары 3. На пути к совершенству (2022 год - наст. время)

Преодолев отметку в 10 тысяч зрителей, мы смогли сконцентрироваться на фичах нашего сервиса. Архитектура оставалась прежней, но, тем не менее, произошло событие, ознаменовавшее новое поколение вебинаров - переход фронтенда на ReactJS.

Вместе с этим сразу адаптировали интерфейс к мобильным устройствам - теперь стало возможным смотреть вебинар через браузер телефона (в начале 2023 мы сделали возможным даже проводить его с телефона).

Транскодер тоже получил новые фичи. Далеко не полный список:

  1. Научился транслировать видеофайл сам.

Раньше мы транслировали его напрямую из плеера ведущего, теперь же транскодер получает сигналы «перемотай», «останови», а зрители видят нужную секунду видеофайла.

  1. Научился работать с видеокодером (OBS).

Вебинары всё больше становились похожи на стриминговые платформы - мы решили сделать возможным использовать тот же инструментарий.

  1. Научился накладывать виртуальный фон.

Уверен, у каждого сотрудника одно из ярких воспоминаний года удалёнки - виртуальные фоны, скрывающие бардак на заднем плане. Теперь это стало возможным сделать и у нас!

Заключение

Чем же занимаемся мы сейчас? «Быстрее, выше, сильнее». Теперь наша задача - сделать продукт предельно отказоустойчивым.

Тернистый путь к сегодняшним вебинарам занял у нас почти 7 лет и 3 большие итерации. Могли мы сразу разработать текущую архитектуру? Однозначно нет. WebRTC - одна из самых молодых веб-технологий, и мы развивались буквально вместе с ней (более того - развиваемся до сих пор).

Чему мы научились за эти годы?

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

  2. Распотрошили полностью ffmpeg в собственном форке - не бойтесь брать такого масштаба open-source проекты и делать его под себя.

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

Всей этой истории и нашего отдела не было бы, выбери тогда компания сторонний сервис видеосвязи.

Наконец, самое главное, чего мы достигли - полностью закрыли вопрос видеокоммуникации в нашей компании и сделали это даже с запасом!

Комментарии (1)


  1. puzo
    21.11.2023 11:31
    +1

    Все есть, что я любил в teams!!!! так держать