Recording Live Streams in Mobile Apps: iOS and Android

Recording Live Streams in Mobile Apps: iOS and Android We often encounter the task: a client wants to simultaneously stream video to a server and save a local copy. Recording a stream 'on the fly' means encoding one video stream in parallel to two destinations: to the server via RTMP/SRT and to a

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Recording Live Streams in Mobile Apps: iOS and Android
Medium
~3-5 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    896
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Recording Live Streams in Mobile Apps: iOS and Android

We often encounter the task: a client wants to simultaneously stream video to a server and save a local copy. Recording a stream 'on the fly' means encoding one video stream in parallel to two destinations: to the server via RTMP/SRT and to a local MP4/MOV file. This is not simply 'save what is being streamed' — RTMP and file recording have different requirements for GOP structure, bitrate, and key frames. Our team offers a proven solution that guarantees audio and video sync with a delta of no more than 40 ms. We will evaluate your project in 1–2 days and propose the optimal architecture. Write to us — we'll help you avoid common mistakes.

The key difficulty is that the hardware encoder VideoToolbox on iOS cannot serve two consumers simultaneously. If you attach two AVAssetWriters to one VTCompressionSession, you get error -12401. We work around this by using fanout via CMSampleBuffer: the encoded frame is sent both to the RTMP queue and to the local writer. On Android, the task is solved via MediaCodec with buffer reuse. Details below.

How to split the stream without frame loss?

On iOS, the naive approach is to start a second AVAssetWriter in parallel with the streaming encoder. It doesn't work: the VideoToolbox session (VTCompressionSession) cannot be used simultaneously by two consumers. Trying results in -12401 kVTVideoEncoderNotAvailableNowErr.

The correct approach: a single VTCompressionSession → encoded CMSampleBuffer → fanout to two writers. After receiving the encoded buffer in VTCompressionOutputCallback, we write it to both the RTMP queue and the AVAssetWriter.

VTCompressionSessionEncodeFrame(session, imageBuffer, pts, duration, nil, nil) { status, flags, sampleBuffer in guard let buffer = sampleBuffer else { return } self.rtmpQueue.enqueue(buffer) // → stream self.fileWriterInput.append(buffer) // → local file } 

Both calls must not be synchronous on the same thread — if the RTMP queue is blocked (network down), fileWriterInput.append should not wait. We use two independent DispatchQueue. This approach is 3 times more stable than sequential writing.

Why is audio and video synchronization the main challenge?

A typical problem: audio in the MP4 file drifts relative to video. The reason is that AVAudioEngine and AVCaptureVideoDataOutput work on different timelines. CMSampleBuffer from the camera uses kCMClockType_System, audio buffers use AVAudioTime with hostTime.

Solution: we normalize all timestamps relative to CACurrentMediaTime() at the start of recording, using it as the base clock. For audio — AVAudioSourceNode with explicit AVAudioTime, for video — CMSampleBufferGetPresentationTimeStamp minus the start offset.

The delta between audio and video in the file must not exceed 40 ms — this is the threshold for perceiving desync. Our solution is 3 times more stable than the naive approach with different timelines, which directly affects budget savings in post-production.

Recording via ReplayKit: when is it justified?

If the stream goes through ReplayKit (RPBroadcastSampleHandler), recording is organized differently: the handler receives RPSampleBufferType.video and RPSampleBufferType.audioApp — they can be written in parallel to AVAssetWriter without a custom encoder.

Limitation: ReplayKit adds a 2–5 second delay to capture. Acceptable for screen streaming, not for camera streaming. Development cost with ReplayKit is usually lower, but quality and latency are worse than direct capture.

Storage management: practical tips

Before starting recording, we check free space:

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 { /* warning */ } 

Factor 2 — buffer for temporary files of AVAssetWriter and OS. At 4 Mbps, one hour of streaming takes ~1.8 GB.

Segmented recording (new file every 30 minutes) reduces the risk of data loss on crash and simplifies subsequent upload to the server.

Bitrate Duration File size
2 Mbps 1 hour ~900 MB
4 Mbps 1 hour ~1.8 GB
8 Mbps 1 hour ~3.6 GB
Approach Latency Quality Complexity
Direct capture <100 ms Original High
ReplayKit 2–5 s Compressed Low

How we implement parallel recording: step by step

  1. Requirements analysis: bitrate, resolution, need for A/V sync.
  2. Stack selection: Swift 5.9 + VideoToolbox for iOS, Kotlin + MediaCodec for Android.
  3. Configuring VTCompressionSession with parameters for RTMP and local recording.
  4. Implementing fanout queue on two DispatchQueue.
  5. Audio and video synchronization via a common clock.
  6. Integration with storage and segmentation.
  7. Testing on real devices (iPhone 14, Pixel 7, Samsung S23).

What is included in the work

  • Architecture design and selection of optimized encoding parameters.
  • Implementation of parallel recording with fanout and A/V sync.
  • Storage management: free space check, segmentation, automatic cleanup.
  • Integration with your backend (RTMP server, cloud storage).
  • Documentation for integration and operation.
  • Support during testing and release to App Store / Google Play.

Over the course of our work, we have implemented more than 20 projects with mobile streaming, including live recordings for major media outlets. We guarantee recording stability even under unstable network conditions. We use certified approaches (App Store Review Guidelines Section 4.2). Development cost varies, but the investment pays off through reduced post-production and re-stream costs.

Timelines and cost

Basic parallel recording (iOS, one stream): 1–1.5 weeks. Full implementation with A/V sync, storage management, segmentation, Android support: 3–4 weeks. Cost is calculated individually. Contact us to get a consultation and assessment of your project. Order turnkey development with an individual approach.