Интеграция Agora SDK для видеосвязи в мобильном приложении
Agora — один из самых распространённых managed-сервисов для real-time видео и аудио. SDK берёт на себя WebRTC под капотом, собственную транспортную сеть (не публичный интернет), адаптивный битрейт и кодеки. Задача интеграции — не просто добавить зависимость, а правильно настроить lifecycle, токены, обработку событий и UI.
Инициализация и токены
Agora работает по модели App ID + Token. App ID — публичный идентификатор из консоли. Token — короткоживущий JWT, который генерирует ваш бэкенд через Agora Token Builder и передаётся клиенту при входе в канал.
Инициализировать движок нужно один раз при старте приложения:
// iOS
let config = AgoraRtcEngineConfig()
config.appId = "YOUR_APP_ID"
agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
// Android
val config = RtcEngineConfig()
config.mContext = context
config.mAppId = "YOUR_APP_ID"
config.mEventHandler = handler
rtcEngine = RtcEngine.create(config)
Повторная инициализация при каждом звонке — ошибка. sharedEngine — синглтон, повторный вызов с тем же App ID просто возвращает существующий экземпляр. RtcEngine.create() на Android — нет: каждый вызов создаёт новый экземпляр, предыдущий нужно уничтожить через RtcEngine.destroy(). Это не очевидно из документации, но утечка нативных ресурсов проявляется через 3–5 звонков.
Подключение к каналу и обработка видео
let option = AgoraRtcChannelMediaOptions()
option.clientRoleType = .broadcaster
option.channelProfile = .communication
agoraKit.joinChannel(
byToken: token,
channelId: channelName,
uid: 0, // 0 = автогенерация
mediaOptions: option
)
uid: 0 — Agora назначает UID сама. Если нужна привязка к пользователю системы — передавайте детерминированный числовой ID (не UUID — Agora UID это 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 — для планшетов или когда качество критично. AgoraVideoBitrateStandard — автоматический выбор битрейта под разрешение, работает лучше, чем ручная установка в большинстве сценариев.
Обработка прерываний и lifecycle
На iOS AVAudioSession.routeChangeNotification и AVAudioSession.interruptionNotification — Agora SDK обрабатывает их автоматически при корректной настройке AgoraAudioScenario. Сценарий .meeting — оптимален для видеозвонков: включает AEC (акустическое эхоподавление), ANS (шумоподавление), AGC (нормализация громкости).
При входящем системном звонке на iOS Agora не паузируется автоматически. Реализуем через CXCallObserver и callObserver(_:callChanged:): при CXCall.hasConnected == true — mute локального аудио в Agora (muteLocalAudioStream(true)), при завершении — размьютим.
На Android при переходе в фоновый режим без ForegroundService — Android 8+ убьёт процесс через 5–10 минут. Запускаем ForegroundService при начале звонка с уведомлением. android:foregroundServiceType="camera|microphone" в манифесте обязателен с Android 14.
Ошибки аутентификации токена
AgoraErrorCode.tokenExpired (109) и AgoraErrorCode.invalidToken (110) — наиболее частые проблемы в продакшене. Token имеет ограниченный TTL (от 24 часов до 1 часа в зависимости от настроек). Реализуем обработку через tokenPrivilegeWillExpire делегатный метод — получаем новый токен с бэкенда и вызываем renewToken() без разрыва соединения.
Типичная ошибка: токен генерируется с UID 0 на бэкенде, но клиент после joinChannel получает конкретный UID от Agora — и при следующем renewToken передаёт токен, сгенерированный под неправильный UID. Нужно сохранять UID из didJoinChannel и использовать его при запросе нового токена.
Сроки
Базовая интеграция (1-на-1 видеозвонок с управлением камерой, mute, flip) — 3–5 дней. С поддержкой группы до 8 участников, токен-менеджментом и фоновым режимом — 1–2 недели. Стоимость рассчитывается после анализа требований.







