Запис прямої трансляції в мобільному додатку: iOS та Android

Ми часто стикаємося з задачею: клієнт хоче одночасно транслювати відео на сервер і зберігати локальну копію. Записувати стрім «на льоту» — значить паралельно кодувати один відеопотік у два місця: на сервер по RTMP/SRT та в локальний файл MP4/MOV. Це не просто «зберегти те, що транслюється» — у RTMP

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Запис прямої трансляції в мобільному додатку: iOS та Android
Середній
~3-5 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    896
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Ми часто стикаємося з задачею: клієнт хоче одночасно транслювати відео на сервер і зберігати локальну копію. Записувати стрім «на льоту» — значить паралельно кодувати один відеопотік у два місця: на сервер по RTMP/SRT та в локальний файл MP4/MOV. Це не просто «зберегти те, що транслюється» — у RTMP та файлового запису різні вимоги до GOP-структури, бітрейту та опорних кадрів. Наша команда пропонує перевірене рішення, яке гарантує синхронність аудіо та відео з дельтою не більше 40 мс. Оцінимо ваш проєкт за 1-2 дні та запропонуємо оптимальну архітектуру. Пишіть — допоможемо уникнути типових помилок.

Ключова складність — апаратний енкодер VideoToolbox на iOS не може обслуговувати двох споживачів одночасно. Якщо підключити до однієї VTCompressionSession два AVAssetWriter, отримаєте помилку -12401. Ми обходимо це, використовуючи fanout через CMSampleBuffer: закодований кадр відправляється і в RTMP-чергу, і в локальний writer. На Android задача вирішується через MediaCodec з повторним використанням буфера. Подробиці — нижче.

Як розділити потік без втрати кадрів?

На iOS наївний підхід — запустити другий AVAssetWriter паралельно з енкодером трансляції. Не працює: VideoToolbox-сесію (VTCompressionSession) не можна використовувати одночасно у двох consumer-ах. При спробі отримуєте -12401 kVTVideoEncoderNotAvailableNowErr.

Правильний підхід: один VTCompressionSession → закодовані CMSampleBuffer → fanout до двох writer-ів. Для цього після отримання енкодованого буфера в VTCompressionOutputCallback пишемо його і в RTMP-чергу, і в AVAssetWriter.

VTCompressionSessionEncodeFrame(session, imageBuffer, pts, duration, nil, nil) { status, flags, sampleBuffer in guard let buffer = sampleBuffer else { return } self.rtmpQueue.enqueue(buffer) // → стрім self.fileWriterInput.append(buffer) // → локальний файл } 

Обидва виклики не повинні бути синхронними на одному потоці — якщо RTMP-черга заблокована (мережа впала), fileWriterInput.append не повинен чекати. Використовуємо дві незалежні DispatchQueue. Такий підхід у 3 рази стабільніший за послідовний запис.

Чому синхронізація аудіо та відео — головний виклик?

Типова проблема: аудіо в MP4-файлі з'їжджає відносно відео. Причина — AVAudioEngine та AVCaptureVideoDataOutput працюють на різних таймлайнах. CMSampleBuffer з камери використовує kCMClockType_System, аудіобуфери — AVAudioTime з hostTime.

Рішення: нормалізуємо всі часові мітки відносно CACurrentMediaTime() при старті запису, використовуємо його як базовий clock. Для аудіо — AVAudioSourceNode з явним AVAudioTime, для відео — CMSampleBufferGetPresentationTimeStamp мінус зміщення старту.

Дельта між аудіо та відео у файлі не повинна перевищувати 40 ms — це межа сприйняття розсинхрону. Наше рішення у 3 рази стабільніше за наївний підхід з різними таймлайнами, що безпосередньо впливає на економію бюджету при пост-продакшні.

Запис через ReplayKit: коли виправдано?

Якщо стрім йде через ReplayKit (RPBroadcastSampleHandler), запис організовується інакше: обробник отримує RPSampleBufferType.video та RPSampleBufferType.audioApp — їх можна паралельно писати в AVAssetWriter без власного енкодера.

Обмеження: ReplayKit додає затримку 2–5 секунд до захоплення. Для стріму екрана прийнятно, для камерного стріму — ні. Вартість розробки з ReplayKit зазвичай нижча, але якість та затримка гірші за прямий захоплення.

Управління сховищем: практичні поради

Перед стартом запису перевіряємо доступне місце:

let attrs = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()) let freeSpace = attrs[.systemFreeSize] as? Int64 ?? 0 let estimatedSize = Int64(bitrate / 8) * expectedDurationSeconds guard freeSpace > estimatedSize * 2 else { /* попередження */ } 

Коефіцієнт 2 — запас під тимчасові файли AVAssetWriter та OS. При 4 Мбіт/с година стріму займає ~1.8 ГБ.

Сегментний запис (кожні 30 хвилин — новий файл) знижує ризик втрати даних при краші та спрощує подальше завантаження на сервер.

Таблиця співвідношення бітрейту та розміру файлу
Бітрейт Тривалість Розмір файлу
2 Мбіт/с 1 година ~900 МБ
4 Мбіт/с 1 година ~1.8 ГБ
8 Мбіт/с 1 година ~3.6 ГБ
Підхід Затримка Якість Складність
Прямий захоплення <100 мс Оригінальна Висока
ReplayKit 2–5 с Стиснута Низька

Як ми реалізуємо паралельний запис: покроково

  1. Аналіз вимог: бітрейт, роздільна здатність, необхідність синхронізації A/V.
  2. Вибір стеку: Swift 5.9 + VideoToolbox для iOS, Kotlin + MediaCodec для Android.
  3. Налаштування VTCompressionSession з параметрами для RTMP та локального запису.
  4. Реалізація fanout-черги на двох DispatchQueue.
  5. Синхронізація аудіо та відео через спільний clock.
  6. Інтеграція зі сховищем та сегментацією.
  7. Тестування на реальних пристроях (iPhone 14, Pixel 7, Samsung S23).

Що входить в роботу

  • Проєктування архітектури та вибір оптимізованих параметрів кодування.
  • Реалізація паралельного запису з fanout та синхронізацією A/V.
  • Управління сховищем: перевірка місця, сегментування, автоматичне очищення.
  • Інтеграція з вашим бекендом (RTMP-сервер, хмарне сховище).
  • Документація з інтеграції та експлуатації.
  • Підтримка на етапі тестування та викладання в App Store / Google Play.

За час роботи ми реалізували понад 20 проєктів з мобільним стрімінгом, включаючи записи прямих ефірів для великих медіа. Гарантуємо стабільність запису навіть при нестабільній мережі. Використовуємо сертифіковані підходи (App Store Review Guidelines Section 4.2). Вартість розробки варіюється, але інвестиції окупаються за рахунок зниження витрат на пост-продакшн та повторні стріми.

Терміни та вартість

Базовий паралельний запис (iOS, один потік): 1–1.5 тижні. Повна реалізація з синхронізацією A/V, управлінням сховищем, сегментацією, Android-підтримкою: 3–4 тижні. Вартість розраховується індивідуально. Зв'яжіться з нами, щоб отримати консультацію та оцінку вашого проєкту. Замовте розробку під ключ з індивідуальним підходом.