Запись, вещание и мост WebRTC → HLS

Автор: Николай СапуновОбновлено: август 202632 мин чтения
Содержание статьи +

TL;DR

Любой продукт с интерактивным видео поверх WebRTC рано или поздно сталкивается с одной и той же задачей: маркетинг называет её «записью», юристы – «архивом», а отдел роста – «прямой трансляцией на маркетинговом сайте». Это вторая, постоянная копия разговора для пассивных зрителей, существующая вне WebRTC-сессии. Доставить эту копию тысячам или миллионам зрителей быстрее всего по HLS, а процесс преобразования содержимого комнаты SFU в публичный HLS-плейлист в индустрии принято называть мостом WebRTC → HLS. В 2026 году в продакшене используются пять рабочих паттернов такого моста: пер-трековая запись, server-side композиция, композиция через headless-браузер, WebRTC → RTMP с выходом в отдельный live-энкодер и управляемые SaaS-мосты вроде LiveKit Egress, Dolby OptiView и Amazon Chime Live Connector. Какой из них подойдёт вашему продукту, определяют три вопроса: сколько у вас разных макетов, работает ли мост в режиме горячего ожидания или запускается по требованию, и какую общую задержку вы можете допустить. Эта статья подробно разбирает все пять паттернов – с архитектурой, цифрами по задержкам, сценариями отказов и реальной картиной из продакшена 2026 года.

Почему это важно

Если вы строите видеоконференции, телемедицину, e-learning, live-шопинг, аукционы, спорт-беттинг или платформу удалённой совместной работы на базе WebRTC, переход на мост в HLS – это момент, когда переворачивается ваша экономика. Доставка через WebRTC обходится дорого на одного зрителя, потому что каждый зритель – это отдельный пиринговый клиент для сервера. Доставка по HLS, напротив, выгодна: CDN кэширует сегмент один раз и раздаёт его миллионам пользователей. Архитектурные решения на уровне моста – что именно вы записываете, как формируете макет комнаты, где размещается транскодер, насколько сильно отстаёт broadcast-хвост – определяют максимальный размер аудитории, которую вы можете обслужить, и нижнюю границу расходов на CPU и трафик. Эти решения, как правило, становятся необратимыми после запуска продукта, когда на каждое шоу приходит уже тысяча зрителей. Статья предлагает архитектуру, расчёт задержек и сценарии отказоустойчивости для каждого паттерна, чтобы вы выбрали мост правильно с первого раза – а не со второго, после неудачного запуска.

Какую задачу решает мост

Комната WebRTC представляет собой короткую, маршрутизируемую напрямую между участниками (peer-to-peer) сессию реального времени для двустороннего общения. Каждый участник – это пиринговый узел (peer), а сервер (Selective Forwarding Unit, или SFU; см. SFU, MCU и Mesh) устанавливает отдельный WebRTC-канал (PeerConnection) для каждого, настраивает шифрование DTLS-SRTP для каждого (см. DTLS, SRTP, TLS, mTLS для медиа), отслеживает состояние ICE (см. ICE, STUN, TURN подробно) и пересылает RTP-пакеты в реальном времени по зашифрованному каналу сессии. Расход ресурсов растёт пропорционально числу участников: N участников × M кбит/с на каждого. Шесть человек в комнате – небольшой SFU и недорогой TURN. А сто тысяч пассивных зрителей – уже нет: каждый зритель остаётся пиринговым узлом, каждый потребляет реальные байты на сервере, и стоимость линейно растёт с числом зрителей.

HLS решает обратную задачу. Издатель формирует последовательность HTTP-сегментов на origin-сервере; HTTP-кэш (edge CDN) скачивает каждый сегмент один раз и отдаёт его всем, кто запрашивает этот URL. Кривая затрат для оператора по сути остаётся плоской при росте числа зрителей, поскольку распределение (fan-out) берёт на себя CDN. Однако за это приходится платить задержкой: даже современный Low-Latency HLS (LL-HLS), описанный в спецификации HLS Authoring Specification от Apple и стандартизируемый в IETF как draft-pantos-hls-rfc8216bis (второе издание, основанное на RFC 8216), обеспечивает доставку с задержкой от 2 до 5 секунд – на порядки медленнее, чем 200–500 мс, которые WebRTC даёт участникам комнаты (см. WebRTC delivery в масштабе).

