Мы разрабатываем видеозвонки в мобильных приложениях. Это не просто WebRTC-соединение: управление камерой и микрофоном, lifecycle на уровне системы, обработка прерываний (входящий звонок, уведомление, блокировка экрана), корректная работа в фоне и на низком заряде батареи. Каждая из этих деталей — отдельная задача с нетривиальными решениями на iOS и Android. Наш опыт в этой области превышает 7 лет, мы реализовали более 30 проектов с видеозвонками для клиентов из разных индустрий.
Какой транспорт выбрать: WebRTC или готовый SDK?
Чистый WebRTC — это RTCPeerConnection, RTCSessionDescription, ICE/STUN/TURN серверы, getUserMedia, сигналинг через WebSocket. Полная реализация с нуля занимает 3–6 недель только на транспортный слой, без UI.
Большинство проектов выбирают SDK поверх WebRTC: Twilio Video, Daily.co, 100ms, Livekit или Agora. Они берут на себя ICE negotiation, codec negotiation (VP8/VP9/H.264/AV1), адаптивный битрейт, и дают готовые нативные обёртки для iOS и Android.
Если требования к кастомизации невысоки и важна скорость запуска — выбираем SDK. Если нужен полный контроль над кодеком, шифрованием или минимальным весом бинарника — чистый WebRTC через GoogleWebRTC (iOS) или org.webrtc (Android).
| Критерий | WebRTC | SDK (Twilio/Agora) |
|---|---|---|
| Время разработки | 3–6 недель | 1–2 недели |
| Контроль | Полный | Ограниченный |
| Вес бинарника | Минимальный | Больше на 5–10 МБ |
| Поддержка кодеков | Любые | Ограничена SDK |
Как реализовать видеозвонок на iOS?
Видео с камеры захватывается через AVCaptureSession. Правильная инициализация:
let session = AVCaptureSession() session.sessionPreset = .hd1280x720 let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) let input = try AVCaptureDeviceInput(device: camera!) let output = AVCaptureVideoDataOutput() output.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue")) AVCaptureVideoDataOutput с делегатом даёт сырые CMSampleBuffer — их передаём в WebRTC через RTCVideoSource. Важно: AVCaptureSession.startRunning() вызывается строго в фоновом потоке, не на главном — иначе UI заморозится на 200–400 мс.
Переключение фронтальной/основной камеры — AVCaptureSession.beginConfiguration() + удаление старого input + добавление нового + commitConfiguration(). Без begin/commit вокруг этих операций — фликер на видео во время переключения.
CallKit — обязательный компонент для iOS-приложений с видеозвонками. Без него входящий звонок отображается как push-уведомление, которое может быть пропущено. С CallKit — полноэкранный системный экран звонка, интеграция с Bluetooth/AirPods, правильная обработка прерывания аудио. Реализуем через CXProvider и CXCallController. VoIP push через PKPushRegistry — единственный способ разбудить приложение для входящего звонка.
Как реализовать видеозвонок на Android?
На Android Camera2 API (CameraManager.openCamera()) даёт доступ к ImageReader с форматом YUV_420_888 — стандартный формат для WebRTC на Android. Для большинства задач хватает уровня CameraDevice.StateCallback + CaptureRequest.Builder.
ConnectionService — Android-аналог CallKit. Регистрируем PhoneAccount, через TelecomManager управляем состоянием звонка. Без этого на Android 10+ приложение не может работать в foreground во время звонка без постоянного уведомления.
Для сохранения соединения при сворачивании — ForegroundService с типом mediaProjection или phoneCall. На Android 14 это требует явного указания в манифесте: android:foregroundServiceType="camera|microphone".
Управление камерой и микрофоном
Mute микрофона — не отключение устройства, а замена аудио-трека на тишину. В WebRTC: RTCAudioTrack.isEnabled = false. Полное отключение микрофона на уровне AVAudioSession — ломает эхоподавление.
Flip камеры во время звонка — через RTCCameraVideoCapturer.stopCapture() + смена устройства + startCapture(with:fps:). Без полной остановки — крэш на некоторых устройствах Huawei и Xiaomi из-за состояния гонки в Camera2.
Поворот экрана — RTCVideoTrack сам по себе не учитывает ориентацию. Нужно передавать RTCVideoRotation в RTCVideoFrame при захвате с камеры, иначе собеседник увидит повёрнутое на 90° видео на устройствах с portrait-lock.
Качество соединения и адаптация
Адаптивный битрейт — базовая функция WebRTC (GCC алгоритм). Но нужно явно задать диапазон: RTCRtpEncodingParameters с minBitrateBps: 100_000 и maxBitrateBps: 1_500_000. Без ограничения сверху на Wi-Fi WebRTC попытается использовать 4–8 Мбит/с — это некомфортно для других пользователей сети.
Индикатор качества соединения через RTCPeerConnection.getStats() — парсим RTCInboundRtpStreamStats для framesPerSecond и packetsLost. Потери > 5% — показываем предупреждение пользователю.
Что входит в работу
- Аудит требований и выбор оптимального транспорта (WebRTC или SDK)
- Разработка сигналинга (WebSocket или сторонний сервер)
- Интеграция камеры и микрофона с AVCaptureSession/Camera2
- Подключение CallKit/ConnectionService для системных звонков
- Разработка UI: превью локального видео, удалённое видео, кнопки управления
- Адаптивный битрейт и контроль качества соединения
- Тестирование на реальных устройствах (iOS/Android)
- Документация по интеграции и передача исходного кода
- Поддержка после релиза (2 недели)
Процесс
- Аудит требований → 2. Выбор транспорта → 3. Реализация сигналинга → 4. Интеграция камеры/микрофона → 5. CallKit/ConnectionService → 6. UI и кнопки управления → 7. Тестирование на реальных устройствах → 8. Деплой в магазины.
Оценим ваш проект бесплатно. Напишите нам, и мы предложим оптимальное решение с учётом ваших сроков и бюджета. Базовый видеозвонок 1-на-1 через SDK (Twilio/Agora/100ms) с управлением камерой, mute и flip — 1–2 недели. Чистый WebRTC с сигналингом, CallKit, фоновый режим — 3–5 недель. Стоимость рассчитывается после анализа требований.







