Содержание статьи +
- TL;DR
- Почему это важно
- Что такое WebRTC на самом деле
- Пробел в сигнализации
- SDP – как два узла описывают, что они будут передавать
- ICE, STUN, TURN – как узлы находят рабочий путь
- DTLS, SRTP, RTP – что реально летит по проводам
- Серверные архитектуры: mesh, SFU, MCU, гибрид
- Полный звонок от начала до конца
- Числовой пример: реальная стоимость TURN-тяжёлого продукта
- Частые ошибки и подводные камни
- Где Фора Софт
- Дерево решений – топология за пять вопросов
- Ключевые выводы
- Что читать дальше
- Источники
TL;DR
WebRTC – Web Real-Time Communication – это открытый стандарт, который позволяет браузеру, телефону, серверу или встроенной камере отправлять аудио, видео и данные другому браузеру, телефону, серверу или камере примерно за полсекунды, без плагина и без кастомного клиента. На этом стандарте построены Google Meet, голосовые каналы Discord, Microsoft Teams, web-клиент Zoom, телемедицинские порталы, онлайн-классы, дашборды видеонаблюдения, аукционы в реальном времени и почти все современные виджеты поддержки. В 2026 году WebRTC переносит подавляющую часть низколатентного интерактивного видео в интернете. Чтобы правильно его использовать, нужно понимать четыре вещи, которые новички постоянно путают: SDP – язык, на котором два узла договариваются о том, что они будут передавать; ICE, STUN и TURN – то, как они находят рабочий сетевой путь через firewalls и NAT; и выбор между архитектурами SFU и MCU, который определяет, масштабируется ли ваш продукт на десять человек или на десять тысяч. Эта статья разбирает каждый элемент простым языком и заканчивается решающим деревом, которое можно применить к реальному продукту без участия инженера.
Почему это важно
Если вы делаете что угодно, где двум или более людям нужно видеть и слышать друг друга в реальном времени – конференц-инструмент, виртуальный класс, консультацию врача, sales-демо, видеочат поддержки, live-шопинг с интерактивными гостями, мультиплеер с голосом, систему видеонаблюдения с динамиком, умный дверной звонок, – WebRTC в 2026 году стоит «по умолчанию» для транспортного слоя аудио и видео. Выбрать его легко; гораздо сложнее – четыре решения, которые технология заставляет принять до того, как вы напишете первую строку кода. Где будет жить ваш signalling-сервер? Как пробивать корпоративные firewalls? Сколько TURN-трафика вы готовы оплачивать? И какую серверную архитектуру поставить между участниками, когда их станет больше трёх? Сделав эти четыре решения правильно, команда из пяти инженеров может выпустить продукт, конкурирующий с Zoom по качеству и стоимости. Сделав их неправильно – потратите полгода на борьбу с собственной инфраструктурой и ещё полгода на объяснения корпоративным клиентам, почему звонки рвутся.
Эта статья даёт ментальную модель, чтобы принять все четыре решения правильно с первого раза. Мы начнём с того, что WebRTC реально делает внутри браузера, разберём handshake переговоров (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-media и интеграцию с 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-буфер, маскировка потерянных пакетов, congestion control. С этим работает media-инженер. Большая часть pipeline скрыта от разработчика, и вы замечаете её только когда что-то ломается.
Когда в этой статье мы говорим «WebRTC», мы имеем в виду все три значения сразу: API, который вызывает страница, протоколы, которым следуют байты, и media pipeline, который скрывает сложность посередине.
Чем WebRTC не является – это протоколом сигнализации. WebRTC объясняет двум узлам, как им посылать аудио, видео и данные, после того как они договорились о параметрах, но сам шаг договорённости – как именно они обменяются параметрами – намеренно оставляет разработчику приложения. Этот пробел – самое неожиданное, что есть в WebRTC, и мост, который нужно построить, прежде чем всё остальное обретёт смысл.
Пробел в сигнализации
Представьте двух людей в разных комнатах, которые хотят начать телефонный разговор. Прежде чем заговорить, им нужен кто-то – секретарь, телефонный номер, обмен письмами – чтобы их познакомить, сообщить каждому, где другой, и помочь договориться о языке. Только после этого они кладут трубку с секретарём и говорят напрямую.
WebRTC устроен так же. Два браузера не могут найти друг друга в публичном интернете сами. Кто-то снаружи WebRTC должен их представить. Этот «кто-то» называется signalling-каналом, и вы строите его сами.
Построить signalling-канал несложно. В 2026 году почти каждый WebRTC-продукт использует один из трёх подходов: WebSocket-соединение с небольшим сервером, который разработчик пишет сам; server-sent events для одностороннего сигналинга; или сторонний real-time backend вроде Firebase, Ably, Pusher или Supabase Realtime. Единственная задача signalling-сервера – пересылать несколько небольших текстовых сообщений (SDP offer, SDP answer и поток ICE-кандидатов) от одного участника к другому, пока звонок устанавливается. Когда соединение установлено, signalling-сервер уходит со сцены; аудио и видео идут напрямую между участниками.
Выбор signalling-протокола за вами. Можно сделать кастомный WebSocket-протокол, использовать SIP, использовать XMPP, написать REST API. Спецификации WebRTC всё равно – это и свобода (вы берёте, что подходит вашему стеку), и налог (каждый WebRTC-проект заново пишет один и тот же скучный signalling-код). Практические ограничения два: канал должен быть надёжным (сообщения не должны теряться) и двусторонним (оба участника должны иметь возможность пушить сообщения друг другу в реальном времени).
Мы подчёркиваем эту мысль потому, что именно на signalling-сервере падают большинство ранних WebRTC-продуктов. Слабый сигналинг – нестабильные переподключения WebSocket, потерянные сообщения, медленные round-trip-задержки между регионами – порождает звонки, которые выглядят так, будто рвутся случайно, хотя аудио и видео в порядке, а сообщения теряет только установочный handshake. Сначала наладьте signalling-сервер, потом обвиняйте WebRTC.
С этим разобрались – теперь посмотрим, что именно signalling-канал переносит. Два сообщения делают почти всю работу, и оба написаны на языке под названием SDP.
SDP – как два узла описывают, что они будут передавать
SDP – Session Description Protocol – это текстовый формат, которым два WebRTC-узла рассказывают друг другу, что они будут отправлять и как. Изначально его придумали для SIP-телефонии в конце 1990-х, формализовали как RFC 8866 в 2021 году и натянули на WebRTC, потому что ничего лучше не существовало. 4 В 2026 году каждый WebRTC-handshake по-прежнему проходит через SDP offer и SDP answer, и обойти это нельзя.
Структура простая в принципе. Узел A – offerer – формирует SDP-блок, в котором по порядку: session-level заголовок с timing и connection-информацией, затем одна или несколько media-секций, каждая описывающая один поток аудио, видео или данных. Каждая media-секция перечисляет кодеки, которые offerer умеет кодировать и декодировать, криптографические ключи, сетевые параметры и длинный список feature-флагов. Offer летит через signalling-канал к узлу 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-credentials: короткий username и пароль, которые стороны используют во время поиска пути, чтобы доказать, что пакеты в сети действительно от ожидаемого партнёра, а не от атакующего, заваливающего тот же порт случайными пакетами.
Получатель сравнивает offer со своими возможностями и формирует answer. Answer имеет ту же форму, но содержит только те кодеки и параметры, на которые answerer соглашается:
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(), а ваша задача – переправить строки туда-обратно через свой signalling-канал.
ICE, STUN, TURN – как узлы находят рабочий путь
Когда стороны знают что они будут отправлять, им нужно понять куда. Звучит банально – казалось бы, каждая сторона просто передаёт другой свой IP – но публичный интернет 2026 года построен поверх полосы препятствий из NAT, firewalls, корпоративных прокси, мобильных операторов и домашних роутеров, которые все вместе мешают двум произвольным машинам говорить напрямую. Фреймворк, который решает эту задачу, называется ICE и опирается на два вспомогательных протокола – STUN и TURN – которые являются рабочими лошадками любого WebRTC-развёртывания.
Проблема в том, что почти ни у одного консьюмерского устройства в современном интернете нет публичного IP-адреса. Ноутбук на домашнем WiFi сидит за роутером, у которого один публичный IP; роутер прячет каждое устройство в доме за этим IP с помощью Network Address Translation, или NAT. Телефон в сотовой сети сидит за двумя-тремя слоями carrier-grade NAT и может получать новый внешний IP каждые несколько минут. Ноутбук в офисе сидит за firewall, блокирующим всё, кроме разрешённых портов. Когда узел 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-адреса на сетевых интерфейсах устройства: адрес домашнего WiFi 192.168.x.x, Ethernet, VPN. Host-кандидаты работают, если оба узла оказались в одной сети (один офис, один домашний WiFi). Они почти никогда не работают между двумя случайными устройствами в интернете.
Server-reflexive-кандидаты – это публичный адрес, который NAT устройства показывает миру, как его видит публичная точка наблюдения. Чтобы узнать этот адрес, узел отправляет небольшой запрос STUN-серверу – Session Traversal Utilities for NAT, RFC 8489 – и STUN-сервер отвечает: «публичный 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 – которые узел зарезервировал как fallback. 8 Когда два узла не могут достичь друг друга напрямую никакой комбинацией host- или server-reflexive-адресов (обычно потому что хотя бы один из них за symmetric NAT или строгим корпоративным firewall), они оба отправляют медиа TURN-серверу, и тот ретранслирует её другой стороне. TURN-сервер видит и пересылает каждый байт звонка – а значит, оплачивает каждый байт трафика и добавляет 5–50 мс задержки в зависимости от своего расположения.
Каждый узел собирает 2–10 кандидатов, обменивается ими с другой стороной через signalling-канал и пробует каждую пару в порядке приоритета: сначала host-host, затем host-server-reflexive, затем server-reflexive-server-reflexive, затем что угодно через relay. Каждую пару проверяют небольшим STUN-probe в обоих направлениях; первая пара, где оба пробинга проходят, побеждает, и медиа течёт по этому пути.
Trickle ICE
Наивная версия ICE заставляет звонок ждать, пока обе стороны соберут всех кандидатов, прежде чем отправить offer. На медленной сети или с нагруженным TURN-сервером сбор может занять несколько секунд – и эти секунды пользователь смотрит на «connecting…». Решение – Trickle ICE, RFC 8838: каждая сторона отправляет SDP-offer сразу с теми кандидатами, что у неё уже есть, а потом «капает» дополнительными кандидатами через signalling-канал по мере их обнаружения. 9 В 2026 году каждое production WebRTC-развёртывание использует Trickle ICE – это сокращает воспринимаемое время установки звонка на 30–70%. Цена – чуть более сложный signalling-протокол, потому что канал теперь несёт много мелких сообщений вместо двух больших.
ICE restart
После установки звонка сеть под ним может измениться. Ноутбук на домашнем WiFi выходит за дверь и переключается на сотовую сеть. Поезд проезжает между вышками – и IP меняется. VPN-соединение рвётся. Прежние ICE-кандидаты теперь неактуальны, и медиа перестанет течь. Решение – ICE restart: приложение вызывает pc.restartIce(), браузер генерирует новую пару ICE-username/password, собирает новый список кандидатов, обменивается ими через signalling-канал и заново прогоняет connectivity checks – всё это, сохраняя существующее peer-соединение, ключи шифрования и data channels. С точки зрения пользователя звонок икнул на долю секунды, а не умер. Встроить это в каждый production WebRTC-клиент – одно из самых высокорентабельных действий для надёжности звонков.
Разбивка 70/30 – почему TURN неизбежен
В production около 60–70% WebRTC-соединений успешно устанавливаются через host- или server-reflexive-кандидатов и никогда не нуждаются в TURN. Остальные 30–40% – корпоративные сети со строгими firewall, мобильные сети за несколькими слоями NAT, ограничительные университетские сети, некоторые гостиничные WiFi – требуют TURN, чтобы соединиться вообще. Числа зависят от аудитории: у консьюмерского приложения на домашних соединениях прямых connection больше, у enterprise – TURN-трафика. 10
Это делает TURN-bandwidth самой большой операционной статьёй WebRTC-продукта. Прямой WebRTC-звонок не использует ваш трафик; TURN-relay-звонок использует каждый байт дважды (внутрь от одной стороны, наружу к другой). Для звонка один-на-один с общим bitrate 1 Mbps TURN-сессия сжигает 2 Mbps relay-трафика на всё время звонка. Перемножьте на минуты и количество участников – счёт быстро становится серьёзным.
Совет, который даёт каждый WebRTC-ветеран: всегда запускайте TURN на TCP-порту 443 в дополнение к UDP-порту 3478. Удивительное число корпоративных firewalls блокирует весь исходящий 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-тиры у всех больших облаков. Решение build-vs-buy обычно сводится к тому, готовы ли вы мониторить TURN-серверы в нескольких регионах сами – большинству команд до 20 инженеров стоит покупать.
DTLS, SRTP, RTP – что реально летит по проводам
Как только ICE находит рабочий путь, два узла устанавливают зашифрованный канал и начинают передавать медиа. Шифрование обязательно и не выключается: у WebRTC нет режима «без шифрования». Спецификация W3C и IETF RFC 8827 требуют, чтобы каждый медиа-поток был зашифрован DTLS-SRTP, без opt-out. Передать незашифрованное аудио или видео нельзя, даже если очень захотеть. 11
Шифрование работает в двух слоях. Первый – DTLS, Datagram Transport Layer Security: это по сути TLS (протокол HTTPS), адаптированный под UDP вместо TCP. DTLS делает handshake в начале звонка: каждая сторона доказывает, что владеет сертификатом, чей отпечаток был объявлен в SDP, и стороны договариваются об общем master secret. Здесь работает SDP-отпечаток: даже если злонамеренный signalling-сервер попытается вклиниться, DTLS-handshake не удастся, потому что отпечаток сертификата в проводе не совпадёт с отпечатком в SDP от легитимного партнёра.
Второй слой – SRTP, Secure Real-time Transport Protocol: лёгкая шифровальная обёртка над реальными медиа-пакетами. SRTP использует master secret из DTLS, чтобы вывести по-пакетные AES-ключи, и шифрует и аутентифицирует каждый RTP-пакет. Обязательный cipher suite – SRTP_AES128_CM_HMAC_SHA1_80: AES-128 counter mode и 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-тарифов), но ещё не являются turn-key-фичей.
Сами медиа-пакеты – это обычный RTP, Real-time Transport Protocol, RFC 3550, тот же, что переносит VoIP с 1990-х. 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-соединение со всеми остальными и шлёт своё аудио и видео по каждому соединению. Сервер в media-пути не участвует – только signalling и TURN – поэтому ваша операционная стоимость почти нулевая.
Mesh звучит элегантно и жестоко ограничен на практике. Для звонка из N участников каждый должен отправить N–1 копий своего видео вверх и принять N–1 входящих потоков вниз. При 1 Mbps на поток 4-участничный mesh-звонок стоит каждому участнику 3 Mbps вверх и 3 Mbps вниз. При 6 – уже 5 Mbps в каждую сторону, что превышает типичный домашний uplink в 10 Mbps. При 10 участниках mesh на консьюмерских соединениях невозможен. Compute-стоимость не лучше: каждый участник кодирует своё видео один раз, декодирует видео каждого другого участника и прогоняет всё через композитор браузера.
Арифметика беспощадна:
| Участников | Потоков отправляется | Потоков принимается | 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 Mbps на поток каждый шлёт 1 Mbps вверх (один поток в SFU) и принимает 9 Mbps вниз (девять потоков из SFU). Down-трафик всё ещё растёт с N, но up-трафик зафиксирован на 1 Mbps независимо от размера звонка. С simulcast и SVC (об этом ниже) down-трафик тоже становится управляемым.
SFU платит CPU: один SFU-процесс обычно держит 500–1000 одновременных видеопотоков на современном 16-ядерном сервере (зависит от разрешения, кодека и того, насколько агрессивно используется simulcast). Масштабирование за один сервер означает кластер SFU и умный routing участников, что зрелые реализации делают «из коробки». 12
SFU – это дефолт 2026 года. Все крупные продукты видеоконференций – Google Meet, Microsoft Teams, web-клиент Zoom, Discord, Slack Huddles – построены на SFU. Большую часть open-source-работы делают четыре проекта, которые стоит знать по имени:
| SFU | Язык | Лицензия | Для чего | Заметки |
|---|---|---|---|---|
| LiveKit | Go (поверх Pion) | Apache 2.0 | Новые WebRTC-продукты | Современный стек, чистые SDK (Web, iOS, Android, Flutter, RN), first-class AI-агенты, 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 входящих потока, большинство из которых UI показывает миниатюрами. Слать каждую миниатюру в 1080p – расточительство.
Simulcast – ответ: отправитель кодирует одно видео в нескольких качествах – обычно три слоя, скажем 1080p/2 Mbps, 360p/500 kbps и 180p/150 kbps – и шлёт все три SFU одновременно. SFU потом форвардит подходящий слой каждому подписчику в зависимости от того, что показывает его UI. Зритель, у которого спикер закреплён на полный экран, получает 1080p; те, у кого спикер – миниатюра, получают 180p. Общий downstream-трафик падает на 30–60% в типичных UI конференций.
SVC – Scalable Video Coding – более изощрённый кузен: вместо тройного кодирования отправитель кодирует видео один раз с несколькими «слоями», встроенными в один битстрим, которые можно прогрессивно отбрасывать. SFU отсекает высокие слои при пересылке подписчикам с низким качеством без перекодирования. SVC значительно эффективнее simulcast, потому что кодер работает один раз, а не три – но до недавнего времени хорошо работал только с VP9 (проприетарным кодеком Google). Развитие 2026 года – AV1 SVC: компрессия AV1 плюс нативный SVC – быстро становится дефолтом в новых SFU-развёртываниях. LiveKit добавил first-class AV1 SVC в 2024 году; mediasoup и Janus подтянулись. 13
Для нетехнического читателя вывод прост: в 2026 году SFU должен как минимум поддерживать simulcast, а в идеале – SVC (желательно AV1 SVC), если вы доставляете в современные браузеры. Разница в bandwidth-стоимости 30-участничной встречи на simulcast/SVC и наивной пересылке – примерно 2x; за год эксплуатации это окупает все инженерные вложения.
MCU – Multipoint Control Unit
MCU – Multipoint Control Unit – более старая, более сложная и значительно более дорогая альтернатива SFU. Как и SFU, он сидит посередине звонка, но в отличие от SFU декодирует каждый входящий поток, компонует их в один видео-кадр (сетку участников), перекодирует результат и отправляет один исходящий поток каждому зрителю. Каждый участник заливает один поток, скачивает один поток и видит готовую картинку без client-side композитинга.
Привлекательность MCU – операционная простота на клиенте: устройство декодирует один поток, точка. Это было важно, когда у телефонов был слабый GPU и любое декодирование было дорогим. Это всё ещё важно в трёх ситуациях: когда звонок надо подать в legacy-систему, ожидающую один поток (архив записи, broadcast-симулкаст, SIP-эндпоинт, аппаратный видеотерминал); когда участники на сверхслабых устройствах, не способных декодировать больше одного HD-потока; и когда звонок должен быть переретранслирован пассивной аудитории (вебинар с 5 спикерами и 10 000 listen-only-зрителей).
Проклятие 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-stream и веером раздаёт через HLS или LL-HLS 10 000 listen-only-зрителям. Дорогая работа transcoding оплачивается один раз на панель, а не на зрителя. Большинство коммерческих WebRTC-платформ (LiveKit Cloud, Daily, Vonage, Twilio Video, Dolby.io) упаковывают гибрид как фичу под названием «broadcast mode», «egress» или «recording» – технология под капотом одна.
Полный звонок от начала до конца
Когда детали разложены, пройдёмся по тому, что реально происходит, когда Alice со своего ноутбука звонит Bob'у на телефон. Это канонический handshake – так работает любой WebRTC-звонок в 2026 году.
Секунда 0. Alice открывает конференц-приложение в браузере. Страница открывает WebSocket к signalling-серверу и регистрирует её. Bob делает то же со своего телефона. Оба устройства имеют доступ к микрофону и камере (пользователь дал разрешение раньше).
Секунда 0,5. Alice нажимает «позвонить Bob'у». Страница создаёт новый RTCPeerConnection, добавляет её локальные аудио- и видео-треки и вызывает createOffer(). Браузер возвращает SDP-offer со всеми кодеками, которые устройство Alice умеет кодировать (Opus для аудио; H.264, VP8, AV1, возможно H.265 для видео), плюс отпечаток свежесгенерированного сертификата. Страница запускает сбор ICE-кандидатов: почти мгновенно находит локальный IP (host), отправляет STUN-запрос публичному серверу Google и через несколько миллисекунд получает свой публичный IP (server-reflexive), резервирует relay-слот на корпоративном TURN-сервере (relay-кандидат).
Секунда 0,8. Страница отправляет SDP-offer через WebSocket signalling-серверу, который пересылает его на телефон Bob'а. Телефон Bob'а получает offer, создаёт свой RTCPeerConnection, вызывает setRemoteDescription(offer), затем createAnswer(). Браузер генерирует SDP-answer с одним кодеком на аудио (Opus) и одним на видео (AV1), своим отпечатком и ICE-credentials. Телефон Bob'а параллельно собирает свои ICE-кандидаты.
Секунда 1,0. Телефон Bob'а отправляет SDP-answer signalling-серверу, тот пересылает Alice. Браузер Alice вызывает setRemoteDescription(answer). Обе стороны теперь знают, что собирается слать другая.
Секунды 1,0–1,5. Trickle ICE в разгаре. По мере появления кандидатов на каждой стороне их отправляют через signalling другой стороне. Каждая сторона запускает connectivity checks: маленькие STUN-probes между каждой парой кандидатов. Первая пара, где оба пробинга проходят, побеждает. В типичных 70% случаев это host-host или server-reflexive-server-reflexive, и TURN не задействован. В остальных 30% единственная рабочая пара – через TURN.
Секунды 1,5–1,8. Как только определена рабочая пара, на этом пути запускается DTLS-handshake. Обе стороны проверяют отпечаток сертификата против объявленного в SDP. Если совпадает – выводятся SRTP master keys, и медиа-путь живой.
Секунда 1,8. Первые RTP-пакеты пошли. Аудио микрофона Alice достигает Bob'а; видео камеры Bob'а – Alice. Общее время установки – меньше двух секунд.
На протяжении звонка. RTCP-отчёты летят в обе стороны каждые несколько секунд: потери пакетов, оценки RTT, обратная связь по bandwidth. Congestion controller каждой стороны подстраивает исходящий битрейт под доступную пропускную способность. Если путь упал, приложение может вызвать restartIce(), чтобы пересобрать кандидатов и выбрать новый путь – без обрыва звонка.
Для видеоконференции с тремя и более участниками замените «телефон Bob'а» на «SFU», и пусть каждый участник прогоняет тот же handshake против SFU. SFU – это особый WebRTC-эндпоинт, который одновременно общается со всеми участниками и форвардит пакеты между ними.
Числовой пример: реальная стоимость TURN-тяжёлого продукта
Представьте виджет поддержки, работающий в корпоративных help-desk сценариях: 60% звонков идут из enterprise-сетей, форсирующих TURN, средняя длина звонка 8 минут, общий двусторонний bandwidth 800 kbps (500 kbps видео + 300 kbps аудио + control). Ожидаемая нагрузка – 50 000 звонков в месяц.
TURN-трафик на звонок: 800 kbps × 60 секунд × 8 минут = 24 МБ входящих + 24 МБ исходящих = 48 МБ всего, если идёт через TURN. По всем 50 000 звонков × 60% TURN × 48 МБ = 1,44 ТБ TURN-трафика в месяц.
При типичной облачной цене TURN-egress 0,05 $/ГБ в 2026 году получается 72 $/мес за сам bandwidth. Если ещё платите за compute managed-сервису типа 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: либо TURN-сервера нет вообще, либо TURN только на UDP без TCP/443-fallback. Всегда запускайте TURN, всегда включайте TCP/443-fallback, всегда раздавайте TURN минимум из двух регионов, если ваши пользователи на разных континентах.
Использовать mesh для «маленьких» звонков больше двух человек. Mesh математически работает на 3–4 участников на идеальной сети и перестаёт работать на реальных консьюмерских соединениях при 4–5. К 6 участникам upload пробьёт потолок кабельного интернета. Стройте SFU с первого дня, даже если на старте отгружаете только двусторонние звонки; ретрофитить его позже сложнее, чем начать с него.
Делать signalling-сервер для галочки. Большинство отчётов «WebRTC ненадёжен» – это отчёты о слабом signalling-сервере, а не media-пути. Используйте проверенный 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 и observability. Читайте SDP, только когда отлаживаете конкретный кейс.
Где Фора Софт
Мы делаем WebRTC-продукты для видеостриминга, видеоконференций, e-learning, телемедицины, видеонаблюдения, OTT и AR/VR-клиентов с 2005 года – более 239 выпущенных проектов в этих вертикалях. Большая часть нашей WebRTC-работы в 2026 году – это один из трёх паттернов: кастомный SFU-стек на LiveKit или mediasoup для продуктов с полным контролем call-слоя; интеграция managed-backend (LiveKit Cloud, Daily, Vonage, Twilio, Agora) для команд, которым важно быстро выпуститься без эксплуатации серверов; и гибрид managed TURN с self-hosted SFU для защищённой стоимостной структуры на масштабе. Мы помогаем продуктовым командам выбрать между этими тремя паттернами, спроектировать signalling-протокол, спланировать TURN-ёмкость под географию пользователей и поставить call-quality-instrumentation, чтобы продакт-команда узнавала о происходящем раньше customer-success. Если вы проектируете WebRTC-продукт, выбор между этими тремя паттернами – самое последствительное решение первого месяца, и мы рады быть вторым мнением.
Дерево решений – топология за пять вопросов
Используйте дерево ниже как стартовую точку. Пять вопросов фильтруют до одного из четырёх ответов (mesh, SFU, MCU, гибрид), что покрывает 95% реальных продуктов.
- Сколько участников в одном звонке максимум? 2 → mesh достаточно. 3 – ~500 → SFU. 500+ → SFU плюс broadcast-доставка (гибрид).
- Нужен ли скомпонованный single-stream-output для каких-то участников? Да (запись, SIP-gateway, broadcast пассивной аудитории) → добавить MCU-стадию (гибрид). Нет → чистый SFU.
- Большинство пользователей в консьюмерских (дом, мобильный) или enterprise/ограниченных сетях? Консьюмер → бюджет TURN 30%. Enterprise → бюджет TURN 60–80%. Планируйте трафик соответственно.
- Нужно ли end-to-end шифрование, скрывающее медиа от вашего же SFU? Да → Insertable Streams или MLS E2EE (Signal-style); выбирайте SFU с поддержкой (LiveKit Cloud, Daily для enterprise, Zoom для платных). Нет → стандартный SRTP через SFU – это дефолт.
- Сколько инженерного ресурса можно потратить на call-инфраструктуру? Много → self-host SFU (LiveKit, mediasoup, Janus, Pion). Мало → managed-backend (LiveKit Cloud, Daily, Vonage, Twilio, Agora, Dolby.io).
Ключевые выводы
- WebRTC – это три вещи одновременно: API браузера, стек протоколов IETF и media pipeline.
- Signalling-канал вы пишете сами; спецификация WebRTC на этом останавливается.
- SDP – уродливый, но неизбежный язык переговоров о кодеках, ключах и параметрах.
- ICE находит рабочий путь; STUN раскрывает публичные адреса, TURN ретранслирует, когда ничего другого не работает.
- TURN обслуживает 30–70% реальных звонков и является крупнейшей операционной статьёй.
- SFU – дефолтная топология 2026; mesh – на двоих, MCU – для broadcast и записи.
- AV1 SVC, end-to-end шифрование и ИИ-агенты – три живые frontiers в 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/