Мост – это сервис, соединяющий SFU и HLS-origin. Он подключается к комнате WebRTC как специальный серверный участник, получает те же RTP-пакеты, что и любой зритель, декодирует медиа, при необходимости объединяет несколько видео в один кадр, перекодирует результат и упаковывает его в фрагментированный MP4 (CMAF) или сегменты MPEG-TS, после чего передаёт в HLS-origin. Оттуда контент забирает CDN. Зрители broadcast-хвоста получают поток с задержкой 2–10 секунд от реального разговора, в то время как участники комнаты продолжают видеть друг друга в реальном времени. Два разных стека, одно живое событие, мост между ними.

Рисунок 1. Архитектурная форма любого моста WebRTC → HLS. Левая половина – интерактивная и дорогая на каждого пира; правая – вещательная и дешевая за счёт CDN; мост в центре выполняет работу по протоколам, упаковке и (обычно) композиции, соединяя две половины.

Почему SFU не делает это сам

Закономерный первый вопрос: «зачем нужен отдельный сервис – разве SFU не может писать HLS-сегменты?». Ответ – в том, как устроен SFU и под что он оптимизирован. Современный SFU – это высокопроизводительный форвардер RTP. Он принимает зашифрованные RTP-пакеты, читает заголовки и небольшое число полей payload-формата (для определения слоёв симулькаста и SVC; см. Simulcast и SVC), решает, какие пакеты кому пересылать, и выдаёт зашифрованные пакеты на выход. Он специально не декодирует медиа, потому что декодирование требует много ресурсов, а вся ценность SFU в том, что один процесс может обслуживать сотни и тысячи участников на обычном железе. HLS требует декодированных кадров, потому что композиция (отрисовка макета галереи), перекодирование (получение CMAF-совместимого H.264, H.265 или AV1 в нужной ABR-лестнице) и упаковка (запись fMP4- или MPEG-TS-сегментов по HLS-спецификации) работают с кадрами, а не с пакетами.

Команда LiveKit прямо обозначила компромисс в анонсе Universal Egress: «Главная цель egress-системы – не нагружать SFU. Ни при каких обстоятельствах мы не должны влиять на качество и производительность реального аудио и видео». Все продакшн-SFU – mediasoup, Janus, LiveKit, Jitsi Videobridge, Pion (см. Выбор SFU) – пришли к тому же выводу. Мост представляет собой отдельный воркер-процесс, который часто размещается на отдельной машине и масштабируется горизонтально. Он взаимодействует с SFU через один из двух интерфейсов: либо стандартный RTP-форвард выбранных треков, либо серверную WebRTC-подписку, позволяющую мосту присоединиться к комнате как скрытому участнику.

Вот именно поэтому во всех описанных ниже паттернах задействован второй сервис. SFU остаётся простым ретранслятором, а мост берёт на себя основную нагрузку. При этом они операционно независимы.

Паттерн 1 – Пер-трековая запись: минимально жизнеспособный мост

Самый простой мост записывает один файл на трек на участника – без композиции, без живой трансляции, без HLS на первом этапе. SFU запрашивает форвардинг выбранных RTP-потоков на процессор записи по обычному RTP, тот сохраняет сырые RTP-пакеты в отдельный файл на трек в формате типа .mjr (медиа-контейнер Meetecho для Janus). Файл закрывается при выходе участника, а постобработка конвертирует пер-трековые записи в воспроизводимый формат – .webm для видео, .opus или .m4a для аудио – уже после завершения комнаты. Если продукту нужен также broadcast HLS, постобработанный файл передаётся в FFmpeg или GStreamer, которые генерируют HLS-плейлист и сегменты для загрузки в S3 или любой HTTP-оригин для VOD-воспроизведения.

Janus поставляет этот паттерн с момента появления плагина RecordPlay: плагин записывает данные в .mjr, инструмент janus-pp-rec конвертирует их в .webm / .opus, а любой последующий конвейер может использовать HLS. В mediasoup паттерн аналогичен: SFU вызывает transport.consume() для нужного трека, RTP-поток форвардится в отдельный процесс по UDP, а на приёмной стороне FFmpeg или GStreamer записывают файл. Пример записи в Kurento mediasoup-demos подробно описывает обмен SDP и команду FFmpeg.

Сильная сторона паттерна – операционная простота: путь записи реализуется через форвардер RTP по принципу «выстрелил-и-забыл», recorder сохраняет файлы, а пост-обработка запускается уже после завершения сессии. Никаких дедлайнов на живое транскодирование, не нужно поддерживать живой цикл публикации HLS, не требуется сопровождать сложную логику композиции.

