Building a Mobile Application for Webinars
A webinar on mobile is a direct competitor to Zoom, Webex, and Google Meet in a specific niche. That means requirements aren't just "make a video call" but: stable video stream under poor network conditions, screen sharing, chat with reactions, participant roles (host / speaker / audience), recording and playback. All of this on iOS and Android with latency under 500 ms.
Architectural Choice: WebRTC vs Ready-Made SDK
Building a video conference from scratch on WebRTC is possible but requires 3-6 months just for the media engine. For most products, the right choice is a specialized SDK that handles the SFU, codecs, adaptive bitrate, and network overload management.
Livekit SDK — open source, self-hosted SFU, MIT license. iOS/Android/Flutter SDK. The standard for new projects where data control matters. Room, LocalParticipant, RemoteParticipant — simple object model.
Agora SDK — powerful but cloud-based with per-second billing. Good when global CDN and minimal DevOps are priorities.
Daily.co, 100ms, Whereby — cloud alternatives with various pricing models.
Twilio Video — mature API, but Twilio froze Video development in 2023.
For self-hosted: Livekit + Janus + MediaSoup — the three most actively maintained SFUs.
Video and Audio: Network Adaptation
The main challenge with mobile webinars is switching between Wi-Fi and LTE mid-presentation. An SFU with simulcast solves this: the speaker sends 3 video qualities (720p/360p/180p), and the server chooses the optimal one for each listener based on their bandwidth.
Livekit: simulcast enabled via flag VideoPublishOptions(simulcast: true). iOS: LKLocalVideoTrack with CameraSource. Android: LocalVideoTrack + Camera2Source. Automatic resolution reduction on packet loss is built into the SFU.
Dynacast (Livekit) — automatically pauses video tracks of speakers whom no listeners are viewing. Saves server-side bandwidth with 50+ participants.
Audio: Opus codec, 48 kHz, AEC + NS + AGC built-in to WebRTC. Speakerphone vs earpiece: AVAudioSession.overrideOutputAudioPort(.speaker) / AudioManager.setSpeakerphoneOn(true). Automatic: enable speakerphone for 2+ participants, earpiece for 1-on-1.
Screen Sharing
iOS (ReplayKit). RPScreenRecorder.shared().startCapture(handler:) — works from iOS 11, available from Control Center in iOS 12+. Screen capture returns CMSampleBuffer — pass into WebRTC RTCVideoCapturer through a custom RTCVideoCapturerDelegate. Limitation: in RPBroadcastSampleHandler (Extension) you can't directly call main app code — use App Group + CFMessagePort or Darwin notifications for state transfer.
iOS 15+ RPSystemBroadcastPickerView — native button to launch broadcast without code.
Android (MediaProjection API). MediaProjectionManager.createScreenCaptureIntent() → user confirms → VirtualDisplay → capture frames via ImageReader → VideoEncoder → WebRTC VideoSource. Requires Foreground Service with type mediaProjection (Android 10+). In manifest: <service android:foregroundServiceType="mediaProjection"/>.
Flutter: flutter_screen_capture (native bindings to both APIs) or custom plugin with platform channels.
Chat, Reactions, Q&A
Real-time chat: WebSocket or Livekit DataChannel (LocalParticipant.publishData). DataChannel works over the same RTC connection — no separate WebSocket server needed.
Reactions (👏🔥❤️): instant animation for all participants. Send via DataChannel, render with particle animation over video grid. iOS: UIViewPropertyAnimator + CAEmitterLayer. Android/Compose: AnimatedVisibility + LaunchedEffect.
Q&A: question queue with upvote. Storage on server (Livekit RPC or separate REST). Host sees prioritized list.
Roles and Access
Host, co-host, speaker, audience. Differences in permissions: audience doesn't publish video/audio (bandwidth savings), can only raise hand → host gives word.
Livekit: ParticipantPermission — canPublish, canPublishData, canSubscribe. Set by server when creating token or changed via RoomServiceClient.updateParticipant.
"Raise hand": DataChannel message {type: "raise_hand", participantId: "..."} → indicator appears for host.
Recording Webinar
Livekit Egress: cloud recording to S3/R2. EgressServiceClient.startRoomCompositeEgress() — records composite view (all participants in grid) or track-by-track (separate tracks for editing). Format: MP4 with H.264 + AAC.
Recording access: presigned S3 URL with 24h TTL. In app — player (AVPlayer / ExoPlayer) with seeking and playback speed.
Stages and Timeline
| Stage | Timeline |
|---|---|
| SFU choice and server setup | 1 week |
| Video/audio room, roles | 2–3 weeks |
| Chat, reactions, Q&A | 1 week |
| Screen share iOS + Android | 1 week |
| Recording and playback | 1 week |
| Load testing (50+ participants) | 1 week |
Total: MVP webinar app — 6–8 weeks. With event registration, email campaigns, attendance analytics — 10–12 weeks.







