Skip to main content
Back to Quickstart Guides

Mobile Streaming

Native iOS, Android, Flutter & React Native SDKs

45 minutes
Intermediate
iOS 14+ | Android API 24+
60%
Battery savings with hardware encoding
<500ms
Glass-to-glass latency
4K@60fps
Max supported resolution
99.9%
Stream uptime reliability

Choose Your Platform

Select the SDK that matches your development stack

Advantages

  • Native performance
  • Deep hardware integration
  • Excellent camera APIs

Considerations

  • Apple ecosystem only
  • App Store restrictions

Features

ScreenCaptureKit
ReplayKit
AVFoundation
Metal GPU
SDK Size: 2.3 MBMarket Share: 28%

Installation

Add WAVE SDK to your mobile project

Swift Package Manager (Recommended)

// Package.swift
dependencies: [
    .package(url: "https://github.com/wave-streaming/wave-ios", from: "2.0.0")
]

// Or in Xcode: File → Add Package Dependencies
// URL: https://github.com/wave-streaming/wave-ios

CocoaPods

# Podfile
pod 'WaveStreamingSDK', '~> 2.0'

# Then run:
pod install

Required Permissions (Info.plist)

<key>NSCameraUsageDescription</key>
<string>Camera access is required for live streaming</string>

<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for live streaming</string>

<key>UIBackgroundModes</key>
<array>
    <string>audio</string>
</array>

Complete iOS Example

import SwiftUI
import WaveStreamingSDK

struct StreamView: View {
    @StateObject private var wave = WaveClient(apiKey: "wave_live_xxxxx")
    @StateObject private var streamer: WaveStreamer
    @State private var isStreaming = false
    @State private var streamInfo: StreamInfo?

    init() {
        _streamer = StateObject(wrappedValue: WaveStreamer(
            camera: .front,
            resolution: .hd1080,
            fps: 30,
            orientation: .portrait,
            audio: AudioConfig(
                enabled: true,
                echoCancellation: true,
                noiseSuppression: true,
                sampleRate: 48000
            ),
            video: VideoConfig(
                stabilization: .cinematic,
                hdr: true,
                codec: .h265,
                bitrate: .adaptive(min: 1_000_000, max: 6_000_000)
            )
        ))
    }

    var body: some View {
        ZStack {
            // Camera preview
            WaveCameraPreview(streamer: streamer)
                .ignoresSafeArea()

            // Controls overlay
            VStack {
                Spacer()

                HStack(spacing: 20) {
                    // Switch camera
                    Button(action: { streamer.switchCamera() }) {
                        Image(systemName: "camera.rotate")
                            .font(.title2)
                            .foregroundColor(.white)
                            .padding()
                            .background(.ultraThinMaterial)
                            .clipShape(Circle())
                    }

                    // Start/Stop streaming
                    Button(action: { toggleStream() }) {
                        Image(systemName: isStreaming ? "stop.fill" : "record.circle")
                            .font(.largeTitle)
                            .foregroundColor(isStreaming ? .red : .white)
                            .padding()
                            .background(.ultraThinMaterial)
                            .clipShape(Circle())
                    }

                    // Beauty filter toggle
                    Button(action: { streamer.beautyFilter.toggle() }) {
                        Image(systemName: "sparkles")
                            .font(.title2)
                            .foregroundColor(streamer.beautyFilter.isEnabled ? .yellow : .white)
                            .padding()
                            .background(.ultraThinMaterial)
                            .clipShape(Circle())
                    }
                }
                .padding(.bottom, 40)
            }

            // Stream stats overlay
            if isStreaming, let info = streamInfo {
                VStack {
                    HStack {
                        Circle()
                            .fill(.red)
                            .frame(width: 8, height: 8)
                        Text("LIVE")
                            .font(.caption.bold())
                        Text("\(info.viewerCount) viewers")
                            .font(.caption)
                    }
                    .padding(.horizontal, 12)
                    .padding(.vertical, 6)
                    .background(.ultraThinMaterial)
                    .cornerRadius(20)

                    Spacer()
                }
                .padding(.top, 60)
            }
        }
        .onAppear {
            Task {
                await streamer.prepare()
            }
        }
    }

    private func toggleStream() {
        Task {
            if isStreaming {
                await streamer.stop()
                isStreaming = false
                streamInfo = nil
            } else {
                let stream = try await wave.streams.create(
                    title: "Mobile Stream",
                    protocol: .webrtc,
                    visibility: .public
                )

                try await streamer.start(streamId: stream.id)
                isStreaming = true

                // Listen for viewer updates
                for await info in wave.streams.observe(stream.id) {
                    streamInfo = info
                }
            }
        }
    }
}