Цена – выходной формат пер-трековый: один файл на камеру, один – на микрофон, поэтому сборка единого «видео встречи» требует решения о макете и пост-композиции. Пост-обработка часто занимает много времени: на 60-минутную встречу уходит 5–20 минут на композицию и перекодирование – в зависимости от выбранного макета и целевого кодека.

Для продуктов, где запись предоставляется через несколько минут или часов в виде скачиваемого файла (архивы тренингов, телемедицинские копии для compliance, депозиции), такой подход вполне приемлем. А вот для решений, где запись должна быть доступна почти в реальном времени как живой стрим, – он не подходит.

Реальные числа для Паттерна 1

Трек 720p VP8 со скоростью 1500 кбит/с и аудиотрек Opus на 64 кбит/с в сумме дают около 175 МБ .mjr в час на одного участника. Постобработка записи комнаты с восемью участниками в формате 720p до галереи на 16-ядерном encode-воркере с использованием libx264 и FFmpeg в пресете veryfast занимает 18–25 минут на 60-минутную запись. Затраты времени – это время работы постпроцессора, умноженное на почасовую ставку; затраты на хранение – файлы по трекам плюс итоговый собранный выход.

Паттерн 2 – Серверная композиция: один мост-воркер на комнату

Второй паттерн переносит композицию внутрь мост-воркера, не привязывая воркер к браузеру. Мост подключается к SFU как серверный участник WebRTC (или получает RTP-форварды выбранных треков), запускает медиаконвейер, который декодирует каждый подписанный трек, объединяет декодированные кадры в единый композитный кадр согласно выбранной оператором layout-функции, перекодирует композицию в единый поток H.264 или H.265, упаковывает закодированный поток в фрагментированный MP4 (CMAF) или MPEG-TS, записывает сегменты и плейлист в HLS-origin и обновляет плейлист по мере появления новых сегментов. Конвейер обычно строится на GStreamer или графе libavfilter из FFmpeg; layout-функция – это несколько сотен строк кода, реализующих размещение N видеоисточников в сетку, по принципу active-speaker, в формате presenter-плюс-миниатюры или любой другой раскладке, требуемой продуктом.

Этот паттерн чаще всего реально работает «под капотом» в продакшен-решениях. Деплои на mediasoup обычно запускают отдельный Node- или Python-воркер, который вызывает consume() для треков комнаты, передаёт RTP в GStreamer-элементы webrtcbin / rtpbin и compositor, прогоняет результат через x264enc и hlssink2. Документация GStreamer на hlssink2 описывает элемент и его свойство low-latency; low-latency=true включает CMAF chunked transfer для совместимости с LL-HLS. Деплои на Janus делают аналогичное с плагинами Streaming и VideoRoom плюс внешний композер.

Задержка от спикера до broadcast-зрителя в хорошо настроенном мосту Паттерна 2 – примерно сумма следующих компонентов: RTP-форвард внутри ЦОД (менее 10 мс), декодирование (один кадр, около 33 мс при 30 fps), композит (один кадр, менее 10 мс), кодирование с настройкой на нулевую задержку (один кадр, около 33 мс), сегментация и запись пакетёром (одна часть, около 200 мс для LL-HLS), распространение по CDN (обычно 200–500 мс для первого запроса через origin shield; см. Origin shield и tiered caching), а также требуемый буфер плеера (1–3 части для LL-HLS, то есть 200–600 мс). Итого – 2–5 секунд для LL-HLS и около 8–15 секунд для классического HLS с 6-секундными сегментами и буфером плеера из трёх сегментов. Участники комнаты продолжают видеть друг друга с задержкой 200–500 мс; broadcast-хвост отстаёт на 2–5 секунд при low-latency и на 8–15 секунд при классическом режиме. (См. Задержка glass-to-glass.)

Сильная сторона – низкая задержка: можно собрать настоящий low-latency broadcast-хвост без аренды стороннего SaaS. Цена – операционная: мост-воркер – это stateful процесс в реальном времени, который должен работать всё время жизни комнаты. Layout-код выполняется внутри него и требует поддержки, энкодеру нужна аппаратная акселерация, чтобы масштабироваться эффективно (иначе доминирует CPU), а сегментёр должен успевать за wall-clock, иначе плейлист отстаёт.

Типичная ошибка: считать, что WebRTC в GStreamer заменяет SFU

