Інтеграція трансляції в Twitch з мобільного додатка
Twitch Live Streaming SDK для iOS і Android — не той інструмент, який «просто підключив і працює». Типовий сценарій: розробник додає TwitchIVS або пробує IVSBroadcastSession, перший тест на симуляторі проходить, але на реальному iPhone 13 з нестабільним LTE стрім зависає через 90 секунд, тому що бітрейт не адаптується під пропускну здатність мережі.
Де все ломається на практиці
Amazon IVS (Interactive Video Service) — поточний офіційний шлях для Twitch-інтеграції на мобільному. SDK доступен через CocoaPods (AmazonIVSBroadcast) і Maven (com.amazonaws:ivs-broadcast). Головна біль — правильна настройка IVSBroadcastConfiguration.
За замовчуванням IVSVideoConfiguration встановлює фіксований бітрейт. При падінні сигналу енкодер продовжує пушити 3.5 Мбіт/с у буфер, буфер растає, затримка стрима йде за 30 секунд, глядачі бачать фриз. Рішення — включити адаптивний бітрейт через IVSAutoQualityMode і встановити minBitrate/maxBitrate діапазон: звичайно 300 кбіт/с–4000 кбіт/с для 720p30 стримів.
Друга проблема — ротація екрана. IVSBroadcastSession не стежить за зміною орієнтації автоматично. Якщо не перехопити UIDeviceOrientationDidChangeNotification і не викликати broadcastSession.setOrientation(_:), стрім у landscape буде трансльовано портретним кадром з чорними полосами. Android з CameraX те ж саме — потрібно підписатися на OrientationEventListener і передавати кут в imageCapture.targetRotation.
Аудіопайплайн окрема тема. На iOS IVSMicrophoneInput конфліктує з AVAudioSession, якщо додаток використовує фонове відтворення. AVAudioSession.setCategory(.playAndRecord, options: .mixWithOthers) знімає конфлікт, але його потрібно активувати до ініціалізації broadcast-сесії, інакше отримаєте OSStatus -10851 у логах.
Як будуємо інтеграцію
Стек для iOS: Swift 5.9+, AmazonIVSBroadcast 1.14+, AVFoundation, ReplayKit (для screen capture). Android: Kotlin, ivs-broadcast 1.14+, CameraX 1.3, MediaCodec.
Етапи:
1. Настройка IVS-каналу. Створюємо канал через AWS Console або Terraform-модуль, отримуємо ingest endpoint і stream key. Endpoint вида rtmps://a1b2c3d4e5f6.global-contribute.live-video.net:443/app/. Ключ зберігаємо в Keychain (iOS) або EncryptedSharedPreferences (Android) — не в конфігу додатка.
2. Конфігурація сесії. На iOS:
let config = IVSBroadcastConfiguration()
try config.video.setSize(CGSize(width: 1280, height: 720))
try config.video.setTargetFramerate(30)
try config.video.setInitialBitrate(2_500_000)
try config.video.setMinBitrate(300_000)
try config.video.setMaxBitrate(4_000_000)
config.video.usesBFrames = true
usesBFrames = true знижує бітрейт при тій же візуальній якості — включайте, якщо мінімальний iOS 14+.
3. Камера і мікрофон. Замість прямого використання AVCaptureSession — підключаємо через IVSBroadcastSession.listAvailableDevices(). SDK сам управляє AVCaptureSession, не потрібно створювати конкуруючу сесію. Якщо надо показувати превью — використовуємо IVSImagePreviewView, який SDK відає через attachCamera(_:toSlotWithName:previewAspectMode:).
4. Обробка мережевих подій. Реалізуємо IVSBroadcastSessionDelegate:
func broadcastSession(_ session: IVSBroadcastSession,
networkHealthChanged health: IVSBroadcastSessionHealth) {
switch health {
case .bad, .critical:
// Показуємо попередження користувачу, логуємо в Crashlytics
}
}
5. Завершення і очистка. broadcastSession.stop() асинхронний — не звільняйте сесію одразу. Чекаємо делегатний виклик broadcastSession(_:transmissionStatisticsChanged:) з нульовим бітрейтом, тільки потім broadcastSession = nil.
Тестування перед продакшеном
Перевіряємо поведінку при: внезапному розриві з'єднання (режим airplane mode на 10 секунд під час стрима), переключенні між Wi-Fi і LTE, вхідному дзвінку (переривання AVAudioSession). Для автоматичних тестів — IVSBroadcastSession підтримує testMode, який імітує відправку без реального RTMPS-підключення.
Нагрузовий сценарій: запускаємо стрім, через 5 хвилин включаємо network link conditioner з профілем 100% Loss на 15 секунд, дивимося, відновлюється ли сесія без краху й без утечки пам'яті у Xcode Instruments (allocations + leaks).
Терміни і оцінка
Базова інтеграція (одна камера, фіксована якість, iOS або Android): 1–2 тижні. Повнофункціональна реалізація з адаптивним бітрейтом, ротацією, обробкою перервань, превью та тестами — 3–5 тижнів. Якщо потрібна кросплатформа (Flutter з platform channels або React Native з нативними модулями) — додайте 1–2 тижні на інтеграційний шар.
Вартість розраховується індивідуально після аналізу вимог.







