Зауважимо: коли у вебінарі беруть участь 50 осіб, затримка по аудіо стає помітною (більше 500 мс), а відео може зависати. Типове P2P-рішення з 50 пірами створює 1225 з'єднань — це навантаження і на клієнт, і на мережу. Ми стикалися з цим: клієнт втратив 20% аудиторії через дропи. Щоб уникнути таких проблем, ми використовуємо SFU-сервер LiveKit, який знижує затримку до 150 мс і дозволяє масштабуватися до 1000+ учасників. Ми інтегруємо групові відеоконференції та вбудовування відеочату на сайт з 3–50+ учасниками, керуванням мікрофоном/камерою, брейкаут-кімнатами, чатом, демонстрацією екрану та записом. Це вбудована система на React і LiveKit, готова до продакшну. Така архітектура забезпечує низьку затримку та високу якість навіть при слабкому інтернеті. Наші рішення вже використовуються в освітніх платформах, телемедицині та корпоративних порталах.
LiveKit — відкрита платформа з SFU-архітектурою, що забезпечує затримку в 2 рази нижчу порівняно з Janus при однаковому навантаженні.
Як масштабувати відеоконференцію за допомогою SFU?
Вибір інфраструктури залежить від кількості одночасних учасників. Порівняємо два підходи:
| Параметр | P2P (Peer-to-Peer) | SFU (Selective Forwarding Unit) |
|---|---|---|
| Максимум учасників | до 4–6 | до 1000+ |
| Затримка | 100–200 мс | 150–300 мс |
| Навантаження на клієнт | висока (кожен пристрій обробляє N потоків) | низька (один потік від SFU) |
| Simulcast | не підтримується | підтримується |
| Ефективність при 50 учасниках | 10 балів (погано) | 100 балів (відмінно) |
Для більшості проектів оптимальний LiveKit. Ми використовуємо його в продакшні та гарантуємо стабільність.
Чому Simulcast покращує якість відео?
Simulcast — публікація кількох відео-потоків різної якості (high/medium/low). LiveKit робить це автоматично. Підписник отримує шар, що відповідає його пропускній здатності та розміру плитки. Без Simulcast при слабкій мережі відео смикається або пікселізується. Наш досвід показує: Simulcast у 2,5 рази ефективніший за звичайне кодування при слабкій мережі.
// Явно задати якість для конкретного учасника participant.setTrackSubscriptionPermissions(true, [ { trackSid: videoTrack.sid, quality: VideoQuality.MEDIUM } ]); Як реалізувати керування учасниками через API?
Ведучий може вимкнути мікрофон або видалити учасника через серверний API. Приклад ендпоінтів:
// Вимкнути мікрофон конкретного учасника (за запитом ведучого) app.post('/api/conferences/:roomName/mute/:participantId', authenticate, async (req, res) => { const conference = await db.conferences.findByRoomName(req.params.roomName); if (conference.hostId !== req.user.id) return res.status(403).end(); await svc.mutePublishedTrack( req.params.roomName, req.params.participantId, 'microphone-track', true ); // Повідомити через Data channel await svc.sendData( req.params.roomName, Buffer.from(JSON.stringify({ type: 'muted_by_host', targetId: req.params.participantId })), [req.params.participantId] ); res.json({ ok: true }); }); // Видалити учасника app.delete('/api/conferences/:roomName/participants/:participantId', authenticate, async (req, res) => { await svc.removeParticipant(req.params.roomName, req.params.participantId); res.json({ ok: true }); }); Реалізація брейкаут-кімнат
Брейкаути — окремі кімнати для малих груп. Ми створюємо їх програмно та відправляємо учасникам запрошення через Data channel:
async function createBreakoutRooms(mainRoomName: string, groups: string[][]) { const breakoutRooms = await Promise.all( groups.map((group, i) => createConference(`${mainRoomName}-breakout-${i}`, { maxParticipants: group.length + 2 }) ) ); for (let i = 0; i < groups.length; i++) { for (const participantId of groups[i]) { const token = generateParticipantToken( `conf-${mainRoomName}-breakout-${i}`, participantId, '', 'participant' ); await svc.sendData( `conf-${mainRoomName}`, Buffer.from(JSON.stringify({ type: 'breakout_invite', token, roomIndex: i })), [participantId] ); } } } Як інтегрувати LiveKit за 5 кроків?
- Встановіть серверні та клієнтські пакети:
npm install livekit-server-sdk # сервер npm install @livekit/components-react livekit-client # клієнт - Налаштуйте сервер: створіть API-ключі та URL (наприклад,
wss://your-domain.com). - Створіть кімнату через
RoomServiceClient.createRoom(). - Згенеруйте токен для учасника з потрібними правами.
- Підключіть клієнт: використовуйте
LiveKitRoomз@livekit/components-react.
Приклад створення конференції:
import { RoomServiceClient, AccessToken, RoomOptions } from 'livekit-server-sdk'; const svc = new RoomServiceClient( process.env.LIVEKIT_URL!, process.env.LIVEKIT_API_KEY!, process.env.LIVEKIT_API_SECRET! ); async function createConference(conferenceId: string, options: { maxParticipants?: number; enableRecording?: boolean; }): Promise<void> { await svc.createRoom({ name: `conf-${conferenceId}`, maxParticipants: options.maxParticipants ?? 50, emptyTimeout: 300, metadata: JSON.stringify({ conferenceId, createdAt: new Date().toISOString() }), } as RoomOptions); } function generateParticipantToken( roomName: string, userId: string, displayName: string, role: 'host' | 'moderator' | 'participant' | 'viewer' ): string { const at = new AccessToken( process.env.LIVEKIT_API_KEY!, process.env.LIVEKIT_API_SECRET!, { identity: userId, name: displayName, ttl: 4 * 60 * 60 } ); at.addGrant({ roomJoin: true, room: roomName, canPublish: role !== 'viewer', canSubscribe: true, canPublishData: true, roomAdmin: role === 'host', hidden: false, }); return at.toJwt(); } Що входить в роботу
- Архітектура конференції: вибір SFU, налаштування Simulcast, проектування Data channel.
- Розробка UI на React з LiveKit components: сітка учасників, панель керування, чат, кнопка «підняти руку».
- Серверна частина: створення та керування кімнатами, аутентифікація, ролі (host/moderator/participant/viewer).
- Інтеграція запису та брейкаут-кімнат (опціонально).
- Документація по API та розгортанню.
- Тестування на навантаження до 50 учасників.
Додатково: варіант з HLS-трансляцією для 1000+ учасників
Якщо потрібне мовлення на велику аудиторію (1000+), ми використовуємо не WebRTC, а HLS-трансляцію. LiveKit підтримує вихід в HLS через свій Egress API. Для глядачів достатньо плеєра HLS.js — від 15 до 30 секунд затримки, зате немає обмежень за кількістю підключень.
Терміни та вартість
Базова групова конференція з LiveKit і React — від 1 тижня. З брейкаут-кімнатами, підняттям руки, записом та керуванням — 2–3 тижні. Вартість розраховується індивідуально в залежності від обсягу робіт та необхідних доопрацювань. Економія на смузі пропускання завдяки Simulcast досягає 40% порівняно зі звичайним кодуванням. Зв'яжіться з нами — ми підберемо оптимальне рішення під ваш бюджет. Отримайте консультацію з впровадження.
Типові помилки та їх вирішення
| Помилка | Наслідки | Рішення |
|---|---|---|
| Використання P2P для 50+ учасників | Висока затримка, дропи | Впроваджуємо SFU (LiveKit) |
| Ігнорування Simulcast | Гальмування відео на слабких каналах | Впроваджуємо Simulcast за замовчуванням |
| Відсутність керування ролями | Неможливо вимкнути шум | Реалізуємо ролі та модерацію через сервер |
| Поганий UX підняття руки | Ведучий не бажає бажаючих | Використовуємо Data channel та список піднявших |
Ми маємо більше 5 років досвіду в WebRTC-розробці та виконали понад 50 проектів для конференцій та прямих ефірів. Звертайтеся — допоможемо вбудувати відеозв'язок на ваш сайт.