Распространённое заблуждение: элемент GStreamer webrtcbin можно «подключить» к комнате LiveKit или mediasoup – и мост готов. Это невозможно. webrtcbin – это peer-элемент, который устанавливает соединение 1:1 с другим peer’ом, а не с протоколом сигнализации SFU. Мост должен работать с room-протоколом SFU на уровне control-plane – RoomService.JoinRoom в LiveKit, WebSocket-сигнализирование в mediasoup, API плагина VideoRoom в Janus – и передавать в конвейер GStreamer только RTP-потоки, прошедшие согласование SFU и установку ключей SRTP. Именно поэтому в каждом производственном мосте присутствует тонкая прослойка, специфичная для SFU, перед конвейером GStreamer или FFmpeg – никогда не «один конвейер».

Рисунок 2. Пять продакшен-паттернов моста в 2026 году. Сложность возрастает слева направо; контроль над макетом также растёт – пока в Паттерне 5 макет не фиксируется контрактом с вендором.

Паттерн 3 – Headless-браузер: макет в HTML

Третий паттерн – это то, что LiveKit, Daily и несколько других коммерческих WebRTC-платформ предлагают по умолчанию как room-composite egress. Вместо написания layout-кода внутри мост-воркера оператор создаёт обычную веб-страницу на HTML, CSS и JavaScript, которая отображает желаемый вид комнаты в браузере. Мост-воркер запускает настоящий headless Chrome, открывает эту страницу, страница подключается к комнате через стандартный web-SDK как скрытый участник, браузер рендерит живой композит на canvas, воркер захватывает вывод браузера по кадрам, кодирует, упаковывает в HLS и записывает сегменты.

Документация LiveKit Egress называет это режимом «room composite». Исходники Egress делают ровно то, что описано выше: когда egress-сервис получает RoomCompositeEgressRequest, он запускает Chrome, загружает выбранный шаблон как веб-страницу, подключает её к комнате LiveKit как скрытого участника с помощью JavaScript, а затем захватывает содержимое окна браузера, кодирует его и упаковывает в выходной контейнер – HLS, MP4 или RTMP для передачи downstream. Кодирование выполняет GStreamer внутри LiveKit Egress; его выбрали вместо FFmpeg для room composition, потому что libavfilter оказалось сложнее программно собирать FFmpeg под нужды команды.

Сильная сторона – непревзойдённая гибкость макета: оператор может вывести любой вид, который умеет отображать веб-страница. Active-speaker плюс четыре миниатюры, спикер-плюс-боковой-чат, кастомный брендовый оверлей с логотипом и нижней частью, анимированный переход при смене активного спикера – всё это реализуется через изменение CSS или JavaScript в шаблоне, а не требует правки кода в мост-воркере. Цена – повышенная нагрузка на ресурсы: headless Chrome на каждую активную комнату потребляет 1–2 ГБ оперативной памяти и одно-два ядра CPU ещё до кодирования, поэтому стоимость на комнату выше, чем у чистого GStreamer-конвейера в Паттерне 2. Для комнат с уникальными макетами при умеренном масштабе (типичный SaaS-продукт для конференций или вебинаров) такой компромисс обычно оправдан. А вот для комнат с одним фиксированным макетом и очень большим масштабом (например, платформа для спорт-беттинга с 10 000 live-событий) Паттерн 2 оказывается дешевле.

Реальные числа для Паттерна 3

Room-composite egress в стиле LiveKit под headless Chrome в разрешении 1280×720 при 30 кадрах в секунду с x264enc в режиме zero-латентного тюнинга и с LL-HLS-выходом потребляет примерно 1,6 ГБ ОЗУ и 1,8 ядра CPU на активную комнату на современном процессоре Intel Xeon. Общая задержка от активного спикера до зрителя через LL-HLS составляет 3–5 секунд при конфигурации с сегментами по 200 мс и 8–15 секунд – при использовании классического HLS с сегментами длительностью 4–6 секунд. Команда LiveKit явно отмечает, что RTMP-ретрансляция из LiveKit Egress добавляет встроенный буфер в 1–2 секунды поверх задержки LL-HLS ради надёжности канала – то есть путь WebRTC → LiveKit Egress → RTMP → downstream-HLS накладывает этот буфер на собственную задержку моста, что зачастую выводит общую задержку glass-to-glass за 6 секунд.

Паттерн 4 – WebRTC → RTMP с выходом на отдельный live-энкодер

Четвёртый паттерн убирает HLS-упаковку из мост-воркера и передаёт её существующему live-энкодеру: AWS Elemental MediaLive, Wowza Streaming Engine, NimbleStreamer, инсталляции Ant Media Server, Mux Video, Cloudflare Stream Live или Amazon IVS. Мост-воркер по-прежнему выполняет WebRTC-подписку и композицию, затем перекодирует композит, оборачивает поток в RTMP и отправляет его в downstream live-энкодер. Тот формирует ABR-лестницу (см. Построение битрейт-лестницы), выполняет CMAF-упаковку, генерирует HLS- и DASH-плейлисты, вставляет рекламные метки SCTE-35 и интегрируется с CDN. На этом работа мост-воркера завершается – он публикует один высокобитрейтный RTMP-поток на указанный endpoint.

