Skip to content

Видеокомнаты

Planner включает видеоконференции на базе LiveKit SFU (Selective Forwarding Unit).

Архитектура

  • LiveKit Server — Docker-сервис (порты 7880 HTTP, 7881 WS, 3478 TURN, 50000-60000 UDP медиа)
  • Бэкендlivekit-server-sdk для управления комнатами и генерации токенов
  • Фронтендlivekit-client (WebRTC) для подключения к LiveKit SFU
  • WebSocket — пространство имён /video для signaling relay

Типы комнат

ТипОписание
instantНемедленный звонок + уведомления участникам
scheduledЗапланированная конференция + событие календаря + напоминания

API Endpoints

МетодПутьОписание
GET/api/video-roomsСписок комнат (фильтр: active/scheduled/ended)
POST/api/video-roomsСоздать комнату
GET/api/video-rooms/:idДетали комнаты
PATCH/api/video-rooms/:idОбновить комнату
DELETE/api/video-rooms/:idЗавершить/удалить комнату
POST/api/video-rooms/:id/joinПрисоединиться (возвращает LiveKit токен)
POST/api/video-rooms/:id/leaveПокинуть комнату
GET/api/video-rooms/:id/participantsСписок участников
POST/api/video-rooms/:id/tokenПолучить LiveKit токен
POST/api/video-rooms/:id/recording/startНачать запись
POST/api/video-rooms/:id/recording/stopОстановить запись
GET/api/video-rooms/:id/recording/statusСтатус записи

WebSocket события (/video)

Клиент → Сервер

СобытиеОписание
joinПрисоединиться к комнате (room:<id>)
leaveПокинуть комнату
signalWebRTC signaling relay

Сервер → Клиент

СобытиеОписание
video:participant_joinedУчастник подключился
video:participant_leftУчастник отключился
video:room_updatedКомната обновлена
video:call_startedНачат instant-звонок
video:recording_startedЗапись начата
video:recording_stoppedЗапись остановлена

Фронтенд

Store видеокомнат

typescript
const store = useVideoChatStore()
const { rooms, currentRoom, participants } = storeToRefs(store)

await store.fetchRooms()
await store.createRoom({ type, name, scheduledAt? })
await store.joinRoom(roomId)  // получает LiveKit токен
await store.leaveRoom(roomId)
await store.endRoom(roomId)

Composables

typescript
const {
  isConnected, remoteParticipants,
  isMuted, isScreenSharing, isRecording, isPiP
} = useLiveKit()

await liveKit.connect(tokenData)  // подключиться к LiveKit
liveKit.toggleMute('audio')      // вкл/выкл микрофон
liveKit.toggleMute('video')      // вкл/выкл камеру
liveKit.toggleScreenShare()      // демонстрация экрана
liveKit.startRecording(roomId)   // начать запись
liveKit.enterPiP()               // Picture-in-Picture

Компоненты

  • VideoRoomsView.vue (/video-rooms) — хаб с вкладками: Активные, Запланированные, Прошедшие
  • VideoRoomView.vue (/video-rooms/:id) — активная комната: VideoGrid + VideoControls + сайдбар участников + копирование ссылки
  • VideoGrid — сетка видео участников
  • ParticipantTile — плитка одного участника
  • VideoControls — панель управления (mute, камера, демонстрация, запись, выход)
  • ScheduleVideoDialog — диалог создания запланированной комнаты
  • VideoRoomCard — карточка комнаты в списке

Ключевые детали реализации

  • Запланированные комнаты создают CalendarEvent с типом video
  • Напоминания отправляются за 15 минут до начала (cron каждые 5 минут)
  • При скрытии вкладки автоматически включается Picture-in-Picture
  • Неактивные LiveKit-комнаты очищаются при инициализации модуля

Диалог входящего звонка

При 시작е мгновенного видеозвонка участники получают всплывающее окно IncomingCallDialog.vue:

  • Отображает имя звонящего и название комнаты
  • Принять → присоединиться к комнате и подключиться к LiveKit
  • Отклонить → отправить уведомление об отказе
  • Автоматически закрывается через 30 секунд