В видеозвонках на мобильных платформах главные проблемы — lifecycle и управление токенами. Без правильной настройки получаете утечки ресурсов, обрывы сессий и перерасход лицензий. Наш опыт более 30 проектов с Agora SDK позволил сформулировать рабочий подход.
Почему Agora SDK — лучший выбор для видеозвонков?
Agora SDK — managed-сервис real-time видео и аудио, который берёт на себя WebRTC под капотом, собственную транспортную сеть SD-RTN, адаптивный битрейт и кодеки. В сравнении с raw WebRTC: Agora ускоряет разработку видеозвонков в 12 раз (с 3 месяцев до 1 недели), но требует грамотного токен-менеджмента. Правильная интеграция даёт сокращение расходов на инфраструктуру до 40% за счёт использования SD-RTN.
Как правильно настроить токены и избежать ошибок?
Agora работает по модели App ID + Token. App ID — публичный идентификатор из консоли. Token — короткоживущий JWT, который ваш бэкенд генерирует через Agora Token Builder и передаёт клиенту при входе в канал. Самые частые ошибки в продакшене: tokenExpired (109) и invalidToken (110). Token имеет ограниченный TTL (от 24 часов до 1 часа). Реализуем обработку через tokenPrivilegeWillExpire делегатный метод — получаем новый токен с бэкенда и вызываем renewToken() без разрыва соединения.
Типичная ошибка: токен генерируется с UID 0 на бэкенде, но клиент после joinChannel получает конкретный UID от Agora — и при следующем renewToken передаёт токен под неправильный UID. Решение: сохраняем UID из didJoinChannel и используем его при запросе нового токена.
| Сценарий | TTL | Рекомендация |
|---|---|---|
| Стандартный | 24 часа | Баланс безопасности и частоты обновлений |
| Высокая нагрузка | 1 час | Снижает риск компрометации токена |
Инициализация движка
Инициализируйте движок один раз при старте приложения:
let config = AgoraRtcEngineConfig() config.appId = "YOUR_APP_ID" agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self) val config = RtcEngineConfig() config.mContext = context config.mAppId = "YOUR_APP_ID" config.mEventHandler = handler rtcEngine = RtcEngine.create(config) Не создавайте движок заново под каждый звонок. sharedEngine — синглтон, повторный вызов с тем же App ID возвращает существующий экземпляр. На Android RtcEngine.create() каждый раз создаёт новый экземпляр; предыдущий нужно уничтожить через RtcEngine.destroy(). Иначе утечка нативных ресурсов проявляется через 3–5 звонков. Используйте LifecycleObserver для автоматического уничтожения движка при завершении активности.
Подключение к каналу и обработка видео
let option = AgoraRtcChannelMediaOptions() option.clientRoleType = .broadcaster option.channelProfile = .communication agoraKit.joinChannel( byToken: token, channelId: channelName, uid: 0, mediaOptions: option ) uid: 0 — Agora назначает UID сама. Если нужна привязка к пользователю — передавайте детерминированный числовой ID (UInt32).
Локальное видео выводим через AgoraRtcVideoCanvas с setupLocalVideo(). Удалённое — через setupRemoteVideo() в делегатном методе didJoinedOfUid. Важно: setupRemoteVideo() вызывайте на main thread, иначе EXC_BAD_ACCESS при быстром подключении/отключении участников.
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { DispatchQueue.main.async { let canvas = AgoraRtcVideoCanvas() canvas.uid = uid canvas.renderMode = .hidden canvas.view = self.remoteVideoView self.agoraKit.setupRemoteVideo(canvas) } } Настройка качества видео
Agora предоставляет предустановки AgoraVideoEncoderConfiguration и кастомные параметры:
let config = AgoraVideoEncoderConfiguration( size: CGSize(width: 640, height: 360), frameRate: .fps15, bitrate: AgoraVideoBitrateStandard, orientationMode: .adaptative, mirrorMode: .auto ) agoraKit.setVideoEncoderConfiguration(config) Для мобильного приложения 360p/15fps — разумный баланс качества и батарейной нагрузки. 720p/30fps — для планшетов или когда качество критично. 1080p не подходит для мобильных: потребляет много энергии и ресурсов, а разница в восприятии между 720p и 1080p незначительна.
| Разрешение | fps | Битрейт | Нагрузка на батарею |
|---|---|---|---|
| 360p | 15 | Standard | Низкая |
| 720p | 30 | Standard | Средняя |
| 1080p | 30 | High | Высокая |
Как обработать прерывания и lifecycle?
На iOS AVAudioSession.routeChangeNotification и AVAudioSession.interruptionNotification — Agora SDK обрабатывает их автоматически при корректной настройке AgoraAudioScenario. Сценарий .meeting — оптимален для видеозвонков: включает AEC, ANS, AGC.
При входящем системном звонке Agora не паузируется автоматически. Реализуем через CXCallObserver: при CXCall.hasConnected == true — muteLocalAudioStream(true), при завершении — размьютим.
На Android без ForegroundService Android 8+ убьёт процесс через 5–10 минут. Запускаем ForegroundService при начале звонка с уведомлением. android:foregroundServiceType="camera|microphone" в манифесте обязателен с Android 14.
Что входит в интеграцию
- Анализ требований: количество участников, качество, бэкенд-интеграция, бюджет.
- Настройка токенов: генерация, кэширование, обработка протуханий.
- Реализация UI: видеоканвасы, органы управления, виртуальный фон.
- Lifecycle: ForegroundService на Android, CXCallObserver на iOS.
- Тестирование: 10+ сценариев (обрыв сети, входящий звонок, быстрая перекоммутация).
- Документация: README, комментарии кода, схема токенов.
- Поддержка: 2 недели после релиза, фиксация багов.
Сроки и стоимость
Базовая интеграция (1-на-1 видеозвонок с управлением камерой, mute, flip) — 3–5 дней. С поддержкой группы до 8 участников, токен-менеджментом и фоновым режимом — 1–2 недели. Стоимость рассчитывается после анализа требований. Свяжитесь с нами для оценки вашего проекта — мы подготовим смету и roadmap. Получите консультацию по интеграции Agora или закажите внедрение видеозвонков.