Это доминирующий паттерн для любого продукта, у которого уже настроена видеоинфраструктура для не-WebRTC-контента, и который хочет добавить интерактивный WebRTC-источник. Amazon Chime SDK предоставляет именно такой паттерн в виде Live Connector, который захватывает встречу Chime и транслирует RTMPS в Amazon IVS или AWS Elemental MediaLive – работу с HLS выполняет downstream-сервис. Dolby OptiView (бывший Millicast) поддерживает приём RTMP / RTMPS, который трансмуксируется в WebRTC для низколатентного вывода и может быть преобразован в HLS через отдельный downstream-сервис. Этот паттерн применим к любой комбинации SFU и live-энкодера, при условии, что мост-воркер можно настроить на отправку RTMP по произвольному URL.

Сильная сторона – операционная простота: команда, у которой уже работает кластер live-энкодеров, не обязана осваивать второй пакетёр. Цена – задержка: каждый RTMP-хоп добавляет буферизацию с обеих сторон (RTMP-отправитель издателя и RTMP-приёмник получателя), live-энкодер вносит свою сегментирующую задержку, а плеер HLS – свой буфер. Реалистичная цифра – 6–12 секунд glass-to-glass; sub-5 секунд – задача сложная.

Почему RTMP в 2026 году, когда протокол в целом умирает

RTMP – lingua franca для ingest у live-энкодеров (см. RTMP в 2026: мёртвый протокол, бессмертный дефолт). Каждый live-энкодер за последние 15 лет поддерживает RTMP, а сочетание TCP-доставки, предсказуемой структуры пакетов и повсеместно доступных серверных парсеров делает его естественным выбором – самым простым путём между кастомным мостом и любым коммерческим пакетёром. SRT (см. SRT подробно) – современная альтернатива для передачи через публичный интернет, и лишь небольшое число мостов умеет транслировать SRT вместо RTMP. Однако внутри ЦОД RTMP остаётся достаточно быстрым и повсеместно поддерживаемым. Мосту безразлично, что RTMP умирает в end-to-end-доставке: он использует его как локальный interconnect между двумя сервисами, и на этом сегменте возраст протокола не имеет значения.

Паттерн 5 – Управляемые мосты

Пятый паттерн – «купить мост как SaaS». Вендоры, предлагающие в 2026 году полноценный end-to-end-мост WebRTC → HLS: LiveKit Cloud (Universal Egress с выводом в HLS / MP4 и RTMP-ретрансляцией), Dolby OptiView (платформа Millicast с доставкой по WHEP и HLS-egress через партнёрские интеграции), Amazon Chime SDK Live Connector, Cloudflare Stream (с оговоркой ниже), 100ms, Vonage Video API, Daily, Twilio Programmable Video и несколько broadcast-уровневых специалистов, таких как Norsk и Phenix. Оператор реализует WebRTC на стороне платформы и заключает контракт, в который включён мост в HLS или DASH на стороне egress. Вендор скрывает всё, что описано в паттернах 2, 3 и 4.

Типичный компромисс managed-сервиса: оператор выпускает фичу за квартал вместо года, поминутная стоимость выше, чем у self-hosted-моста на собственном железе, гибкость макета ограничена тем, что позволяет вендор в своих шаблонах (room composite в LiveKit – это HTML-шаблон; у Daily – один из небольшого набора фиксированных пресетов), а roadmap вендора определяет, когда появятся новые функции. Большинство продуктов, внедряющих мост в первом релизе конференций, начинают с этого подхода; часть переходит к Паттерну 2 или 3, когда объёмы оправдывают инженерные затраты на «вкорачивание» моста.

Оговорка по Cloudflare Stream

