Разработка групповых видеоконференций в мобильном приложении
Конференция на 2 участника и конференция на 10 — технически разные задачи. При peer-to-peer WebRTC на 5 участников каждый отправляет видео четырём остальным — итого 20 потоков на группу. iPhone 13 начинает перегреваться через 10 минут. Правильное решение для группы — SFU (Selective Forwarding Unit) или MCU.
Архитектура: SFU против MCU
MCU (Multipoint Control Unit) — сервер смешивает все потоки в один и отправляет каждому участнику одно видео. Нагрузка на клиент минимальная, но микширование на сервере требует мощного CPU и вносит задержку 100–300 мс. Подходит для вебинаров, где большинство смотрит одного.
SFU (Selective Forwarding Unit) — сервер только маршрутизирует потоки, не декодирует. Каждый клиент получает N потоков (по одному от каждого участника), но сам выбирает, какие декодировать и отображать. Нагрузка выше, зато задержка ниже и гибкость больше.
Для мобильного приложения с конференциями до 20 участников оптимален SFU. Готовые решения: Livekit (open-source, self-hosted), Mediasoup, Jitsi Videobridge, или managed-сервисы — Daily.co, 100ms, Twilio Video Rooms.
Livekit — хороший выбор для self-hosted: Go-сервер, WebRTC SFU, поддержка simulcast и dynacast, нативные SDK для iOS (LiveKit-iOS), Android (LiveKit-Android), Flutter и React Native. MIT-лицензия.
Simulcast: ключ к масштабируемости
Без simulcast на конференции 10+ человек мобильное устройство отправляет один поток 720p — и его получают все участники, даже те, у кого маленький тайл на экране. С simulcast клиент отправляет три качества одновременно (например 180p/360p/720p), а SFU отправляет каждому получателю подходящее качество по ширине тайла.
На iOS simulcast настраивается через RTCRtpEncodingParameters с тремя слоями:
let encodings = [
RTCRtpEncodingParameters(rid: "q", scaleResolutionDownBy: 4, maxBitrateBps: 150_000),
RTCRtpEncodingParameters(rid: "h", scaleResolutionDownBy: 2, maxBitrateBps: 500_000),
RTCRtpEncodingParameters(rid: "f", scaleResolutionDownBy: 1, maxBitrateBps: 1_200_000),
]
На Android — аналогично через RtpParameters.Encoding. Это снижает нагрузку на сеть и CPU у получателей при большом числе участников.
Отображение участников: grid и dominant speaker
Grid на 2–4 участника — статичный layout. На 5–16 участников — динамический grid, который меняется при входе/выходе. Правило: не пересоздавать RTCVideoRenderer при каждом обновлении grid — только переназначать track к существующему renderer. Пересоздание вызывает мигание и повторную отрисовку.
Dominant speaker detection — определяем, кто сейчас говорит, и выводим его крупнее. Livekit и 100ms предоставляют это из коробки через события onActiveSpeakersChanged. В сыром WebRTC — через анализ audioLevel из RTCPeerConnection.getStats().
На iOS рендеринг видео через RTCMTLVideoView (Metal) — обязательно для конференций. Старый RTCEAGLVideoView (OpenGL ES) не поддерживает несколько экземпляров с хорошей производительностью на A15+. При 6 участниках RTCEAGLVideoView даёт 40 FPS, RTCMTLVideoView — стабильные 60 FPS.
Батарея и термальное состояние
Групповая конференция — самый батареоёмкий режим приложения. Энкодинг видео 720p на 30 FPS потребляет ~15–20% заряда в час на iPhone 14. При 4+ участниках — ещё декодинг нескольких потоков.
Реагируем на ProcessInfo.thermalState (iOS) — при .serious или .critical понижаем разрешение до 360p и снижаем FPS до 15. На Android — PowerManager.getThermalHeadroom() (Android 11+). Это не деградация, а адаптация: лучше стабильная конференция в 360p, чем перегрев и принудительный throttling процессора.
При сворачивании приложения на iOS — останавливаем захват с камеры (AVCaptureSession.stopRunning()), аудио продолжает работать через AVAudioSession. На Android — ForegroundService с android:foregroundServiceType="camera|microphone" удерживает разрешения.
Типичные ошибки
Одна AVCaptureSession на всё приложение — не пересоздавать при каждом звонке. Инициализация сессии занимает 200–500 мс, пересоздание при каждом звонке заметно пользователю.
Не обрабатывать AVAudioSession.routeChangeNotification — подключение AirPods во время конференции без обработки этого уведомления уводит аудио в earpiece.
Не освобождать RTCVideoTrack при выходе участника из конференции — утечка памяти, которая накапливается при длинных сессиях и больших комнатах.
Процесс и сроки
Аудит требований → выбор SFU (self-hosted или managed) → интеграция SDK → UI (grid, dominant speaker, controls) → simulcast → адаптация к тепловому состоянию → нагрузочное тестирование.
Конференция до 8 участников через managed SFU (100ms, Daily) с готовым SDK — 2–4 недели. Self-hosted Livekit с кастомным UI и simulcast — 4–8 недель. Стоимость рассчитывается после анализа требований.







