Зауважимо: коли у вебінарі беруть участь 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 проектів для конференцій та прямих ефірів. Звертайтеся — допоможемо вбудувати відеозв'язок на ваш сайт.