Cloudflare Stream поддерживает WebRTC-ingest и egress через WHIP и WHEP (см. WHIP – WebRTC-ingest, RFC 9725 и WHEP – HTTP-egress для WebRTC). По состоянию на середину 2026 года WebRTC-документация Cloudflare прямо указывает: WHIP и WHEP должны использоваться совместно – нельзя публиковать поток через WHIP и воспроизводить его через HLS или DASH в рамках одного и того же Cloudflare Stream-ресурса. Чтобы получить HLS-трансляцию из WebRTC-потока, размещённого в Cloudflare, оператору необходимо, чтобы мост-воркер подписался на поток через WHEP, перекодировал его и отправил по RTMP (или использовать Live RTMP-ingest от Cloudflare) в Cloudflare Stream Live-вход, который уже сгенерирует HLS. Решение работает, но это не прямой «WHIP-вход, HLS-выход» – одношаговый вызов в API Cloudflare. Другие вендоры, такие как LiveKit, Mux и AWS, объединяют обе стадии в единый управляемый конвейер; именно поэтому LiveKit Cloud в 2025–2026 годах захватил непропорционально большую долю рынка WebRTC-мостов для трансляции в HLS.

Как выбрать паттерн – дерево решений для продакшена

Честное дерево решений начинается с трёх вопросов, заданных в определённом порядке.

  1. Broadcast-зрители – это фича или побочный эффект? Если основной режим продукта – конференции или телемедицина, а запись нужна только для compliance и никогда не просматривается живой аудиторией, правильным выбором будет Паттерн 1 (пер-трековая запись с офлайн-постобработкой). Мост в этом случае – это батчевая задача. Ничего сложного не должно работать в реальном времени.
  2. Если broadcast-зрители – фича, их сотни или многие тысячи? Для сотен зрителей у оператора обычно хватает трафикового бюджета на прямую доставку через WebRTC в хвост (например, с использованием WHEP из Паттерна 5 или self-hosted WebRTC-egress), и HLS остаётся опциональным. При тысячах зрителей HLS становится обязательным, поскольку стоимость масштабирования WebRTC резко возрастает – и мост должен быть реалтаймовым конвейером, что указывает на Паттерны 2, 3, 4 или 5.
  3. Продукту нужен уникальный макет или достаточно одного из трёх–четырёх стандартных? Уникальный макет (кастомный брендинг, оверлеи, переходы) обычно требует Паттерна 3 (headless-браузер, HTML/CSS-шаблоны) – вся работа с компоновкой переносится в HTML, а не в медиаконвейер, и это наиболее экономичный способ поддержки. Стандартные макеты при очень больших объёмах выгоднее реализовывать через Паттерн 2 (GStreamer-конвейер с compositor-элементом) – он значительно дешевле на комнату, но менее гибкий. Стандартные макеты при умеренных нагрузках, которые команда не хочет поддерживать самостоятельно, – очевидный случай для Паттерна 5 (управляемый мост).

Расчётный пример с арифметикой. Допустим, продукт – это B2C live-shopping-платформа. В комнате один ведущий по WebRTC; broadcast-хвост – 30 000 зрителей по HLS. Каждый зритель смотрит 720p на 2500 kbps 45 минут шоу. Прямая WebRTC-доставка 30 000 зрителям по 2,5 Mbps составила бы 75 Gbps egress за всё шоу. За CDN-трафик по $0,005/ГБ это 75 Gbps × 2700 с ÷ 8 = 25 312 ГБ × $0,005 = $126 за шоу – но только при условии, что WebRTC-ферма серверов в принципе способна выдержать 75 Gbps, что предполагает наличие серьёзного слоя WebRTC-дистрибуции (каскадные SFU и регионы; см. WebRTC в масштабе). HLS-доставка того же контента через multi-CDN (см. Архитектура multi-CDN) потребляет те же 25 312 ГБ, но цена за ГБ для кэшируемых HLS-сегментов на таких объёмах – $0,002–$0,003, то есть около $63 за шоу. Стоимость CPU и упаковки моста – фиксированная добавка (Паттерны 2 или 3 – $1–$3 за комнато-час), которая нивелируется экономией уже после пары тысяч зрителей. Задержка у broadcast-зрителей – на 3–5 секунд позади ведущего – нормальна для шоппинга, но неприемлема для аукциона. Выбор для шоппинга – Паттерн 2 или Паттерн 3 с LL-HLS; выбор для аукциона – Паттерн 5 с WHEP и без HLS-хопа вообще.

Рисунок 3. Бюджет задержки glass-to-glass для каждого паттерна моста, разбитый на семь стадий с заметной задержкой. Паттерн 1 пропущен – он выдаёт файл, а не живой поток; четыре паттерна с живым видео попадают в диапазон 2–15 секунд, причём выбор LL-HLS против классического HLS оказывает большее влияние, чем выбор паттерна.

Что реально работает в продакшене по SFU

Пять основных open-source SFU имеют свою идиоматическую историю моста в 2026 году.

