Imagine: a user starts a stream, but within a minute viewers complain about delays and artifacts. Typical scenario: the mobile app uses software encoding, and the network can't handle the peak bitrate. Result—loss of audience and negative reviews. Overheating and rapid battery drain are another problem of software encoding. We know how to avoid this. Our team has implemented over 20 live streaming projects for iOS and Android, ensuring stability even on unstable connections. Resource savings: hardware encoding reduces power consumption by 90% compared to software. Behind every stream is a complex pipeline: camera capture, hardware encoding H.264/H.265, container packing, sending to a media server, and delivery to CDN. Each stage has its own API and pitfalls. Let's break them down in detail.
Video and Audio Capture
AVCaptureSession is the entry point on iOS. We configure the quality preset (sessionPreset = .hd1280x720), add AVCaptureDeviceInput for camera and microphone, add AVCaptureVideoDataOutput and AVCaptureAudioDataOutput with delegates. captureOutput(_:didOutput:from:) delivers CMSampleBuffer—raw camera frames in real time.
Orientation: AVCaptureConnection.videoOrientation must be updated on device rotation. Otherwise, viewers see video sideways if the stream starts in portrait.
On Android, we use Camera2 API or CameraX (recommended). CameraX.bindToLifecycle() with Preview + VideoCapture use case. VideoCapture.output.prepareRecording() is native recording. For streaming we need a raw stream: ImageAnalysis use case with setOutputImageFormat(OUTPUT_IMAGE_FORMAT_YUV_420_888), frames processed manually via MediaCodec.
| Platform | Capture API | Frame Stream |
|---|---|---|
| iOS | AVCaptureSession | CMSampleBuffer |
| Android | CameraX/Camera2 | YUV_420_888 (Image) |
Why Hardware Encoding?
Software FFmpeg on a phone means overheating and a dead battery in 20 minutes. We use only hardware encoders: VideoToolbox on iOS and MediaCodec on Android. This is 10 times more energy-efficient and delivers stable 30 fps at 720p. Our certified developers guarantee reliable hardware encoding integration.
On iOS: VideoToolbox—VTCompressionSession. We create a session with kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder: kCFBooleanTrue. The outputCallback receives CMSampleBuffer with encoded H.264/H.265.
Key parameters:
-
kVTCompressionPropertyKey_RealTime: kCFBooleanTrue— real-time mode -
kVTCompressionPropertyKey_ProfileLevel: kVTProfileLevel_H264_High_AutoLevel -
kVTCompressionPropertyKey_AverageBitRate: 2_000_000(2 Mbps for 720p) -
kVTCompressionPropertyKey_MaxKeyFrameInterval: 60(keyframe every 2 sec at 30 fps)
On Android: MediaCodec. MediaFormat.createVideoFormat("video/avc", width, height). configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE). In dequeueOutputBuffer we get encoded NAL units.
For audio: AudioRecord → MediaCodec with audio/mp4a-latm (AAC-LC). Sample rate 44100 Hz, bitrate 128 kbps.
How to Ensure Stream Stability?
Adaptive bitrate (ABR) is the key mechanism for camera live streaming. We monitor upload speed: RTMPStream.info.byteCount in HaishinKit, NetworkInfo callback in rtmp-rtsp-stream-client-java. If bandwidth drops, we sequentially reduce bitrate, framerate, and resolution. Optimal check interval is 5-10 seconds to avoid sharp quality swings. This approach reduces interruptions by 70%.
HaishinKit is a popular library for iOS handling RTMP and SRT streams. For Android, we similarly use rtmp-rtsp-stream-client-java.
Packaging into RTMP or SRT
From CMSampleBuffer/MediaCodec output we get H.264 NAL units and AAC frames. They need to be packed into a transport protocol. We use SRT for its network resilience, or RTMP for broad CDN compatibility.
Ready libraries:
- iOS: HaishinKit (Swift)—RTMP, SRT, HLS. Native Swift without FFmpeg dependency.
RTMPStream,SRTStream. - Android:
rtmp-rtsp-stream-client-java(Pedro Vicente)—RTMP and RTSP push.RtmpCamera2with CameraX.SRTStreamfor SRT. - Flutter:
rtmp_streaming(wrapper over native libraries) or native platform channel. - Cross-platform with FFmpeg:
ffmpeg-kit-ios/ffmpeg-kit-android—FFmpegKit.executeAsync("-f avfoundation -i 0:0 -c:v libx264 -preset ultrafast -f flv rtmp://..."). Works but loads CPU more than hardware encoder.
Comparison of RTMP and SRT
SRT is 2-3 times better than RTMP in latency and loss resilience.
| Characteristic | RTMP | SRT |
|---|---|---|
| Latency | 2-5 sec | 0.5-2 sec |
| Loss resilience | Low | High (FEC/ARQ) |
| CDN support | Wide | Growing |
| Use case | Traditional streams | Weak networks, webinars |
For mobile streaming, we recommend SRT because of its network resilience.
Preview and UI
Camera preview—AVCaptureVideoPreviewLayer (iOS) / PreviewView CameraX (Android). Overlay on top: "Live" indicator, viewer count, bitrate, signal level.
Switching front/rear camera without interrupting the stream: iOS—AVCaptureSession.beginConfiguration() → remove old input → add new → commitConfiguration(). HaishinKit supports this in one line: stream.captureSettings.isVideoMirrored.
What's Included in Live Streaming Work
- Video/audio capture from camera
- Hardware encoding with parameter tuning
- Integration of chosen protocol (RTMP/SRT/HLS)
- Adaptive bitrate and network monitoring
- Preview UI with overlay indicators
- Testing on real devices in various networks
- Integration documentation and post-launch support
Contact us to discuss your project. Order live streaming development—get a consultation from an experienced engineer. You can also request examples of our projects. We guarantee quality and proven experience with over 20 successful implementations.
Timelines
Single-platform streaming from camera (RTMP or SRT) with preview and basic UI: 3-5 days. Cross-platform with adaptive bitrate, camera switching, and specific media server integration: 1-2 weeks. Development cost starts from $3,000, with detailed quote after requirements analysis.







