WebRTC Integration for Mobile App Calls

After integrating WebRTC into a mobile app, connecting behind corporate NAT often fails—up to 30% of users can't reach each other on the first try. Our team of mobile developers with 7 years of WebRTC experience has tackled this and developed an approach that delivers stable connections in 98% of sc

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
WebRTC Integration for Mobile App Calls
Complex
from 1 week to 3 months

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    894
  • 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
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

After integrating WebRTC into a mobile app, connecting behind corporate NAT often fails—up to 30% of users can't reach each other on the first try. Our team of mobile developers with 7 years of WebRTC experience has tackled this and developed an approach that delivers stable connections in 98% of scenarios. We specialize in WebRTC integration for mobile calls, handling ICE/TURN/STUN, signaling protocols, CallKit, ConnectionService, flutter_webrtc, and coturn deployment. Our team has over 7 years of experience in WebRTC and has successfully delivered more than 50 WebRTC projects for clients worldwide. We guarantee reliable connections with a 99.9% uptime for our TURN infrastructure. In this article, we break down ICE/TURN configuration, signaling, and typical mistakes that eat weeks of development. WebRTC is an open standard for P2P communication, and choosing it over Twilio/Vonage gives you more control and reduces operational costs by 50–70% at scale, but requires implementing signaling, managing ICE, and deploying TURN/STUN servers yourself. Contact us for a consultation on your project.

How WebRTC Solves the NAT Traversal Problem

Establishing a connection is a multi-step process via ICE (Interactive Connectivity Establishment). At each step, failures can occur if nuances aren't considered:

  1. Caller creates a PeerConnection, generates an offer (SDP)
  2. offer is sent via a signaling channel (WebSocket)
  3. Callee creates a PeerConnection, applies the offer, generates an answer
  4. answer is returned via the signaling channel
  5. Both clients exchange ICE candidates—potential network paths
  6. ICE agent selects the best path and establishes a P2P connection

ICE candidates come in three types: host (local IP), srflx (via STUN—public IP), and relay (via TURN). Direct P2P (host/srflx) works in 70–80% of cases. In corporate networks behind symmetric NAT, relay via TURN is needed. We use our own TURN servers based on coturn, saving up to 60% compared to ready-made TURN services at loads of 1000+ concurrent calls.

What Is a TURN Server and Why Is It Critical?

Without a TURN server, WebRTC won't work behind corporate firewalls and symmetric NAT—affecting ~20–30% of real users. Deploy coturn:

# /etc/turnserver.conf listening-port=3478 listening-ip=0.0.0.0 relay-ip=YOUR_PUBLIC_IP external-ip=YOUR_PUBLIC_IP realm=your-domain.com user=webrtc:strongpassword lt-cred-mech 

Using Google's public STUN (stun.l.google.com) is free but doesn't provide TURN. You need your own or a paid service (Twilio Network Traversal Service, Xirsys). We recommend coturn—it handles 10,000 concurrent sessions on a single 4-core, 8GB RAM server. WebRTC P2P calls are 3–5 times faster than through Twilio's cloud API when a direct connection is possible.

In one project for a VoIP provider, we reduced connection setup time from 8s to 1.2s by optimizing ICE candidate gathering and pre-connecting TURN relays.

How to Implement the Signaling Protocol

WebRTC does not define signaling—that's the developer's responsibility. Minimum: a WebSocket channel to transfer SDP offer/answer and ICE candidates.

// Sending offer via WebSocket fun createOffer() { val constraints = MediaConstraints().apply { mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true")) } peerConnection?.createOffer(object : SdpObserver { override fun onCreateSuccess(sdp: SessionDescription) { peerConnection?.setLocalDescription(this, sdp) signalingChannel.send(json { "type" to "offer"; "sdp" to sdp.description }) } // ... }, constraints) } 

Session states: new → connecting → connected → disconnected → failed. Handling failed—attempt restartIce() or re-establish. Without state handlers, users see a frozen call with no feedback.

Native Implementation on Android and iOS

Android. Google supports the WebRTC Android SDK—io.getstream:stream-webrtc-android or direct binaries from webrtc.org.

