Содержание статьи +
- TL;DR
- Почему это важно
- Что такое WebRTC на самом деле
- Пробел в сигнализации
- SDP – как два узла описывают, что они будут передавать
- ICE, STUN, TURN – как узлы находят рабочий путь
- DTLS, SRTP, RTP – что реально летит по проводам
- Серверные архитектуры: mesh, SFU, MCU, гибрид
- Полный звонок от начала до конца
- Числовой пример: реальная стоимость продукта с высоким энергопотреблением
- Частые ошибки и подводные камни
- Где находится Фора Софт
- Дерево решений – топология за пять вопросов
- Ключевые выводы
- Что читать дальше
- Источники
TL;DR
WebRTC – Web Real-Time Communication – это открытый стандарт, позволяющий браузеру, телефону, серверу или встроенной камере обмениваться аудио, видео и данными с другим устройством – будь то браузер, телефон, сервер или камера – примерно за полсекунды, без необходимости устанавливать плагины или использовать специализированные клиенты. На его основе построены Google Meet, голосовые каналы Discord, Microsoft Teams, веб-клиент Zoom, телемедицинские порталы, онлайн-уроки, системы видеонаблюдения, аукционы в реальном времени и почти все современные виджеты поддержки. К 2026 году WebRTC обеспечит подавляющую часть низколатентного интерактивного видео в интернете. Чтобы эффективно использовать этот стандарт, важно понимать четыре ключевых момента, которые часто путают новички: SDP – язык, на котором два узла договариваются о формате передаваемых данных; ICE, STUN и TURN – технологии, помогающие найти рабочий сетевой путь через брандмауэры и NAT; и выбор между архитектурами SFU и MCU, определяющий, сможет ли ваш продукт масштабироваться с десяти до десяти тысяч участников. Эта статья объясняет каждый элемент простым языком и завершается решением в виде дерева, которое можно применить к реальному продукту без участия инженера.
Почему это важно
Если вы создаёте что угодно, где двум или более людям нужно видеть и слышать друг друга в реальном времени – конференц-инструмент, виртуальный класс, консультацию врача, демонстрацию продукта, видеочат поддержки, live-шопинг с интерактивными гостями, мультиплеер с голосовой связью, систему видеонаблюдения с динамиком, умный дверной звонок – в 2026 году WebRTC по умолчанию используется как транспортный слой для аудио и видео. Его легко выбрать; гораздо сложнее – принять четыре ключевых решения, которые технология требует до написания первой строки кода.
Где разместить ваш signalling-сервер? Как пробивать корпоративные firewalls? Сколько TURN-трафика вы готовы оплачивать? И какую серверную архитектуру использовать, когда участников станет больше трёх?
Приняв эти решения правильно, команда из пяти инженеров может выпустить продукт, не уступающий Zoom по качеству и стоимости. Приняв их неправильно – потратите полгода на борьбу с собственной инфраструктурой и ещё столько же на объяснения корпоративным клиентам, почему звонки постоянно обрываются.
Эта статья даёт понятную ментальную модель, чтобы с первого раза принять все четыре ключевых решения. Мы начнём с того, что на самом деле делает WebRTC внутри браузера, разберём процесс согласования параметров (SDP), поиск сетевого пути (ICE, STUN, TURN) и серверные архитектуры, масштабируемые за пределы двух участников (mesh, SFU, MCU, гибрид). Каждая часть написана так, чтобы продакт-менеджер, основатель или операционный руководитель мог разобраться в ней без предварительных знаний. В конце – дерево решений и скачиваемая шпаргалка. Прочитав статью, вы будете готовы прийти на архитектурное ревью и ответить на вопрос: «Как нам построить call-слой?» – с выбором топологии, оценкой бюджета на TURN и обоснованными аргументами.
Что такое WebRTC на самом деле
Прежде чем говорить о протоколах, разберёмся, что такое WebRTC и чем он не является. Слово «WebRTC» используют в трёх разных смыслах, и их смешение – главная причина путаницы.
Первое значение – это JavaScript API от W3C: объекты RTCPeerConnection, RTCDataChannel и getUserMedia, которые браузер предоставляет веб-страницам. С ними работает фронтенд-разработчик. Спецификация 1.0 получила статус Recommendation от W3C 26 января 2021 года и сегодня реализована во всех современных браузерах. Эволюция 2026 года называется WebRTC-NV («next version») и добавляет хуки для машинного обучения, доступ к raw-медиаданным и интеграцию с WebTransport и WebCodecs – всё это обратно совместимо с 1.0, так что существующие приложения продолжают работать. 1 2
Второе значение – это стек протоколов IETF, форматы передачи данных, которыми обмениваются два узла в сети: SDP, ICE, STUN, TURN, DTLS, SRTP, RTP, RTCP, SCTP. Каждый из них описан в отдельном RFC. С этим работает сетевой инженер. Тот же стек используют нативные мобильные приложения, headless-серверы и встроенные камеры, которые никак не связаны с браузерами. 3
Третье значение – media pipeline по умолчанию: видео в форматах H.264 или VP8, аудио в формате Opus, автоматическое подавление эха, jitter-буфер, маскировка потерянных пакетов, управление загрузкой канала. С этим работает media-инженер. Большая часть pipeline скрыта от разработчика, и вы замечаете её только тогда, когда что-то ломается.
Когда в этой статье мы говорим «WebRTC», мы имеем в виду сразу три аспекта: API, которое вызывает веб-страница, протоколы, по которым передаются байты, и медиапайплайн, скрывающий сложность между ними.
Чем WebRTC не является – это протоколом сигнализации. WebRTC объясняет двум узлам, как передавать аудио, видео и данные, после того как они согласовали параметры, но сам процесс согласования – как именно они обменяются этими параметрами – намеренно остаётся на усмотрение разработчика приложения. Именно этот пробел – самое неожиданное в WebRTC и мост, который нужно построить, прежде чем всё остальное обретёт смысл.
Пробел в сигнализации
Представьте двух людей, находящихся в разных комнатах и желающих начать разговор по телефону. Прежде чем заговорить, им нужен посредник – например, секретарь, телефонный номер или обмен письмами, – чтобы познакомить их, сообщить каждому, где находится другой, и помочь договориться о языке общения. Только после этого они могут положить трубку и общаться напрямую.
WebRTC устроен так же. Два браузера не могут самостоятельно найти друг друга в публичном интернете. Кто-то снаружи WebRTC должен их соединить. Этот «кто-то» называется signalling-каналом, и вы создаёте его самостоятельно.
Построить сигнальный канал несложно. К 2026 году почти каждый WebRTC-продукт использует один из трёх подходов: WebSocket-соединение с небольшим сервером, который разработчик создаёт самостоятельно; server-sent events для одностороннего сигналинга; или сторонний real-time backend, например Firebase, Ably, Pusher или Supabase Realtime. Единственная задача сигнального сервера – передавать несколько небольших текстовых сообщений (SDP offer, SDP answer и поток ICE-кандидатов) от одного участника к другому, пока устанавливается соединение. Как только связь установлена, сигнальный сервер больше не нужен: аудио и видео передаются напрямую между участниками.
Выбор протокола сигнализации – за вами. Можно разработать собственный WebSocket-протокол, использовать SIP, XMPP или реализовать REST API. Спецификации WebRTC всё равно – это и свобода (вы берёте то, что подходит вашему стеку), и налог (каждый WebRTC-проект по новой пишет один и тот же скучный код сигнализации). Практические ограничения – два: канал должен быть надёжным (сообщения не должны теряться) и двусторонним (оба участника должны иметь возможность отправлять сообщения друг другу в реальном времени).
Мы подчёркиваем эту мысль, потому что именно на signalling-сервере падают большинство ранних WebRTC-решений. Слабый сигналинг – нестабильные переподключения WebSocket, потерянные сообщения, высокие round-trip-задержки между регионами – приводит к звонкам, которые кажутся обрывистыми, хотя аудио и видео работают нормально, а теряются только сообщения на этапе установочного handshake. Сначала наладьте signalling-сервер, потом вините WebRTC.
С этим разобрались – теперь посмотрим, что именно передаёт сигнальный канал. Почти всю работу выполняют два сообщения, и оба написаны на языке под названием SDP.
SDP – как два узла описывают, что они будут передавать
SDP – Session Description Protocol – это текстовый формат, с помощью которого два WebRTC-узла обмениваются информацией о том, что они будут передавать и как. Изначально он был разработан для SIP-телефонии в конце 1990-х годов, формализован как RFC 8866 в 2021 году и адаптирован для WebRTC, поскольку ничего лучшего не существовало. 4 В 2026 году каждый WebRTC-обмен ключами по-прежнему проходит через SDP offer и SDP answer, и обойти этот механизм невозможно.
Структура в целом проста. Узел A – offerer – формирует SDP-блок, в котором последовательно идут: заголовок уровня сессии с информацией о тайминге и соединении, затем одна или несколько media-секций, каждая из которых описывает отдельный аудио-, видео- или данных-поток. В каждой media-секции перечислены кодеки, поддерживаемые offerer’ом для кодирования и декодирования, криптографические ключи, сетевые параметры и длинный список feature-флагов. Этот offer передаётся по сигнальному каналу узлу B – answerer, который формирует свой SDP-блок: выбирает по одному кодеку для каждой media-секции, подставляет свои ключи и отправляет блок обратно. Как только обе стороны получили оба блока, у них есть достаточно информации, чтобы начать передачу данных.
Реальный SDP-offer действительно пугает при первом взгляде. Типичный offer для аудио и видео занимает около 80 строк и выглядит примерно так (сильно сокращённо):
v=0
o=- 4611732057311473934 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=msid-semantic: WMS stream-id-1
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:F7gI
a=ice-pwd:x9cml/YzichV2+XlhiMu8g
a=fingerprint:sha-256 D2:FA:0E:C3:22:59:5E:14:95:69:92:3D:13:B4:84:24:2C:C2:A2:C0:3E:FD:34:8E:5E:EA:6F:AF:52:CE:E6:0F
a=setup:actpass
a=mid:0
a=sendrecv
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:F7gI
a=ice-pwd:x9cml/YzichV2+XlhiMu8g
a=fingerprint:sha-256 D2:FA:0E:C3:22:59:5E:14:95:69:92:3D:13:B4:84:24:2C:C2:A2:C0:3E:FD:34:8E:5E:EA:6F:AF:52:CE:E6:0F
a=setup:actpass
a=mid:1
a=sendrecv
a=rtpmap:96 VP8/90000
a=rtpmap:97 rtx/90000
a=rtpmap:98 H264/90000
a=rtpmap:99 rtx/90000
a=rtpmap:100 AV1/90000
a=rtpmap:101 rtx/90000
a=rtpmap:102 H265/90000Три вещи в этом блоке важны для читателя без технического бэкграунда.
Во-первых, offer перечисляет несколько кодеков в порядке приоритета – сначала VP8, затем H.264, затем AV1, затем H.265 – а answerer должен выбрать один. Так WebRTC обходит зоопарк кодеков 2026 года: каждый браузер поддерживает свою комбинацию, и handshake позволяет им найти общий язык, не требуя от разработчика хардкодить ничего. Answer обычно оставляет только самый приоритетный из общих кодеков и отбрасывает остальные.
Во-вторых, каждая media-секция содержит криптографический отпечаток (a=fingerprint:sha-256 ...) – это отпечаток публичного ключа сертификата, который узел будет использовать для шифрования media-потока через DTLS (об этом ниже). Отпечаток передаётся по (недоверенному) signalling-каналу и позволяет каждой стороне убедиться, что зашифрованное соединение действительно установлено с правильным партнёром – даже если злонамеренный signalling-сервер попытается подменить свои ключи.
В-третьих, секция с a=ice-ufrag и a=ice-pwd – это ICE-учётные данные: короткий логин и пароль, которые стороны используют при поиске пути, чтобы подтвердить, что пакеты в сети действительно отправлены ожидаемым партнёром, а не атакующим, который может затоплять тот же порт случайными пакетами.
Получатель сравнивает предложение (offer) со своими возможностями и формирует ответ (answer). Ответ имеет ту же структуру, но содержит только те кодеки и параметры, на которые получатель соглашается:
v=0
o=- 7234890123456789012 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=ice-ufrag:zB2K
a=ice-pwd:KqM3vR8wTpL5xN7yJ4hC6f
a=fingerprint:sha-256 8A:1C:E4:55:32:11:9B:7D:F6:21:CA:83:44:65:18:97:BB:09:DD:5C:7E:23:F1:48:99:0A:6B:1E:32:54:76:88
a=setup:active
a=mid:0
a=sendrecv
a=rtpmap:111 opus/48000/2
m=video 9 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 0.0.0.0
a=ice-ufrag:zB2K
a=ice-pwd:KqM3vR8wTpL5xN7yJ4hC6f
a=fingerprint:sha-256 8A:1C:E4:55:32:11:9B:7D:F6:21:CA:83:44:65:18:97:BB:09:DD:5C:7E:23:F1:48:99:0A:6B:1E:32:54:76:88
a=setup:active
a=mid:1
a=sendrecv
a=rtpmap:100 AV1/90000
a=rtpmap:101 rtx/90000Здесь answerer оставил Opus для аудио и AV1 для видео, отбросив всё остальное. С этого момента обе стороны точно знают, какие байты будут передаваться и как именно они будут зашифрованы.
Честная оценка SDP такова: это самая уродливая часть WebRTC и почти наверняка та, которую заменят в течение следующего десятилетия. Существует альтернативный API под названием ORTC, в котором SDP вообще не используется – вместо него применяются структурированные JavaScript-объекты; сейчас некоторые его элементы интегрируются в WebRTC-NV. 5 Но в production-коде 2026 года вы всё ещё отправляете SDP offer и SDP answer и делаете вид, что формат имеет смысл. Хорошая новость в том, что SDP почти никогда не читают и не пишут вручную. Браузер генерирует его через RTCPeerConnection.createOffer() и обрабатывает с помощью setRemoteDescription(), а ваша задача – просто передавать эти строки туда-обратно по своему сигнальному каналу.
ICE, STUN, TURN – как узлы находят рабочий путь
Когда стороны знают что они будут отправлять, им нужно понять куда. Звучит банально – казалось бы, каждая сторона просто передаёт другой свой IP-адрес, – но публичный интернет 2026 года представляет собой полосу препятствий из NAT, брандмауэров, корпоративных прокси, мобильных операторов и домашних роутеров, которые в совокупности мешают двум произвольным устройствам общаться напрямую. Фреймворк, решающий эту задачу, называется ICE и опирается на два вспомогательных протокола – STUN и TURN, которые являются «рабочими лошадками» любого WebRTC-развёртывания.
Проблема в том, что у большинства потребительских устройств в современном интернете нет публичного IP-адреса. Ноутбук в домашней сети подключён к роутеру, который имеет один публичный IP-адрес, а все устройства в доме скрыты за ним с помощью Network Address Translation (NAT). Телефон в сотовой сети находится за двумя-тремя уровнями carrier-grade NAT и может получать новый внешний IP-адрес каждые несколько минут. Ноутбук в офисе защищён файерволом, который блокирует всё, кроме разрешённых портов. Когда узел A пытается отправить пакет на локальный IP-адрес узла B – например, 192.168.1.42 – пакет покидает сеть A, попадает в публичный интернет и теряется, потому что в публичной сети никто не знает, где находится 192.168.1.42.
Решение должно для каждой пары узлов находить адресную пару, которая реально работает, и делать это быстро, без ручной настройки. Такое решение – ICE (Interactive Connectivity Establishment), описанное в RFC 8445 и уточнённое десятками последующих RFC. 6
Как ICE собирает кандидатов
ICE работает так: каждый узел перечисляет все возможные сетевые адреса, по которым его можно достичь – ICE-кандидаты, – обменивается этим списком с другой стороной и затем последовательно проверяет все пары кандидатов, пока не найдётся рабочая. Важны три типа кандидатов:
Host-кандидаты – локальные IP-адреса на сетевых интерфейсах устройства: адрес домашней сети 192.168.x.x, Ethernet, VPN. Host-кандидаты работают, если оба узла находятся в одной сети (например, в одном офисе или подключены к одному домашнему WiFi). Между двумя случайными устройствами в интернете они почти никогда не работают.
Server-рефлексивные кандидаты – это публичный адрес, который NAT-устройство показывает внешнему миру с точки зрения публичной точки наблюдения. Чтобы определить этот адрес, узел отправляет небольшой запрос на STUN-сервер – Session Traversal Utilities for NAT, RFC 8489 – и получает ответ: «публичный IP и порт, с которых я вижу твой запрос, – X.X.X.X:Y». 7 STUN по умолчанию работает на UDP-порту 3478. Гениальность STUN заключается в том, что сервер практически ничего не делает: он просто смотрит на адрес отправителя входящего пакета и возвращает его в ответ. Публичные STUN-серверы бесплатны, легковесны и используются на миллионах роутеров. Один из самых известных – у Google: stun:stun.l.google.com:19302.
Relay-кандидаты – это адреса на TURN-сервере (Traversal Using Relays around NAT, RFC 8656), которые узел зарезервировал в качестве резервного варианта. 8 Когда два узла не могут установить прямое соединение ни при какой комбинации host- или server-рефлексивных адресов (обычно из-за того, что хотя бы один из них находится за симметричным NAT или строгим корпоративным файрволом), они передают медиа через TURN-сервер, который ретранслирует данные другому узлу. TURN-сервер видит и пересылает каждый байт голосового потока – следовательно, он оплачивает весь трафик и добавляет задержку в 5–50 мс в зависимости от своего географического расположения.
Каждый узел собирает от 2 до 10 кандидатов, обменивается ими с другой стороной через сигнальный канал и проверяет каждую пару в порядке приоритета: сначала host–host, затем host–server-рефлексивный, далее server-рефлексивный–server-рефлексивный и, наконец, любые через релей. Каждую пару тестируют небольшим STUN-запросом в обоих направлениях; побеждает первая пара, в которой оба теста проходят успешно, и медиа начинает передаваться по этому пути.
Trickle ICE
Наивная реализация ICE заставляет звонок ждать, пока обе стороны соберут всех кандидатов, прежде чем отправить offer. На медленной сети или при перегруженном TURN-сервере этот процесс может занять несколько секунд – и всё это время пользователь видит надпись «connecting…». Решение – Trickle ICE, описанный в RFC 8838: каждая сторона сразу отправляет SDP-offer с теми кандидатами, которые у неё уже есть, а затем «капает» дополнительными кандидатами через сигнальный канал по мере их обнаружения. 9 В 2026 году каждое production-развёртывание WebRTC будет использовать Trickle ICE – это сокращает воспринимаемое время установки соединения на 30–70%. Платой за это становится чуть более сложный сигнальный протокол, поскольку канал теперь передаёт множество мелких сообщений вместо двух крупных.
Перезапуск ICE
После установки звонка сеть под ним может измениться: ноутбук, подключённый к домашнему Wi-Fi, выходит за дверь и переключается на сотовую сеть, поезд проезжает между вышками – и IP-адрес меняется. VPN-соединение обрывается. Прежние ICE-кандидаты становятся неактуальными, и передача медиа прекращается. Решение – ICE restart: приложение вызывает pc.restartIce(), браузер генерирует новую пару ICE-логин/пароль, формирует новый список кандидатов, обменивается ими через сигнальный канал и заново выполняет проверки соединения – при этом существующее peer-соединение, ключи шифрования и data channels сохраняются. С точки зрения пользователя звонок «икнул» на долю секунды, но не оборвался. Внедрение этой функции в каждый production-клиент WebRTC – одно из самых эффективных решений для повышения надёжности звонков.
Разбивка 70/30 – почему TURN неизбежен
В production около 60–70% WebRTC-соединений успешно устанавливаются через host- или server-reflexive-кандидатов и вовсе не нуждаются в TURN. Остальные 30–40% – это корпоративные сети со строгими фаерволами, мобильные сети за несколькими уровнями NAT, ограничительные университетские сети, некоторые гостиничные WiFi – требуют TURN, чтобы вообще установить соединение. Эти цифры зависят от аудитории: у потребительских приложений на домашних соединениях больше прямых соединений, у enterprise-приложений – больше трафика через TURN. 10
Это делает TURN-канал самой крупной статьёй операционных расходов WebRTC-продукта. Прямой WebRTC-звонок не использует ваш трафик, тогда как TURN-ретрансляция потребляет каждый байт дважды – сначала внутрь от одного участника, затем наружу к другому. Для однонаодного звонка с суммарным битрейтом 1 Мбит/с TURN-сессия расходует 2 Мбит/с ретрансляционного трафика на протяжении всего разговора. Умножьте это на продолжительность в минутах и количество участников – и счёт быстро становится ощутимым.
Совет, который дают все ветераны WebRTC: всегда запускайте TURN на TCP-порту 443 в дополнение к UDP-порту 3478. Удивительно, сколько корпоративных фаерволов блокируют весь исходящий UDP-трафик, кроме DNS, но не могут блокировать TCP/443 – ведь это сломало бы HTTPS-обзор в браузерах. А TURN-сервер, работающий на TCP/443, в трафике неотличим от обычного веб-сервера. Без этого звонки из корпоративных сетей будут обрываться с раздражающе непредсказуемой частотой.
De facto open-source TURN – это coturn, который работает на небольшом VPS и обеспечивает тысячи одновременных сессий на скромном оборудовании. Облачные альтернативы: Twilio Network Traversal Service, Xirsys, Subspace, Cloudflare Calls (включает STUN/TURN с managed SFU), а также TURN-услуги у всех крупных облачных провайдеров. Выбор между самостоятельной разработкой и покупкой решения обычно сводится к одному вопросу: готовы ли вы сами мониторить TURN-серверы в нескольких регионах? Большинству команд из 20 и менее инженеров стоит выбирать готовое решение.
DTLS, SRTP, RTP – что реально летит по проводам
Как только ICE находит рабочий путь, два узла устанавливают зашифрованный канал и начинают передавать медиа. Шифрование обязательно и не отключается: у WebRTC нет режима «без шифрования». Спецификация W3C и IETF RFC 8827 требуют, чтобы каждый медиа-поток шифровался с помощью DTLS-SRTP – без возможности отказа. Передать незашифрованное аудио или видео невозможно, даже если очень захотеть. 11
Шифрование работает в двух слоях. Первый – DTLS, Datagram Transport Layer Security: это, по сути, TLS (протокол HTTPS), адаптированный под UDP вместо TCP. DTLS выполняет handshake в начале звонка: каждая сторона подтверждает, что владеет сертификатом, чей отпечаток был указан в SDP, и стороны договариваются об общем master secret. Здесь работает SDP-отпечаток: даже если злонамеренный signalling-сервер попытается вмешаться, DTLS-рукопожатие не пройдёт, потому что отпечаток сертификата в канале не совпадёт с отпечатком из SDP легитимного партнёра.
Второй слой – SRTP (Secure Real-time Transport Protocol): лёгкая шифровальная обёртка поверх реальных медиа-пакетов. SRTP использует master secret из DTLS для генерации по-пакетных ключей AES и шифрует, а также аутентифицирует каждый RTP-пакет. Обязательный набор шифров – SRTP_AES128_CM_HMAC_SHA1_80: режим AES-128 с счётчиком и 80-битный аутентификатор HMAC-SHA1. 11
Важны два свойства безопасности. Во-первых, DTLS-ключи по умолчанию генерируются заново для каждого звонка и недоступны JavaScript-слою – они хранятся в защищённом контексте браузера. Даже полностью скомпрометированная веб-страница не может получить доступ к ключам активного звонка. Во-вторых, шифрование осуществляется hop-by-hop, что важно для обсуждения серверной архитектуры ниже: если медиа проходит через SFU, то SFU видит расшифрованные RTP-пакеты при пересылке (иначе он не сможет их форвардить). Для end-to-end шифрования, которое скрывает медиа даже от SFU, требуются Insertable Streams или MLS-based E2EE – обе технологии должны стать зрелыми к 2026 году и уже поддерживаются некоторыми коммерческими платформами (Signal, Zoom для платных клиентов, Google Meet для отдельных enterprise-тарифов), но пока не являются готовыми к использованию «из коробки».
Сами медиа-пакеты – это обычный RTP, Real-time Transport Protocol (RFC 3550), тот же протокол, что с 1990-х используется для передачи VoIP. RTP представляет собой тонкую обёртку вокруг байтов кодека: небольшой заголовок содержит sequence number, timestamp, payload type и 16-битный synchronization source. Парный протокол RTCP передаёт служебную информацию – оценки RTT, отчёты о потерях, sender и receiver reports – примерно каждые пять секунд. WebRTC объединяет аудио, видео и data channels на одном UDP-порту с помощью функции BUNDLE, чтобы потребовалась всего одна ICE-цепочка через firewall, а не по одной на каждый поток.
Серверные архитектуры: mesh, SFU, MCU, гибрид
Пока мы говорили только о двух узлах. Самый важный архитектурный вопрос любого группового продукта – что происходит, когда участников становится больше двух. В 2026 году доминируют три топологии, и выбор между ними определяет, сможет ли ваш продукт масштабироваться до 4 участников или до 4000.
Mesh – каждый с каждым
Самая простая топология – mesh, она же peer-to-peer или full mesh. Каждый участник устанавливает прямое WebRTC-соединение со всеми остальными и передаёт своё аудио и видео по каждому из них. Сервер не участвует в передаче медиа – только в сигнальной обработке и работе с TURN – поэтому операционные расходы практически нулевые.
Mesh звучит элегантно, но на практике жёстко ограничен. Для звонка из N участников каждый должен отправить N–1 копий своего видео вверх и принять N–1 входящих потоков вниз. При 1 Мбит/с на поток 4-участничный mesh-звонок требует от каждого участника 3 Мбит/с на загрузку и 3 Мбит/с на скачивание. При 6 участниках – уже 5 Мбит/с в каждую сторону, что превышает типичный домашний uplink в 10 Мбит/с. При 10 участниках mesh-звонок на потребительских соединениях становится невозможным. Вычислительная нагрузка не лучше: каждый участник кодирует своё видео один раз, декодирует видео всех остальных и прогоняет всё через композитор браузера.
Арифметика беспощадна:
| Участников | Потоков отправляется | Потоков принимается | Upload при 1 Mbps/поток |
|---|---|---|---|
| 2 | 1 | 1 | 1 Mbps |
| 3 | 2 | 2 | 2 Mbps |
| 4 | 3 | 3 | 3 Mbps |
| 6 | 5 | 5 | 5 Mbps |
| 10 | 9 | 9 | 9 Mbps |
Вердикт 2026 года по mesh: использовать только для двух участников. Для трёх и более участников требуется медиа-сервер посередине, и этот сервер почти всегда – SFU.
SFU – Selective Forwarding Unit
SFU – Selective Forwarding Unit – это медиа-сервер, находящийся посередине звонка. Каждый участник отправляет аудио и видео только один раз – в SFU. SFU пересылает каждый входящий поток без изменений каждому другому участнику, на него подписавшемуся. SFU никогда не декодирует и не перекодирует медиа: он лишь анализирует RTP-заголовки, определяет, кому нужен пакет, и пересылает его.
С точки зрения участника это улучшение трафика в 10–50 раз по сравнению с mesh. В 10-участничном SFU-звонке при 1 Мбит/с на поток каждый отправляет 1 Мбит/с вверх (один поток в SFU) и получает 9 Мбит/с вниз (девять потоков от SFU). Трафик на приём всё ещё растёт с увеличением числа участников, но трафик на передачу остаётся фиксированным – 1 Мбит/с, независимо от размера звонка. С simulcast и SVC (об этом ниже) трафик на приём также становится управляемым.
SFU потребляет ресурсы CPU: один SFU-процесс обычно обрабатывает 500–1000 одновременных видеопотоков на современном 16-ядерном сервере (в зависимости от разрешения, кодека и степени использования simulcast). Масштабирование за пределы одного сервера требует построения кластера SFU и умного маршрутизирования участников – что зрелые реализации обеспечивают «из коробки». 12
SFU – это стандарт 2026 года. Все крупные платформы видеоконференций – Google Meet, Microsoft Teams, веб-клиент Zoom, Discord, Slack Huddles – построены на SFU. Большинство open-source-разработок сосредоточено вокруг четырёх ключевых проектов, которые стоит знать:
| SFU | Язык | Лицензия | Для чего | Заметки |
|---|---|---|---|---|
| LiveKit | Go (поверх Pion) | Apache 2.0 | Новые WebRTC-продукты | Современный стек, чистые SDK (Web, iOS, Android, Flutter, RN), first-class ИИ-агенты, managed cloud или self-host. Дефолтный выбор для новых проектов в 2026. |
| mediasoup | C++ ядро, Node.js слой | ISC | Высоконагруженные кастомные продукты | Используется Discord. Низкоуровневый и компонуемый – routing-логику пишете сами. Лучший выбор, когда нужен глубокий контроль. |
| Janus | C, плагинная архитектура | GPLv3 | SIP/PBX-мосты, broadcast | Очень зрелый, очень расширяемый через плагины (streaming, recording, SIP gateway). Лучший выбор для моста с legacy-телефонией. |
| Pion | Go | MIT | Embedded-продукты, хакерские сценарии | Библиотека под капотом LiveKit. Используйте напрямую для Go-нативного WebRTC внутри другого продукта. |
LiveKit, mediasoup и Janus поддерживают simulcast, а большинство из них – SVC с AV1: две технологии, которые значительно снижают down-трафик SFU. Разберём их подробнее ниже.
Simulcast и SVC – как сделать downstream SFU дешёвым
Проблема downstream-трафика SFU: каждый участник получает поток каждого другого участника в оригинальном качестве. На встрече из 25 человек это 24 входящих потока, большинство из которых интерфейс отображает миниатюрами. Отправлять каждую миниатюру в 1080p – расточительство.
Simulcast – ответ: отправитель кодирует одно видео в нескольких качествах – обычно три слоя, например 1080p/2 Mbps, 360p/500 kbps и 180p/150 kbps – и отправляет все три в SFU одновременно. SFU затем пересылает подходящий слой каждому подписчику в зависимости от того, что отображает его интерфейс. Зритель, у которого спикер закреплён на полном экране, получает 1080p; те, у кого спикер отображается в миниатюре, – 180p. Общий объём исходящего трафика снижается на 30–60% в типичных интерфейсах видеоконференций.
SVC – Scalable Video Coding – более изощрённый вариант: вместо трёх отдельных кодировок отправитель кодирует видео один раз, встраивая несколько «слоев» в один битстрим, которые можно постепенно отбрасывать. SFU удаляет верхние слои при пересылке подписчикам с низкой пропускной способностью, не перекодируя видео. SVC значительно эффективнее simulcast, потому что кодер запускается один раз, а не три – но до недавнего времени хорошо работал только с VP9 (проприетарным кодеком Google). Развитие 2026 года – AV1 SVC: сжатие AV1 в сочетании с нативным SVC – быстро становится стандартом по умолчанию в новых SFU-архитектурах. LiveKit внедрил полноценный AV1 SVC в 2024 году; mediasoup и Janus последовали его примеру. 13
Для нетехнического читателя вывод прост: в 2026 году SFU должен как минимум поддерживать simulcast, а в идеале – SVC (желательно AV1 SVC), если вы транслируете контент в современные браузеры. Разница в расходе полосы пропускания между 30-участной встречей при использовании simulcast/SVC и наивной пересылкой составляет примерно в 2 раза; за год эксплуатации это окупает все инженерные вложения.
MCU – Multipoint Control Unit
MCU – Multipoint Control Unit – более старая, сложная и значительно более дорогая альтернатива SFU. Как и SFU, он находится в центре звонка, но в отличие от SFU декодирует каждый входящий поток, компонует их в один видео-кадр (сетку участников), перекодирует результат и отправляет один исходящий поток каждому зрителю. Каждый участник отправляет один поток, получает один поток и видит готовую картинку без клиентской компоновки.
Привлекательность MCU – в простоте работы на стороне клиента: устройство декодирует всего один поток, и всё. Это было важно, когда у телефонов был слабый GPU, и любое декодирование требовало значительных ресурсов. Эта особенность остаётся актуальной в трёх случаях: когда вызов нужно передать в legacy-систему, ожидающую единственный поток (архив записи, симулкаст-трансляция, SIP-эндпоинт, аппаратный видеотерминал); когда участники используют устройства с крайне ограниченными возможностями, не способные обрабатывать более одного HD-потока; и когда вызов должен быть транслирован большой пассивной аудитории (например, вебинар с пятью спикерами и десятью тысячами зрителей, подключённых только для прослушивания).
Проклятие MCU – compute-стоимость. Декодирование и перекодирование N потоков в реальном времени требует в 4–10 раз больше CPU, чем у SFU, просто пересылающего N потоков. Один MCU-сервер, обслуживающий 30 участников, нуждается в большем железе, чем SFU на 300. Математика не на стороне MCU с тех пор, как смартфоны получили аппаратные видеодекодеры – это структурная причина, по которой SFU победили в 2010-х и продолжают доминировать в 2026 году. MCU выживают лишь в трёх нишах – broadcast-ингест, recording/transcoding pipeline и SIP-gateway, – но больше не являются архитектурой по умолчанию для новых продуктов.
Гибрид – SFU и MCU для тех, кому действительно нужно
Прагматичная архитектура 2026 для масштабных продуктов – гибрид: SFU для большинства участников и MCU поверх – для тех немногих use-case, которым действительно нужен скомпонованный поток. Классический пример – вебинар: 5 спикеров подключены к SFU и видят друг друга интерактивно; их потоки поступают в MCU, который объединяет их в единый broadcast-стрим и раздаёт 10 000 зрителям, подключённым только на прослушивание, через HLS или LL-HLS. Дорогая операция транскодирования оплачивается один раз на панель, а не на каждого зрителя. Большинство коммерческих WebRTC-платформ (LiveKit Cloud, Daily, Vonage, Twilio Video, Dolby.io) предлагают гибридную модель как функцию под названиями «broadcast mode», «egress» или «recording» – технология под капотом у всех одна.
Полный звонок от начала до конца
Когда детали разложены, давайте разберём, что на самом деле происходит, когда Алиса со своего ноутбука звонит Бобу на телефон. Это канонический handshake – так работает любой WebRTC-звонок в 2026 году.
Секунда 0. Алиса открывает конференц-приложение в браузере. Страница устанавливает соединение WebSocket с сервером сигнализации и регистрирует её. Боб делает то же самое со своего телефона. Оба устройства имеют доступ к микрофону и камере (пользователь ранее дал на это разрешение).
Секунда 0,5. Alice нажимает «позвонить Bob'у». Страница создаёт новый RTCPeerConnection, добавляет локальные аудио- и видеотреки и вызывает createOffer(). Браузер возвращает SDP-офер со всеми кодеками, которые устройство Alice может кодировать (Opus для аудио, H.264, VP8, AV1, возможно H.265 – для видео), а также отпечаток только что сгенерированного сертификата. Страница запускает сбор ICE-кандидатов: почти мгновенно определяется локальный IP-адрес (host), отправляется STUN-запрос на публичный сервер Google, и через несколько миллисекунд приходит публичный IP-адрес (server-reflexive), а на корпоративном TURN-сервере резервируется слот для ретрансляции (relay-кандидат).
Секунда 0,8. Страница отправляет SDP-офер через WebSocket-сервер сигнализации, который пересылает его на телефон Боба. Телефон Боба получает офер, создаёт свой RTCPeerConnection, вызывает setRemoteDescription(offer), а затем createAnswer(). Браузер генерирует SDP-ансер с одним аудиокодеком (Opus) и одним видеокодеком (AV1), своим отпечатком и ICE-учётными данными. Параллельно телефон Боба собирает свои ICE-кандидаты.
Секунда 1,0. Телефон Боба отправляет SDP-ответ на сигнальный сервер, тот пересылает его Алисе. Браузер Алисы вызывает setRemoteDescription(answer). Теперь обе стороны знают, что собирается передавать другая.
Секунды 1,0–1,5. Trickle ICE в разгаре. По мере появления кандидатов на каждой стороне они передаются другой стороне через сигнальный канал. Каждая сторона запускает проверки связности: небольшие STUN-запросы между каждой парой кандидатов. Побеждает первая пара, в которой оба запроса проходят успешно. В типичных 70% случаев это пара host–host или server-reflexive–server-reflexive, и TURN не используется. В оставшихся 30% единственная рабочая пара – через TURN.
Секунды 1,5–1,8. Как только определена рабочая пара, на этом пути запускается DTLS-рукопожатие. Обе стороны сверяют отпечаток сертификата с указанным в SDP. Если он совпадает – генерируются SRTP-мастер-ключи, и медиа-поток становится активным.
Секунда 1,8. Первые RTP-пакеты начали передаваться. Аудио с микрофона Алисы доходит до Боба, видео с камеры Боба – до Алисы. Общее время установления соединения – менее двух секунд.
На протяжении звонка. RTCP-отчёты отправляются в обе стороны каждые несколько секунд: информация о потерях пакетов, оценки RTT, обратная связь по пропускной способности. Контроллеры перегрузки на каждой стороне подстраивают исходящий битрейт под доступную пропускную способность. Если соединение прерывается, приложение может вызвать restartIce(), чтобы пересобрать кандидатов и выбрать новый путь – без обрыва звонка.
Для видеоконференции с тремя и более участниками замените «телефон Bob'а» на «SFU» и пусть каждый участник выполнит тот же handshake с SFU. SFU – это специальный WebRTC-эндпоинт, который одновременно взаимодействует со всеми участниками и пересылает пакеты между ними.
Числовой пример: реальная стоимость продукта с высоким энергопотреблением
Представьте виджет поддержки, работающий в корпоративных сценариях help-desk: 60% звонков поступают из enterprise-сетей, использующих TURN, средняя продолжительность звонка – 8 минут, общий двусторонний трафик – 800 кбит/с (500 кбит/с видео + 300 кбит/с аудио + control). Ожидаемая нагрузка – 50 000 звонков в месяц.
TURN-трафик на один звонок: 800 кбит/с × 60 секунд × 8 минут = 24 МБ входящих + 24 МБ исходящих = 48 МБ всего, если соединение проходит через TURN. По всем 50 000 звонкам × 60% через TURN × 48 МБ = 1,44 ТБ TURN-трафика в месяц.
При типичной облачной цене на TURN-egress 0,05 $/ГБ в 2026 году стоимость трафика составит 72 $/мес. Если дополнительно платить за вычислительные ресурсы через управляемый сервис, например Twilio (по минутам, около 0,0006 $/мин), то расходы составят: 50 000 × 8 × 0,6 × 0,0006 = 144 $/мес – это ещё сверху.
Теперь масштабируем до миллиона звонков в месяц с теми же параметрами: 1440 $ за raw bandwidth и 2880 $ за managed TURN-минуты – примерно 4300 $/мес только за TURN. Это всё ещё мало по сравнению с инженерной стоимостью самостоятельного хостинга coturn в трёх регионах с мониторингом, но уже не выглядит тривиальным в диапазоне миллионов звонков.
Ошибка, которой стоит избегать: оптимистично закладывать в бюджет TURN 10% звонков, потому что так говорят маркетинговые материалы. В enterprise-продуктах с высокой нагрузкой реальное значение ближе к 60%, и итоговая стоимость оказывается в шесть раз выше, чем в «салфеточном» расчёте.
Частые ошибки и подводные камни
Экономьте на TURN. Половина проблем с надёжностью WebRTC – это проблемы с TURN: либо сервер вообще отсутствует, либо работает только по UDP без поддержки TCP/443-резервирования. Всегда запускайте TURN, всегда включайте TCP/443-резервирование, всегда предоставляйте TURN-серверы минимум из двух регионов, если пользователи находятся на разных континентах.
Используйте mesh только для «маленьких» звонков с участием двух и более человек. Mesh математически эффективен при 3–4 участниках в идеальных сетевых условиях, но перестаёт работать на реальных потребительских соединениях уже при 4–5 пользователях. К 6 участникам объём исходящего трафика превысит возможности кабельного интернета. Строить SFU с самого начала – даже если на старте вы реализуете только двусторонние звонки – проще, чем дорабатывать архитектуру позже.
Делать signalling-сервер для галочки. Большинство жалоб на «ненадёжность WebRTC» – на самом деле жалобы на слабый signalling-сервер, а не на медиапуть. Используйте проверенный real-time backend (Firebase, Ably, Pusher, Supabase Realtime, Cloudflare Durable Objects) или стройте signalling поверх надёжной message bus, прежде чем настраивать хоть один SDP-атрибут.
Игнорировать Trickle ICE. Без Trickle установка соединения ждёт самую медленную TURN-аллокацию. С Trickle время установки сокращается на 30–70%. Все современные SDK его поддерживают – включайте.
Пропускать ICE restart. Мобильные пользователи весь день переходят между WiFi и сотовой сетью. Без ICE restart каждый handover – это обрыв звонка. Реализация – одна строка JavaScript, а пользовательский опыт улучшается огромно.
Не позволяйте SDP убедить вас, что вы понимаете WebRTC. SDP громоздкий, неудобочитаемый и в основном не имеет отношения к проектированию вашего продукта. Тратьте время на надёжность сигнализации, расчёт бюджета на TURN, выбор SFU и мониторинг. Изучайте SDP только при отладке конкретных проблем.
Где находится Фора Софт
Мы разрабатываем WebRTC-решения для видеостриминга, видеоконференций, e-learning, телемедицины, видеонаблюдения, OTT и AR/VR-устройств с 2005 года – реализовали более 250 проектов в этих направлениях. Большая часть нашей работы с WebRTC в 2026 году строится вокруг одного из трёх подходов: кастомный SFU-стек на базе LiveKit или mediasoup – для продуктов, где требуется полный контроль над call-слоем; интеграция managed-решений (LiveKit Cloud, Daily, Vonage, Twilio, Agora) – для команд, которым важно быстро выйти на рынок без необходимости управлять серверами; и гибридная модель с managed TURN и self-hosted SFU – для оптимизации затрат при масштабировании. Мы помогаем продуктовым командам выбрать подходящий паттерн, спроектировать протокол сигнализации, рассчитать ёмкость TURN-серверов с учётом географии пользователей и внедрить инструменты мониторинга качества вызовов, чтобы команда продукта получала обратную связь раньше, чем это делают специалисты по работе с клиентами. Если вы разрабатываете WebRTC-продукт, выбор между этими тремя моделями – одно из самых важных решений в первый месяц. И мы рады быть вашим вторым мнением.
Дерево решений – топология за пять вопросов
Используйте приведённое ниже дерево решений как отправную точку. Пять вопросов помогут сузить выбор до одного из четырёх вариантов (mesh, SFU, MCU, гибрид), что охватывает 95% реальных продуктов.
- Сколько участников может быть в одном звонке?
2 → достаточно mesh. 3 – ~500 → SFU. 500+ → SFU с broadcast-доставкой (гибридная архитектура).
- Требуется ли для кого-то из участников объединённый поток (single-stream output)?
Да (например, для записи, SIP-шлюза или трансляции пассивной аудитории) → добавить MCU-стадию (гибридная архитектура). Нет → использовать чистый SFU.
- Большинство пользователей подключаются из домашних или мобильных сетей (consumer) или из корпоративных/ограниченных сетей (enterprise)?
Consumer → выделите 30% бюджета на TURN. Enterprise → потребуется 60–80% бюджета на TURN. Планируйте трафик с учётом этого.
- Нужно ли end-to-end шифрование, при котором медиа остаются недоступны даже для вашего SFU?
Да → используйте Insertable Streams или MLS E2EE (в стиле Signal); выбирайте SFU с поддержкой (LiveKit Cloud, Daily для enterprise, Zoom для платных тарифов). Нет → применяйте стандартный SRTP через SFU – это значение по умолчанию.
- Сколько инженерных ресурсов можно выделить на инфраструктуру звонков?
Много → разверните собственный SFU (LiveKit, mediasoup, Janus, Pion). Мало → используйте управляемый бэкенд (LiveKit Cloud, Daily, Vonage, Twilio, Agora, Dolby.io).
Ключевые выводы
- WebRTC – это одновременно API браузера, стек протоколов IETF и медиапайплайн.
- Signalling-канал вы реализуете самостоятельно; спецификация WebRTC на этом заканчивается.
- SDP – неудобный, но необходимый язык для согласования кодеков, ключей и параметров.
- ICE находит рабочий путь; STUN определяет публичные адреса, а TURN обеспечивает ретрансляцию, когда другие варианты не работают.
- TURN обслуживает 30–70% реальных звонков и является крупнейшей операционной статьёй расходов.
- SFU – топология по умолчанию в 2026 году; mesh – для парных соединений, MCU – для трансляций и записи.
- AV1 SVC, сквозное шифрование и ИИ-агенты – три актуальные области развития в WebRTC NV.
Что читать дальше
- Стриминг-протоколы: 8 главных в 2026 – где WebRTC встраивается между HLS, DASH, LL-HLS, SRT, RTMP.
- LL-HLS vs WebRTC vs CMAF: low-latency – лоб в лоб для продуктов с потребностью в видео меньше 3 секунд задержки.
- AV1: новый стандарт интернета в 2026 – почему AV1 SVC важен для downstream SFU.
Источники
- W3C. WebRTC: Real-Time Communication in Browsers. W3C Recommendation, 26 января 2021. https://www.w3.org/TR/webrtc/
- webrtcHacks. WebRTC Today & Tomorrow: Interview with W3C WebRTC Chair Bernard Aboba. https://webrtchacks.com/webrtc-today-tomorrow-bernard-aboba-qa/
- IETF. RFC 8825: Overview: Real-Time Protocols for Browser-Based Applications. Январь 2021. https://datatracker.ietf.org/doc/html/rfc8825
- IETF. RFC 8866: SDP – Session Description Protocol. Январь 2021. https://datatracker.ietf.org/doc/html/rfc8866
- ORTC Community Group. Object RTC (ORTC) API for WebRTC. https://draft.ortc.org/
- IETF. RFC 8445: Interactive Connectivity Establishment (ICE). Июль 2018. https://datatracker.ietf.org/doc/html/rfc8445
- IETF. RFC 8489: Session Traversal Utilities for NAT (STUN). Февраль 2020. https://datatracker.ietf.org/doc/html/rfc8489
- IETF. RFC 8656: Traversal Using Relays around NAT (TURN). Февраль 2020. https://datatracker.ietf.org/doc/html/rfc8656
- IETF. RFC 8838: Trickle ICE – Incremental Provisioning of Candidates. Январь 2021. https://datatracker.ietf.org/doc/html/rfc8838
- GetStream. WebRTC STUN vs TURN Servers. https://getstream.io/resources/projects/webrtc/advanced/stun-turn/
- IETF. RFC 8827: WebRTC Security Architecture. Январь 2021. https://datatracker.ietf.org/doc/html/rfc8827
- RTC League. WebRTC Infrastructure Guide 2026: Signalling, SFU & Scaling at Enterprise Load. https://rtcleague.com/blogs/webrtc-infrastructure
- LiveKit. Codecs and More – AV1 SVC, Simulcast, and Forward Error Correction. https://docs.livekit.io/transport/media/advanced/