Сегодня видеоконференции — стандартный инструмент для бизнеса, образования и повседневного общения. Одной из ключевых технологий, лежащих в их основе, является WebRTC — открытый стандарт для обмена аудио, видео и данными в реальном времени. Однако качество работы и масштабируемость зависят от выбранной топологии взаимодействия участников.
Кратко про WebRTC
WebRTC — это набор API и протоколов, позволяющих браузерам и мобильным приложениям напрямую обмениваться мультимедийными потоками.
Для того чтобы прямое соединение между двумя браузерами, у которых нет белого IP, было возможно, используется технология ICE.
Поиск пути (ICE, STUN и TURN)
ICE (Interactive Connectivity Establishment) отвечает за выбор оптимального маршрута между клиентами. STUN помогает определить внешний IP и порт за NAT, а TURN служит запасным вариантом, обеспечивая ретрансляцию трафика через сервер.
Сигналинг
Собранной информацией с адресами для подключения (ICE-кандидатами) нужно обменяться между участниками соединения. Передать их можно любым доступным способом, но обычно для этого используют WS/HTTPS-сервер, который не участвует в передаче медиа, но обеспечивает организацию сессий.
Обмен техническими параметрами (SDP)
Также участники должны договориться, как именно будет происходить передача. Для этого используется протокол SDP. Session Description Protocol описывает кодеки, разрешения, форматы и другие параметры медиа.

Виды топологий
Когда речь заходит об организации видеоконференций, где участвует более двух клиентов, есть различные варианты схем такого взаимодействия.
Mesh
Самая простая топология, которая подразумевает прямую передачу потоков от каждого участника ко всем остальным.

Плюсы
Самая простая в реализации схема, не требующая сервера.
Минусы
Главным минусом такой реализации является быстро растущий трафик и нагрузка на клиентские устройства.
Давайте заглянем под капот браузера, как происходит кодирование стримов для отправки другим участникам?
Кажется интуитивно логичным, что браузер кодирует видео с источника (камеры), а потом посылает его во все подключения других участников.

Но в реальности видео отдельно кодируется для каждого соединения, и нагрузка увеличивается прямо пропорционально количеству участников.

Пример: при 4 участниках каждый браузер должен кодировать и отправлять 3 потока и декодировать ещё 3. CPU достигает ~60% загрузки, а суммарный трафик — 6 Мбит/с.
На практике это означает, что при использовании такой топологии видеоконференции более чем на 8 участников организовать не получится.
SFU
SFU (Selective Forwarding Unit) — топология, при которой используется сервер, который перенаправляет потоки между участниками. При этом сам сервер не декодирует и не кодирует стримы в процессе.

Плюсы
Такой подход позволяет снять часть нагрузки с клиента. При этом сервер может гибко перенаправлять потоки, не тратя ресурсы на их перекодирование.
Минусы
На клиенте остается нагрузка, связанная с декодированием каждого входящего потока по отдельности.
Входящая нагрузка на сеть также остается большой.
Связи внутри сервера увеличиваются в прогрессии n2 (где n — количество участников).
Пример: при 4 участниках клиент кодирует один поток и получает три. CPU достигает ~40% загрузки, а суммарный трафик — 4 Мбит/с. Сервер лишь маршрутизирует с нагрузкой ~10% CPU.
При использовании такой топологии получится организовать видеоконференцию примерно на 50 участников.
Но благодаря гибкости такого подхода нагрузку и трафик можно сокращать, увеличивая тем самым количество участников.
Способы оптимизации подключений
Отключение неиспользуемых стримов
Нет смысла отображать на экране больше 30 видео. Это неудобно для пользователя. Следовательно, с участников, которые не отображаются, можно получать только аудио. Тем же, кто смотрит конкретное видео на весь экран, достаточно получать только это видео. В свою очередь, можно не получать аудио с тех, у кого отключен микрофон.
Если у какого-то потока в SFU нет ни одного получателя, его можно и не получать в SFU.
Битрейт по запросу
Еще один способ снизить нагрузку и трафик у клиентов — это уменьшение качества видео в потоке. Например, нет смысла получать качество потока выше, чем размер видеоэлемента в пикселях, а при раскладке в 30 видеоэлементов это размер небольшой. И только при развороте одним из участников видео на весь экран можно попросить отправителя повысить качество. Но при таком раскладе потребление трафика подскочит у всех участников.
Simulcast
Чтобы таких скачков трафика не происходило, а получатели всё могли выбирать качество, используют Simulcast. Участники отправляют всем видео в разном качестве, а получатели сами выбирают, какое им подходит.