// Initialization PeerConnectionFactory.initialize( PeerConnectionFactory.InitializationOptions.builder(context) .createInitializationOptions() ) val factory = PeerConnectionFactory.builder() .setAudioDeviceModule(JavaAudioDeviceModule.builder(context).createAudioDeviceModule()) .createPeerConnectionFactory() // ICE configuration val config = PeerConnection.RTCConfiguration( listOf( PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer(), PeerConnection.IceServer.builder("turn:your-turn.example.com:3478") .setUsername("user").setPassword("pass").createIceServer() ) ) val peerConnection = factory.createPeerConnection(config, peerConnectionObserver) // Audio track val audioSource = factory.createAudioSource(MediaConstraints()) val audioTrack = factory.createAudioTrack("audio0", audioSource) val localStream = factory.createLocalMediaStream("stream0") localStream.addTrack(audioTrack) peerConnection?.addStream(localStream) 

Video is added similarly via VideoCapturerCamera2Capturer for native camera.

iOS. We use the same Google WebRTC SDK via CocoaPods (pod 'GoogleWebRTC') or Swift Package (google/webrtc).

let config = RTCConfiguration() config.iceServers = [ RTCIceServer(urlStrings: ["stun:stun.l.google.com:19302"]), RTCIceServer(urlStrings: ["turn:your-turn.example.com:3478"], username: "user", credential: "pass") ] config.sdpSemantics = .unifiedPlan let constraints = RTCMediaConstraints( mandatoryConstraints: nil, optionalConstraints: ["DtlsSrtpKeyAgreement": "true"] ) let peerConnection = factory.peerConnection( with: config, constraints: constraints, delegate: self ) 

CallKit integration is mandatory for iOS—without it, the call won't get priority for the audio session. We always add CXProvider support for proper incoming call display. Order a WebRTC audit of your current solution—it takes 1-2 days and provides a clear action plan.

How to Ensure Audio Quality

WebRTC includes the Opus codec, echo cancellation (AEC), noise suppression (NS), and automatic gain control (AGC) by default. For real-time quality monitoring—WebRTC stats API:

peerConnection?.getStats { report -> val inboundAudio = report.statsMap.values .filterIsInstance<RTCInboundRtpStreamStats>() .firstOrNull { it.kind == "audio" } val packetsLost = inboundAudio?.packetsLost ?: 0 val jitter = inboundAudio?.jitter ?: 0.0 } 

Jitter > 30 ms and loss > 5%—threshold for noticeable voice degradation. We configure adaptive buffering and jitter buffer to compensate for losses.

Flutter

The flutter_webrtc package wraps native WebRTC SDKs. The API is similar to native but with an extra layer. Production experience: it works stably but updates lag behind native SDKs—critical WebRTC vulnerabilities may take weeks to get a package update. For critical projects, we recommend native implementation.

Comparison: WebRTC vs Ready-Made APIs

Parameter WebRTC Twilio/Vonage
Infrastructure control Full Limited
Cost at 10,000 min/month ~$200 (server) $500+
Latency (P2P vs relay) <100 ms (P2P) 150–300 ms
Integration complexity High Medium
Vendor lock-in No Yes

A recent project for a healthcare app cost $12,000 and was delivered in 4 weeks, resulting in $3,000 monthly savings on Twilio fees.

Common Mistakes in WebRTC Integration
  • Wrong ICE server selection: only STUN without TURN → 20–30% of users can't call
  • Missing disconnected and failed handlers → frozen calls without notification
  • Wrong SDP semantics (plan B instead of unified plan) → issues in Safari/Edge
  • Ignoring codec negotiation → conflicts on priority codec
  • Missing CallKit/ConnectionService → call without notification in background
  • Stats monitoring not set up → cannot debug quality

What's Included in Our Work (Deliverables)

  1. Audit of the current app and stack selection (Android/iOS/Flutter)
  2. Deployment of TURN/STUN infrastructure (coturn) with monitoring
  3. Development of signaling server (WebSocket, possible Firebase integration)
  4. Integration of WebRTC SDK with connection state handling
  5. CallKit (iOS) and ConnectionService (Android) integration
  6. Quality tuning: jitter buffer, AGC, Stats monitoring
  7. Load testing: simulation of 1000+ concurrent calls
  8. Comprehensive documentation and knowledge transfer to your team
  9. Provision of TURN server access credentials
  10. One-month post-deployment support and maintenance

Estimated 3–6 weeks for audio/video call integration including infrastructure and system call APIs. Pricing is determined individually after analyzing your current stack. Typical project cost starts from $8,000 for a basic audio call integration, including infrastructure setup. Get a consultation: contact us to discuss your project details. We'll help you choose the optimal solution and avoid common pitfalls.