Camera Capabilities Reference

Platform-specific camera features and recommendations

FeatureiOSAndroidRecommendedImpact
ResolutionUp to 4K@60fpsUp to 4K@60fps (device dependent)1080p@30fps for streamingHigher = more bandwidth + battery
HDRDolby Vision, HDR10HDR10, HDR10+ (flagship)Enable on supported devicesBetter color range, +20% bandwidth
StabilizationCinematic, Standard, OffOIS, EIS, HybridCinematic/Hybrid for walkingProfessional look, slight delay
Low LightNight Mode, Deep FusionNight Sight (Pixel), variesEnable in low-light scenariosBetter visibility, increased noise
FocusPhase detection, LiDARPDAF, Laser AF, Dual PixelFace tracking for streamersKeeps subject sharp

Network Adaptation Strategies

Handle poor mobile networks gracefully

Advantages

  • Best of both worlds
  • Content-aware

Trade-offs

  • Higher CPU usage
Min: 400 KbpsMax: 10 MbpsBest for: All scenarios

Network Adaptation Code

// Configure network adaptation
const networkConfig = {
  // Bitrate limits
  minBitrate: 300_000,    // 300 Kbps - never go below
  maxBitrate: 8_000_000,  // 8 Mbps - cap for mobile
  startBitrate: 1_500_000, // 1.5 Mbps - initial

  // Network-type presets
  presets: {
    wifi: { resolution: '1080p', fps: 30 },
    cellular_5g: { resolution: '1080p', fps: 30 },
    cellular_4g: { resolution: '720p', fps: 30 },
    cellular_3g: { resolution: '480p', fps: 24 },
  },

  // Adaptation behavior
  adaptationSpeed: 'aggressive', // 'smooth' | 'aggressive' | 'hybrid'
  connectionMonitoring: true,

  // Callbacks
  onNetworkChange: (quality) => {
    console.log(`Adapted to: ${quality.resolution}@${quality.bitrate}bps`);
    // Update UI indicator
  },
  onConnectionLost: () => {
    // Show reconnecting indicator
  },
};

streamer.setNetworkConfig(networkConfig);

Battery Optimization

Stream longer without draining the battery

TechniqueSavingsDescriptionImplementationTrade-off
Hardware Encoding40-60%Use device GPU instead of CPU for encodingEnabled by default in WAVE SDKNone - always recommended
Adaptive Resolution20-30%Lower resolution when battery is lowbatteryAwareMode: trueQuality reduction below 20% battery
Frame Rate Throttling15-25%Reduce FPS from 30 to 24 when neededminFrameRate: 24Slightly less smooth video
Thermal Management10-20%Reduce quality when device is hotthermalThrottling: truePrevents overheating shutdowns
Background Audio Only50-70%Stop video when app backgroundedbackgroundMode: "audio"No video in background

Battery-Aware Streaming

// Enable battery-aware mode
const streamer = new WaveStreamer({
  // ... camera config

  battery: {
    // Enable all battery optimizations
    batteryAwareMode: true,

    // Quality reduction thresholds
    lowBatteryThreshold: 20, // Start reducing at 20%
    criticalThreshold: 10,   // Audio-only below 10%

    // Thermal management
    thermalThrottling: true,
    maxTemperature: 45, // Celsius - reduce quality above this

    // Frame rate adaptation
    minFrameRate: 24, // Never go below 24fps

    // Background behavior
    backgroundMode: 'audio', // 'audio' | 'video' | 'pause'
  },

  // Callbacks
  onBatteryWarning: (level) => {
    alert(`Battery at ${level}%. Quality will be reduced.`);
  },
  onThermalWarning: (temp) => {
    console.log(`Device at ${temp}°C. Cooling down...`);
  },
});

AR Effects & Beauty Filters

Enhance streams with real-time face tracking and effects

Beauty Filters
Popular
  • Skin smoothing
  • Face slimming
  • Eye enlargement
  • Teeth whitening
Low impact (~5% CPU)
Face Masks
Popular
  • Animal ears
  • Glasses
  • Hats
  • Face paint
Medium impact (~15% CPU)
Backgrounds
Popular
  • Blur
  • Virtual backgrounds
  • Green screen
  • Bokeh
High impact (~25% CPU)
Lighting
  • Ring light
  • Studio lighting
  • Mood lighting
  • Color grading
Low impact (~8% CPU)

AR Effects Implementation