LiveKit поставляет Egress в виде отдельного воркер-бинарника, реализующего все четыре паттерна (Паттерны 2, 3, 4 и версию «Паттерна 5» при запуске в LiveKit Cloud). Egress – самый opinionated из пяти компонентов: композиция комнаты – через HTML-шаблон, кодирование – с помощью GStreamer, HLS-выход – через hlssink с опциональной поддержкой LL-HLS, RTMP-выход – на downstream-энкодеры или напрямую в Twitch / YouTube. Сообщество стандартизировалось вокруг этого решения.

mediasoup не поставляет медиамост в составе core-библиотеки. Паттерн заключается в том, чтобы написать отдельный воркер на Node.js или Python, который вызывает transport.consume() для нужных треков, форвардит полученный RTP в процесс GStreamer или FFmpeg через обычный RTP и оставляет за ними композицию, кодирование и упаковку. Сообщество mediasoup поддерживает несколько референсных реализаций – в первую очередь mediasoup3-record-demo и пример записи Kurento mediasoup-demos. В продакшен-деплоях это обычно дополняется внутренним layout-сервисом, который предоставляет сама компания.

Janus поставляет плагин RecordPlay для записи по трекам в .mjr и плагин Streaming для повторной трансляции. Несколько развёртываний Janus используют кастомный плагин или внешний процесс для работы с HLS; документация команды Meetecho подробно описывает механизм записи, а janus-pp-rec – официальный пост-процессор.

Jitsi Videobridge использует Jibri (Jitsi Broadcasting Infrastructure) в качестве моста. Jibri по сути реализует Паттерн 3: headless Chrome подключается к встрече как скрытый участник, захватывает экран и либо записывает в MP4 для архива, либо транслирует по RTMP в downstream (обычно – YouTube Live для community-версии Jitsi Meet). Jibri не генерирует HLS напрямую – этот шаг выполняется на стороне downstream.

Pion – это библиотека на Go, а не предвзятый сервер, и мосты на основе Pion обычно реализуются индивидуально: команда разрабатывает подписку на комнату, логику композиции (часто с использованием Go-обёрток для GStreamer через go-gst, как это делает LiveKit) и схему кодирования и упаковки. Twitch и несколько других крупных WebRTC-развёртываний используют Pion в продакшене с собственными стеками мостов.

Ловушка: WebRTC bandwidth-estimator и тихое тротлирование моста

Тонкий режим отказа, в который рано или поздно попадает каждая команда, – взаимодействие между bandwidth-estimator у SFU (см. Оценка полосы в WebRTC) и мост-воркером. Мост подписывается на комнату как обычный участник, то есть SFU воспринимает его как реального подписчика и применяет к потоку, идущему к мосту, стандартную логику управления перегрузками – Google Congestion Control или transport-cc. Если связь между мостом и SFU временно теряет пакеты (например, из-за шумного intra-DC канала или перегруженного TURN-ретранслиатора), SFU понижает слой simulcast или SVC, передаваемый мосту, и HLS-выход моста незаметно теряет в разрешении. Участники в комнате с надёжными каналами продолжают видеть высокое качество; а те, кто подключён через broadcast-канал, видят 720p или 360p – хотя ведущий никогда не транслировал в 360p.

Решение – явно подключить мост к самому высокому доступному уровню и зафиксировать его, рассматривая мост как «VIP-подписчика», которого SFU никогда не понижает. LiveKit Egress, Jibri и большинство продакшен-мостов делают это по умолчанию; самописный мост по Паттерну 2 требует явной настройки preferred-layer при подписке и отключения layer-downgrade для этого подписчика. У SFU все необходимые настройки есть; режим отказа – просто не воспользоваться ими.

Где здесь Фора Софт

Фора Софт поставляет WebRTC-решения с 2008 года и использует мосты WebRTC → HLS в продакшене во всех ключевых отраслях: видеоконференции, телемедицина, e-learning и live-торговля. В телемедицине чаще всего применяется Паттерн 1 – создание compliance-копии каждого визита, которая сохраняется в архив на S3 и никогда не транслируется в реальном времени. Инженерная работа здесь сосредоточена на регуляторных метаданных: временных метках, идентификаторах участников и политике хранения.

В e-learning и live-торговле чаще востребованы Паттерн 2 или Паттерн 3 – низколатентный публичный HLS, позволяющий подключать к сессии значительно большую пассивную аудиторию. Здесь основная инженерная задача – настройка layout-шаблонов, оптимизация энкодера под целевую ABR-лестницу и обеспечение операционной дисциплины при управлении stateful-парком мостов, который масштабируется автоматически в зависимости от количества активных комнат.

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

