Голосовой чат между игроками в кооперативной игре. Видеозвонок консультанта с клиентом прямо в личном кабинете, без перехода в Zoom. Комната, где несколько человек обсуждают проект и видят лица друг друга. Всё это — задача «передать живое видео и звук от одного пользователя к другому с минимальной задержкой», и она принципиально сложнее, чем разослать текстовое сообщение или обновить счёт в игре. В статье про Socket.io разобран свой сервер для событий вроде «игрок сходил» — там счёт идёт на байты и миллисекунды передачи текста. Видеозвонок — это постоянный поток мегабит в обе стороны, кодирование картинки на лету, адаптация под качество связи каждого участника и синхронизация звука с видео. Написать это руками поверх голого WebRTC — задача не для новичка и не для одного вечера с ИИ-ассистентом. LiveKit берёт эту сложность на себя: ты вызываешь готовый SDK, а медиасервер, кодеки и масштабирование остаются его заботой.
Содержание
- Что такое LiveKit и при чём тут архитектура SFU
- Чем LiveKit отличается от голого WebRTC
- Как это подключается на уровне концепции
- Self-hosted или LiveKit Cloud
- Стоимость
- Ограничения, о которых стоит знать заранее
- Практический пример: голосовой чат в игре и видеозвонок в личном кабинете
- Как попробовать LiveKit на практике
- Частые вопросы
- Заключение
Что такое LiveKit и при чём тут архитектура SFU
LiveKit — открытый SDK и серверная инфраструктура для звонков в реальном времени: видео, аудио, демонстрация экрана. Технически он построен поверх WebRTC — того же протокола, на котором работает Zoom или Google Meet в браузере, — но снимает с разработчика всю низкоуровневую возню с этим протоколом.
Ключевое архитектурное решение LiveKit — SFU, Selective Forwarding Unit, медиасервер, который стоит между участниками звонка. Без такого сервера у видеозвонка есть только один рабочий вариант — mesh, когда каждый участник соединяется напрямую с каждым. Для разговора вдвоём это ещё терпимо, но уже на пятерых число прямых соединений и, главное, число исходящих потоков с каждого устройства растёт так, что телефон или ноутбук участника захлёбывается собственным аплоадом задолго до того, как упрётся в лимиты сети.
SFU решает это иначе. Каждый участник отправляет свой видео- и аудиопоток один раз — на сервер LiveKit. Сервер получает эти потоки и раздаёт их остальным участникам, каждому — то, что нужно именно ему. Нагрузка на исходящий канал участника перестаёт расти вместе с числом собеседников: он всегда шлёт один поток, сколько бы человек ни было в комнате. Вся тяжёлая часть — маршрутизация, адаптация битрейта под связь каждого получателя, обработка отключений — происходит на сервере, а не на телефоне пользователя.
Отдельно стоит отличать SFU от MCU (Multipoint Control Unit) — более старого подхода, где сервер не просто пересылает потоки, а сводит их в одну общую картинку и отдаёт участникам уже смикшированное видео. MCU снимает нагрузку с клиента ещё сильнее, но требует от сервера постоянного перекодирования видео в реальном времени, что дорого по вычислениям и добавляет задержку. LiveKit выбрал SFU как более лёгкий и гибкий вариант — клиент сам решает, что и как отрисовать из полученных потоков, а сервер занимается только маршрутизацией.
Чем LiveKit отличается от голого WebRTC
WebRTC — это стандарт браузеров и мобильных платформ, а не готовый продукт. Он определяет, как два устройства могут обменяться медиапотоком напрямую, но ничего не говорит о том, как найти собеседника, как пройти через NAT и файрволы разных сетей, что делать, когда участников больше двух, и как реагировать, если связь у одного из них внезапно просела.
Вручную поверх WebRTC нужно поднять сигнальный сервер — отдельный канал, через которым участники обмениваются техническими данными, чтобы договориться о соединении. Нужны STUN- и TURN-серверы, которые помогают пробить NAT и, если напрямую пробиться не удалось, пересылают трафик через себя — без них звонок между двумя людьми в разных домашних сетях просто не установится в заметной доле случаев. Нужна логика на случай трёх и более участников, потому что голый WebRTC из коробки умеет только соединение точка-точка. И нужен код, который следит за качеством связи каждого собеседника и адаптирует поток под него — иначе один участник с плохим интернетом будет тормозить видео у всех.
LiveKit закрывает все эти пункты сразу: сигнальный сервер, TURN-инфраструктура, SFU для многосторонних звонков, адаптивный битрейт — всё это уже реализовано и спрятано за клиентским SDK. Разработчику остаётся вызвать несколько методов: подключиться к комнате, включить камеру и микрофон, отрисовать полученные потоки на экране. Сравнение с той же логикой, что в статье про Socket.io: там своя WebSocket-библиотека даёт полный контроль над сервером ценой того, что сервер — твоя забота. LiveKit устроен ровно наоборот по духу задачи: он не про контроль над каждым байтом видео, а про то, чтобы вообще не думать о протоколе и заниматься только продуктом.
Как это подключается на уровне концепции
Разворачивать WebRTC-протокол руками не нужно — работа сводится к нескольким понятным шагам на уровне архитектуры.
Сервер приложения выдаёт клиенту токен доступа — короткоживущий JWT, подписанный секретным ключом проекта, который разрешает конкретному пользователю попасть в конкретную комнату с определёнными правами (например, только слушать или ещё и говорить). Токен нельзя генерировать в браузере — секретный ключ должен оставаться на сервере, иначе любой пользователь сможет подделать себе доступ в чужую комнату.
Дальше клиентское приложение — на вебе, iOS или Android, у LiveKit есть SDK под основные платформы — подключается к серверу LiveKit с этим токеном и присоединяется к комнате. С этого момента SDK сам договаривается о соединении, поднимает медиапотоки камеры и микрофона и начинает получать потоки остальных участников комнаты.
Комната здесь — базовая единица: у неё есть имя, список участников и их права. Два человека в приватном видеозвонке — это комната на двоих. Групповой голосовой чат в игре — комната с несколькими участниками и без видео вовсе, только аудио. Логика создания и закрытия комнат, добавления участников — это уже код приложения, LiveKit даёт для этого API, но саму бизнес-логику — когда открывать комнату для звонка консультанта, когда закрывать голосовой канал после матча — пишет разработчик.
Self-hosted или LiveKit Cloud
LiveKit — открытый проект, и у него есть два пути развёртывания, которые стоит понимать ещё до того, как начинать интеграцию.
LiveKit Cloud — управляемая версия от самой компании. Регистрируешься, получаешь ключи проекта, и SFU-сервер уже работает на инфраструктуре провайдера — не нужно поднимать сервер, следить за его нагрузкой и масштабированием. Это ближе всего к тому, что новичку нужно для старта: подключение занимает время сопоставимое с чтением документации, а не с разворачиванием инфраструктуры.
Self-hosted — можно развернуть LiveKit-сервер самому, например через Docker, на собственном хостинге или сервере. Это даёт полный контроль над тем, где физически находятся данные звонков, и снимает зависимость от стороннего облака, но взамен требует того же, что и любой свой сервер реального времени: постоянно работающий процесс, мониторинг, обновления, а на серьёзной нагрузке — ещё и настройку TURN-серверов под свою сеть. Для игры или личного кабинета на старте это избыточная сложность, которую стоит откладывать до момента, когда для неё появится конкретная причина — например, требование хранить медиатрафик исключительно на своей инфраструктуре.
Для учебного проекта и для большинства реальных приложений на старте разумный дефолт — LiveKit Cloud: он снимает вопрос эксплуатации сервера точно так же, как управляемый сервис снимает его в других частях курса.
Стоимость
У LiveKit Cloud есть бесплатный тариф, которого достаточно, чтобы попробовать и собрать рабочий прототип. Дальше тарификация обычно привязана к объёму видео- и аудиотрафика через сервер — чем больше минут звонков и чем больше участников, тем выше счёт. Точные цифры здесь приводить смысла нет: условия меняются, актуальные тарифы и лимиты бесплатного плана стоит смотреть прямо на сайте LiveKit перед тем, как закладывать сервис в бюджет проекта.
Ограничения, о которых стоит знать заранее
LiveKit решает инфраструктурную часть звонка, но не снимает вопросы, которые всё равно ложатся на разработчика.
Клиентский код никуда не девается. SDK берёт на себя протокол, но отрисовку видео на экране, интерфейс кнопок «включить камеру», «выключить микрофон», индикаторы качества связи и реакцию на отключение собеседника всё равно пишет разработчик приложения.
Задержка сети остаётся физикой. SFU снимает нагрузку с клиента, но не отменяет законы связи: если у участника плохой интернет, видео у него будет тормозить или терять качество, сколько бы ни было мощности на сервере LiveKit.
Права доступа — забота приложения. LiveKit проверяет токен и то, что в нём записано, но решение о том, кому вообще разрешено попасть в комнату — например, что консультант видит только своих клиентов, а не чужих, — это логика на стороне сервера приложения, та же ответственность, что описана в статье про RLS-политики Supabase применительно к данным: правило «доступ имеет только тот, кому разрешено» переносится и на видеокомнаты.
Запись и хранение звонков — отдельная настройка. Если нужно сохранять видеозвонки для истории обращений или модерации, это дополнительная функциональность LiveKit, которую нужно осознанно включать и продумывать, где хранить получившиеся файлы.
Это не про голосовых ИИ-ассистентов из коробки. У LiveKit есть отдельный набор для голосовых агентов (LiveKit Agents) — фреймворк, который умеет подключать в звонок бота, слушающего и отвечающего голосом. Это соседняя, но другая задача: она пригодится, если в проекте нужен именно ИИ-собеседник в звонке, а не просто связь между живыми людьми. Для распознавания речи как таковой, отдельно от звонков, в курсе есть статья про Whisper — если задача сводится к «превратить голос в текст», необязательно поднимать инфраструктуру звонков вообще.
Практический пример: голосовой чат в игре и видеозвонок в личном кабинете
Разница между двумя сценариями — не в технологии, а в том, как приложение использует одни и те же примитивы LiveKit: комнату и потоки участников.
Голосовой чат между игроками. Когда матч начинается, сервер приложения создаёт комнату LiveKit с именем, привязанным к идентификатору партии, и выдаёт каждому игроку токен с правом говорить и слушать, но без видео — только аудиодорожка. Клиент подключается к комнате при входе в матч и отключается при выходе или завершении игры. Микрофон включён по умолчанию или по удержанию клавиши push-to-talk — это уже решение интерфейса, а не LiveKit. Когда матч заканчивается, комната закрывается, и ресурсы сервера освобождаются.
Видеозвонок в личном кабинете. Здесь комната создаётся не автоматически при входе, а по действию пользователя — например, кнопка «связаться с консультантом» в интерфейсе. Сервер приложения проверяет, что оба участника имеют право быть в этой конкретной комнате (клиент видит только своего консультанта, консультант — только назначенных ему клиентов), выдаёт токены с правом на видео и аудио и создаёт комнату на двоих. После завершения звонка комната закрывается автоматически, если оба участника вышли.
В обоих случаях LiveKit не знает и не должен знать о бизнес-логике игры или личного кабинета — кто с кем имеет право говорить, когда открывать и закрывать комнату. Это остаётся кодом приложения; LiveKit отвечает только за то, чтобы поток внутри уже созданной и разрешённой комнаты дошёл от одного участника до другого с минимальной задержкой.
flowchart TB
A["Клиент А
(камера + микрофон)"]
T["Сервер приложения
выдаёт токен"]
S["LiveKit SFU-сервер"]
B["Клиент Б
(камера + микрофон)"]
A -- "запрос токена" --> T
T -- "JWT-токен" --> A
A -- "медиапоток" --> S
S -- "медиапоток" --> B
B -- "медиапоток" --> S
S -- "медиапоток" --> A
Каждый клиент отправляет на сервер только один исходящий поток, а получает от сервера потоки остальных участников комнаты — это и есть та самая разгрузка, ради которой существует архитектура SFU.
Как попробовать LiveKit на практике
Самый быстрый путь для новичка — не разворачивать self-hosted сервер, а начать с LiveKit Cloud. Регистрация даёт тестовый проект с ключами API, которых достаточно, чтобы подключить SDK к простому прототипу — например, странице с двумя кнопками «войти в комнату» и «выйти».
Дальше стоит опираться на официальную документацию LiveKit — она держит актуальные примеры под конкретные платформы (веб, iOS, Android, React Native) и меняется вместе с версиями SDK быстрее, чем успевает устареть любой пересказ в статье. Для первого прототипа достаточно связки: серверная функция, которая выдаёт токен по запросу авторизованного пользователя, и клиентский код, который подключается к комнате этим токеном и отрисовывает видео участников на странице.
Если задача — не полноценный видеозвонок, а именно голосовой канал без видео (как в примере с игроками), в SDK для этого не нужен отдельный продукт: достаточно не запрашивать доступ к камере и не публиковать видеодорожку, оставив только аудио. Комната и токен устроены одинаково для обоих случаев — видео и аудио здесь не разные технологии, а разные типы потоков внутри одной и той же инфраструктуры.
Частые вопросы
LiveKit — это то же самое, что WebRTC?
Нет. WebRTC — открытый протокол, стандарт для передачи медиа между устройствами напрямую. LiveKit построен поверх WebRTC и добавляет то, чего в самом протоколе нет: SFU-сервер для многосторонних звонков, сигнальный сервер, TURN-инфраструктуру и клиентские SDK, которые прячут всю эту сложность за простым API.
Нужен ли LiveKit, если в приложении только текстовый чат?
Нет. Для текстовых сообщений и игровых событий реального времени решают другие инструменты — например, Socket.io или Supabase Realtime, как разобрано в статье про Socket.io. LiveKit имеет смысл подключать только тогда, когда в приложении реально нужны живое видео или аудио между пользователями.
Можно ли использовать LiveKit бесплатно?
У LiveKit Cloud есть бесплатный тариф, которого хватает для прототипа и небольших нагрузок. Актуальные лимиты и условия платных тарифов стоит смотреть прямо на сайте сервиса — они меняются, и приводить здесь точные цифры смысла нет.
Чем LiveKit Cloud отличается от self-hosted версии?
LiveKit Cloud — управляемая инфраструктура: регистрируешься, получаешь ключи, сервер уже работает и масштабируется без твоего участия. Self-hosted — разворачиваешь SFU-сервер сам, например через Docker, получаешь полный контроль над расположением данных, но берёшь на себя мониторинг, обновления и настройку TURN-серверов под свою сеть.
Подходит ли LiveKit для группового видеозвонка, а не только для двоих?
Да, именно для этого и существует архитектура SFU: сервер сам раздаёт потоки нескольким участникам, и клиенту не нужно устанавливать прямое соединение с каждым собеседником. Число участников в комнате ограничено тарифом и мощностью сервера, а не самой технологией.
Нужно ли самому писать сигнальный сервер для LiveKit?
Нет, сигнальный сервер уже встроен в инфраструктуру LiveKit. От разработчика приложения требуется только выдавать клиентам токены доступа через свой backend — сам обмен техническими данными для установки соединения SDK берёт на себя.
Заключение
LiveKit решает задачу, которая новичку в одиночку не по силам за разумное время — построение видео- и аудиосвязи в реальном времени поверх WebRTC. SFU-архитектура снимает с клиента нагрузку многосторонних соединений, а готовый SDK прячет сигнальный сервер, TURN-инфраструктуру и адаптивный битрейт за несколькими вызовами API. LiveKit Cloud — разумная точка входа для прототипа: не нужно поднимать и обслуживать сервер, чтобы проверить, работает ли голосовой чат в игре или видеозвонок в личном кабинете. Self-hosted вариант остаётся в запасе на случай, когда для полного контроля над инфраструктурой появится конкретная причина, а не просто желание перестраховаться заранее.
Читай дальше
Все статьиНе просто статьи — тебя доведут до результата
В практикуме за 2499 ₽ рядом живая команда практикующих разработчиков и маркетологов: ведём по шагам до твоего работающего приложения. Не «ролики и сам разбирайся» — помогаем на каждом затыке.
Перейти к практикуму