// Beauty filter configuration
streamer.beautyFilter.configure({
  enabled: true,
  level: 0.5, // 0-1 intensity

  // Individual controls
  skinSmoothing: 0.6,
  faceSlimming: 0.3,
  eyeEnlargement: 0.2,
  teethWhitening: 0.4,
});

// Face masks and effects
await streamer.effects.add({
  type: 'faceMask',
  asset: 'cat_ears',
  tracking: 'face', // 'face' | 'head' | 'body'
});

// Virtual backgrounds
await streamer.effects.add({
  type: 'background',
  mode: 'blur', // 'blur' | 'replace' | 'bokeh'
  intensity: 0.8,
  // Or replace with image:
  // mode: 'replace',
  // image: require('./background.jpg'),
});

// Lighting effects
await streamer.effects.add({
  type: 'lighting',
  preset: 'ring_light', // 'ring_light' | 'studio' | 'warm' | 'cool'
  intensity: 0.5,
});

// Performance tip: Limit to 3 simultaneous effects
console.log(`Active effects: ${streamer.effects.count}/3`);

Real-World Use Cases

How leading companies use WAVE mobile SDKs

TikTok-Style Social Streaming

🍎🤖

Key Features

Portrait mode
Beauty filters
AR effects
Duet support

Performance

Avg stream: 15 minutesViewers: 100-10KLatency: <800ms

"WAVE's mobile SDK let us ship our streaming feature in 3 weeks instead of 3 months. The AR effects library alone saved us a year of development."

MC
Maya Chen
CTO, Vibely

Sports & Fitness Broadcasting

🍎🤖💙

Key Features

Landscape + Portrait
Heart rate overlay
Multi-cam
Replay

Performance

Avg stream: 45 minutesViewers: 500-50KLatency: <500ms

"Our fitness instructors stream from iPhones and Android devices seamlessly. The battery optimization means they can teach a full 90-minute class without plugging in."

JM
Jake Morrison
Head of Product, FitStream

Live Commerce

🍎🤖⚛️

Key Features

Product overlays
Buy buttons
Inventory sync
Multi-camera

Performance

Avg stream: 60 minutesViewers: 1K-100KLatency: <1s

"We process $2M in sales per live stream. The sub-second latency means viewers can ask questions about products and get answers in real-time."

LW
Lisa Wang
VP Engineering, ShopLive

Troubleshooting Guide

Common issues and how to resolve them

Camera permission denied

Symptoms

  • Black preview
  • Permission dialog not showing

Causes

  • App not requesting permissions
  • User previously denied
  • Privacy settings

Solutions

  • Add camera permission to Info.plist (iOS) or AndroidManifest.xml
  • Use permission request APIs before accessing camera
  • Guide users to Settings if previously denied
High battery drain

Symptoms

  • Device overheating
  • Battery drops >1%/min

Causes

  • Software encoding
  • High resolution
  • 60fps
  • No thermal throttling

Solutions

  • Enable hardware encoding (default)
  • Reduce resolution to 720p for long streams
  • Enable thermalThrottling: true
  • Use batteryAwareMode for automatic adaptation
Stream keeps buffering

Symptoms

  • Viewers see loading spinner
  • Stream reconnects frequently

Causes

  • Poor network
  • Bitrate too high
  • Slow adaptation

Solutions

  • Reduce maxBitrate to 2 Mbps for mobile networks
  • Enable aggressive adaptation mode
  • Use networkMonitoring for proactive quality drops
Audio echo or feedback

Symptoms

  • Viewers hear themselves
  • Echo in recording

Causes

  • Echo cancellation disabled
  • Speaker audio captured
  • Bluetooth delay

Solutions

  • Enable echoCancellation: true
  • Use earphones/headphones when monitoring
  • Disable speaker playback during streaming
AR effects lag

Symptoms

  • Face tracking delayed
  • Effects stutter

Causes

  • Too many effects
  • Device limitations
  • High resolution

Solutions

  • Limit to 2-3 active effects
  • Reduce camera resolution to 720p
  • Use GPU-accelerated effects only
  • Test on target minimum device specs

Mobile Streaming Best Practices

Do

  • Request permissions before accessing camera/mic
  • Test on minimum supported devices, not just flagships
  • Show network quality indicator to streamers
  • Implement graceful reconnection logic
  • Use hardware encoding always (default in SDK)

Don't

  • Stream at 4K without checking device capabilities
  • Ignore thermal warnings - device may shut down
  • Use too many AR effects simultaneously (max 3)
  • Forget to handle app backgrounding
  • Skip echo cancellation for live interactions
WAVE - Enterprise Live Streaming Platform