Расчётный пример: бюджет задержки для LL-HLS-стриминга (LL-HLS-моста)

Допустим, продукт для live-шопинга работает по Паттерну 2 с выходом LL-HLS (LL-HLS). Ведущий транслирует видео в разрешении 1080p, кодированное по стандарту H.264, со скоростью 4 Мбит/с; мост расположен в том же центре обработки данных, что и SFU; конфигурация LL-HLS предусматривает сегменты длиной 200 мс и целевой временной интервал 6 секунд; целевой буфер плеера рассчитан на две части.

По стадиям:

  • Захват микрофона у спикера до энкодера: 30 мс.
  • Pacing H.264-энкодера у спикера (libwebrtc default): 30 мс.
  • Транзит RTP от спикера до SFU по публичному интернету: 40 мс.
  • Форвард SFU пакета мосту-subscriber’у (внутри дата-центра, подмиллисекундная сеть плюс pacing SFU): 5 мс.
  • Декодер моста (один кадр при 30 fps): 33 мс.
  • Compositor (один кадр): 8 мс.
  • Энкодер моста в режиме zero-latency (один кадр): 33 мс.
  • Пакетёр закрывает 200-мс часть и пишет её в origin: 200 мс.
  • HTTP-распространение origin → CDN edge: 80 мс.
  • Загрузка по preload-hint у плеера и буфер из двух частей: 400 мс.

Сумма: 30 + 30 + 40 + 5 + 33 + 8 + 33 + 200 + 80 + 400 = 859 мс – время от захвата до первого декодируемого байта у зрителя, плюс внутренний темп декодирования у зрителя и одна отрисовка: ещё около 100 мс. Итоговое время «стекло к стеклу» – 950 мс, или 1,1 с при оптимальной конфигурации и качественном плеере (hls.js с поддержкой LL-HLS; см. hls.js подробно). Увеличение буфера плеера до четырёх сегментов (что типично для стабильности) доводит итоговое время до 1,4–1,6 с. Классическая конфигурация HLS с 4-секундными сегментами и буфером плеера из трёх сегментов даёт задержку 14–16 с – вполне приемлемо для продукта, где основной интерактив – чат, а ведущий естественно делает паузы под хвост трансляции.

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

Сводная таблица – пять паттернов рядом

ПаттернМесто композицииLive или batchТипичный glass-to-glassКастомные макетыСтоимость на комнату (относительная)Сложность для оператора
1. Пер-трековая записьНет (пер-трековые файлы)Batch (пост-процесс)Не live – файл позжеНет (только в пост-композиции)НизкаяНизкая
2. Server-side компонентМост-воркер (GStreamer)Live2–5 с LL-HLS, 8–15 с classicОграничены (изменения в коде)НизкаяВысокая
3. Headless-браузерМост-воркер (HTML/CSS)Live3–5 с LL-HLS, 8–15 с classicБезграничныСредняяСредняя
4. RTMP в live-энкодерМост + downstream-энкодерLive6–12 с типичноОграничены со стороны мостаНизкая на мосту; энкодер биллится отдельноСредняя (два сервиса)
5. Управляемый мост (SaaS)ВендорLive3–8 с типичноВендорские шаблоныСамая высокая поминутноСамая низкая

Ключевые выводы

  • Любой WebRTC-продукт рано или поздно нуждается в egress в HLS или DASH для пассивного хвоста; мост – стандартное решение.
  • В продакшене используются пять паттернов; выбор зависит от размера аудитории, гибкости макета и допустимой задержки.
  • SFU намеренно не генерирует HLS самостоятельно – композиция и кодирование выполняются в отдельном воркере, подписанном на комнату.
  • LL-HLS через хорошо настроенный мост по Паттерну 2 или 3 обеспечивает задержку 2–5 секунд от экрана до экрана; классический HLS – 8–15 секунд.
  • Настройте мост на максимальный слой – иначе broadcast-хвост незаметно снизит разрешение из-за управления перегрузкой в SFU.

Что прочитать дальше

CTA

  • Поговорить с инженером по стримингу – забронируйте 30-минутную встречу по определению задач с архитектором Фора Софт.
  • Посмотреть наши кейсы – WebRTC, телемедицина, live-shopping, e-learning.
  • Скачать decision sheet WebRTC → HLS – пять паттернов, бюджеты задержек и дерево решений в одном PDF: Скачать.

Строите такую систему?

Подберём параметры кодирования под ваш контент и посчитаем стоимость доставки до старта разработки.