В этом случае нагрузка и трафик на отправителе повышается, т. к. нужно кодировать три отдельных потока для разных вариантов качества. Количество связей в SFU также растет в разы.
SVC
SVC (Scalable Video Coding) — это еще один подход для решения той же задачи, но в этом случае все варианты качества кодируются вместе и расположены в одном потоке, причем все они являются производными из одного основного. Все участники могут получать от SFU только слой с необходимым вариантом качества в отдельности.

Единственным недостатком является ограничения кодеков. Полноценно кодирование в SVC сейчас поддерживают только VP9 и AV1, причем только в Хроме. Для участников без поддержки кодирования в SVC придется использовать Simulcast или единственный вариант качества.
MCU
MCU (Multipoint Control Unit) — топология, при которой сервер объединяет все входящие потоки в один и отправляет каждому участнику только итоговый микс.

Плюсы
Минимальная нагрузка на клиентов.
Отлично для слабых и мобильных устройств.
Минимальный трафик.
Минусы
Высокая нагрузка на сервер, т.к. сервер должен декодировать все потоки, объединить и кодировать в один.
У конечного пользователя пропадает возможность выбирать, чье видео смотреть, только общее.
Пример: клиент кодирует один поток и получает один общий и тратит на это ~20% CPU с суммарным трафиком — 2 Мбит/с. Сервер, напротив, работает на 100% CPU.
С таким подходом количество участников в видеоконференции, теоретически, может быть неограничено.
Какими качествами должен обладать MCU
Прежде всего, производить объединение видео и аудио;
Обеспечивать возможность подключения/отключения источников в реальном времени;
Синхронизировать аудио/видео и разные источники между собой (это может быть нетривиальной задачей);
Обработка должна происходить с минимальной задержкой;
Должна быть возможность управления раскладками (мозаика, активный спикер, «картинка в картинке» и т. д.);
В идеале, для перекодирования должно использоваться GPU;
Варианты реализации MCU
Классические способы организации MCU сложные в реализации и доработке.
Аппаратные решения
Профессиональные видеомикшеры и платы видеозахвата обеспечивают высокое качество и низкую задержку, но стоят дорого и плохо масштабируются. Реализовать дополнительный функционал на их основе невозможно.
GStreamer или FFmpeg
Использование мультимедийных библиотек, которые позволяют собирать потоки и выводить общий видеоряд. Это гибко, но требует больших доработок этих библиотек и глубокой экспертизы.
На основе браузера
Мы подумали — вот бы был движок, который:
умеет принимать и отдавать потоки по RTP/WebRTC;
имеет богатые возможности манипулирования визуалом и звуком, используя для этого GPU;
сам автоматически синхронизирует всё между собой;
имеет удобный канал управления на лету, а не запускается в виде процесса с заранее заданными параметрами.
Но ведь он есть — браузер у участников как раз этим и занимается.
Можно использовать сам браузерный движок (например, Chromium в headless-режиме) в качестве «сборщика» видеопотоков. Браузер умеет декодировать WebRTC-потоки, рендерить их на canvas или производить захват экрана, объединять аудио через Web Audio API и выдавать обратно в WebRTC-стрим. Такой метод позволяет:
ускорить разработку за счёт готовых API и знакомого стека для разработчиков;
использовать GPU и аппаратное ускорение;
добавлять интерактивные элементы (оверлеи, титры, визуальные эффекты) на видео;
управлять происходящим на видео в прямом эфире, например через WebSocket.
Давайте поговорим о реализации такого функционала. Для этого нам понадобятся следующие браузерные API:
WebRTC API (https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API)
MediaDevices (https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices)
MediaStream (https://developer.mozilla.org/en-US/docs/Web/API/MediaStream)
Web Audio API (https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)
В таком подходе MCU выступает служебным участником видеоконференции. Все участники подключаются не друг к другу, а к нему, получая в ответ общий «склеенный» поток. MCU получает MediaStream из RTCPeerConnection каждого участника и отображает их в сетке своего лейаута так же, как и обычные участники, после чего производит захват экрана с помощью getDisplayMedia и передает стрим в RTCPeerConnection каждого участника.

Особенности объединения аудио
Для аудио MCU может собирать общий микс, но нужно понимать, что каждому вещающему нужно отправлять индивидуальную версию (исключая его собственный голос, чтобы не было эха).

Для объединения аудио MCU преобразует MediaStream каждого участника в MediaStreamAudioSourceNode. Кроме того, для каждого участника создается свой MediaStreamAudioDestinationNode, куда подключаются MediaStreamAudioSourceNode всех участников, кроме него самого. Полученный в итоге стрим передается в RTCPeerConnection этого участника.

Ресурсы
В этом случае почти вся нагрузка ложится на MCU. Он должен декодировать потоки каждого участника и кодировать общий поток для каждого участника.
Пример: при 4 участниках клиент кодирует один поток и получает один. CPU достигает ~20% загрузки, а суммарный трафик — 2 Мбит/с. MCU получает 4 потока и отдает 4. CPU на MCU достигает ~260% загрузки.
Использование GPU
После настройки использования GPU нагрузка перераспределяется.
Пример: при 4 участниках клиент кодирует один поток и получает один. CPU достигает ~20% загрузки, а суммарный трафик — 2 Мбит/с. MCU получает 4 потока и отдает 4. CPU на MCU достигает ~150% загрузки. GPU на MCU достигает ~30%.
Комбинированный подход MCU + SFU
Чтобы нивелировать недостатки, которые появляются при использовании MCU, можно воспользоваться комбинированным подходом, когда используется и MCU, и SFU. MCU не нужно будет кодировать общий стрим для каждого участника. Кроме того, появляется возможность гибкого перенаправления и выбора между индивидуальными потоками и общим с MCU.

В таком подходе MCU выступает служебным участником видеоконференции, который, как и остальные, подключается к SFU. MCU получает MediaStream каждого участника из RTCPeerConnection SFU и отображает их в сетке своего лейаута так же, как и обычные участники, после чего производит захват экрана с помощью getDisplayMedia и передает стрим в RTCPeerConnection SFU.

Для объединения аудио MCU преобразует MediaStream каждого участника в MediaStreamAudioSourceNode. Кроме того, для каждого участника создается свой MediaStreamAudioDestinationNode, куда подключаются MediaStreamAudioSourceNode всех участников, кроме него самого. Полученный в итоге стрим передается в RTCPeerConnection SFU.

Такой подход предоставляет целый ряд преимуществ:
Вариативность получения стримов. Например, даже при просмотре пользователем общего потока с MCU можно реализовать разворот индивидуального видео на весь экран;
Показывать MCU индивидуально, а не всем, например, только для слабых и мобильных устройств;
MCU стрим можно использовать в качестве серверной видеозаписи, которая сразу готова.
Пример: при 4 участниках клиент кодирует один поток и получает один. CPU достигает ~20% загрузки, а суммарный трафик — 2 Мбит/с. CPU SFU равняется ~10%. MCU получает 4 потока и отдает 1. CPU на MCU достигает ~115% загрузки. GPU на MCU достигает ~25%.

Заключение
Комбинированный подход показал себя как наиболее гибкое решение: удалось равномерно распределить нагрузку между клиентами и серверной частью, максимально снизив требования к пользовательским устройствам. Использование браузерного движка в роли MCU стало удачным выбором — это дало возможность ускорить разработку, использовать GPU и знакомые веб-API, а также обеспечить удобство управления и расширяемость системы. Такой подход открывает путь к созданию более масштабируемых и адаптивных платформ видеоконференций.
Комментарии (6)

khserg
28.10.2025 12:23В гибридной схеме MCU+SFU MCU должен декодировать N входящих потоков, но кодировать уже только один исходящий. Были ли у вас возможности измерить, насколько именно использование GPU (через браузер) снижает нагрузку на CPU по сравнению с программным кодированием? И есть ли у вас метрики, определяющие, когда выгоднее подключать пользователя к MCU, а когда направлять ему индивидуальные потоки через SFU?

beatlejute Автор
28.10.2025 12:23Привет. Спасибо, что помогаешь раскрыть тему. Как расписал в примерах по распределению нагрузки на MCU без GPU и с ним, видно, что нагрузка на CPU снизилась на ~43%. MCU выгодно использовать на мобильных устройствах в первую очередь, а так для всех слабых устройств и в медленных сетях.
YaMars
Автор, конечно, выдал что-то эпичное. Такое ощущение, что статья писалась после беглого прочтения пары форумов, а не из опыта. MCU на браузерном движке — звучит примерно как «самолёт на педалях»: вроде летит, но только в воображении. Может, прежде чем писать про архитектуру WebRTC, стоит хотя бы разобраться, как работает RTP и зачем нужен SFU?
beatlejute Автор
Извините, вероятно, вы оставили комментарий, исходя только из заголовка, в статье есть про SFU и не только.
YaMars
Упоминание SFU там есть, но выглядит скорее как галочка для видимости, чем осознанная часть архитектуры. Такое чувство, что материал писался больше под впечатлением от демо, чем с пониманием особенностей медиасервера. Возможно, если чуть глубже копнуть в RTP/RTCP и топологию потоков, получится статья, к которой вопросов не будет.
beatlejute Автор
Есть решение, которое используется и справляется со своей задачей, о каких демо речь? Было бы замечательно, если бы в ваших сообщениях содержался конструктив. Какие именно у вас вопросы, с чем вы не согласны, в чем ваши сомнения?