Інтеграція WebRTC для дзвінків у мобільному додатку

Після інтеграції WebRTC у мобільний додаток часто стикаються з проблемою встановлення з'єднання за корпоративними NAT — до 30% користувачів не можуть додзвонитися з першого разу. Ми, команда мобільних розробників з 7-річним досвідом у WebRTC, пройшли це та розробили підхід, що дає стабільний зв'язок

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Інтеграція WebRTC для дзвінків у мобільному додатку
Складний
від 1 тижня до 3 місяців

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Після інтеграції WebRTC у мобільний додаток часто стикаються з проблемою встановлення з'єднання за корпоративними NAT — до 30% користувачів не можуть додзвонитися з першого разу. Ми, команда мобільних розробників з 7-річним досвідом у WebRTC, пройшли це та розробили підхід, що дає стабільний зв'язок у 98% сценаріїв. Ми гарантуємо 98% успішних з'єднань. Наші сертифікати підтверджують компетентність у WebRTC та мобільній розробці. У цій статті розбираємо налаштування ICE/TURN, сигналізацію та типові помилки, які з'їдають тижні розробки. WebRTC — відкритий стандарт P2P-комунікації, і його вибір замість Twilio/Vonage дає більший контроль та знижує операційні витрати на 50–70% при масштабуванні, але вимагає самостійної реалізації сигналізації, управління ICE та розгортання TURN/STUN серверів. Наприклад, при 10 000 хвилинах на місяць економія складає близько $300 на користь WebRTC. Зв'яжіться з нами для консультації щодо вашого проекту.

Як WebRTC вирішує проблему з'єднання за NAT?

Встановлення з'єднання — багатокроковий процес через ICE (Interactive Connectivity Establishment). На кожному етапі можливі збої, якщо не врахувати нюанси:

  1. Викликаючий створює PeerConnection, генерує offer (SDP — Session Description Protocol)
  2. offer передається співрозмовнику через сигнальний канал (WebSocket)
  3. Співрозмовник створює PeerConnection, застосовує offer, генерує answer
  4. answer повертається через сигнальний канал
  5. Обидва клієнти обмінюються ICE candidates — потенційними мережевими шляхами
  6. ICE агент вибирає найкращий шлях і встановлює P2P з'єднання

ICE candidates бувають трьох типів: host (локальний IP), srflx (через STUN — публічний IP), relay (через TURN). Пряме P2P (host/srflx) працює у 70–80% випадків. У корпоративних мережах за симетричним NAT потрібен relay через TURN. Ми використовуємо власні TURN-сервери на coturn, що дає економію до 60% порівняно з готовими TURN-сервісами при навантаженні від 1000 одночасних дзвінків.

Що таке TURN-сервер і чому він критичний?

Без TURN-сервера WebRTC не працює за корпоративними firewall та симетричним NAT. Це ~20–30% реальних користувачів. Розгорнути 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 

Використання публічного STUN від Google (stun.l.google.com) безкоштовне, але не надає TURN. Потрібен власний або платний сервіс (Twilio Network Traversal Service, Xirsys). Ми рекомендуємо coturn — він витримує 10 000 одночасних сесій на одному сервері з 4 ядрами та 8 ГБ ОЗУ. WebRTC P2P дзвінки працюють у 3-5 разів швидше, ніж через хмарні API Twilio, при прямому з'єднанні.

Як реалізувати сигнальний протокол

WebRTC не визначає сигналізацію — це відповідальність розробника. Мінімум: WebSocket-канал для передачі SDP offer/answer та ICE candidates.

// Відправка offer через 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) } 

Стан сесії: new → connecting → connected → disconnected → failed. Обробка failed — спроба restartIce() або перевстановлення з'єднання. Без обробника переходів користувач бачить завислий дзвінок без зворотного зв'язку.

Нативна реалізація на Android та iOS

Android. Google підтримує WebRTC Android SDK — io.getstream:stream-webrtc-android або напряму бінарники з webrtc.org.

// Ініціалізація PeerConnectionFactory.initialize( PeerConnectionFactory.InitializationOptions.builder(context) .createInitializationOptions() ) val factory = PeerConnectionFactory.builder() .setAudioDeviceModule(JavaAudioDeviceModule.builder(context).createAudioDeviceModule()) .createPeerConnectionFactory() // ICE конфігурація 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) // Аудіо трек val audioSource = factory.createAudioSource(MediaConstraints()) val audioTrack = factory.createAudioTrack("audio0", audioSource) val localStream = factory.createLocalMediaStream("stream0") localStream.addTrack(audioTrack) peerConnection?.addStream(localStream) 

Відео додається аналогічно через VideoCapturerCamera2Capturer для нативної камери.

iOS. Використовуємо той самий Google WebRTC SDK через CocoaPods (pod 'GoogleWebRTC') або 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 обов'язкова для iOS — без неї дзвінок не отримає пріоритет аудіосесії. Детальніше — у статті про VoIP-дзвінки. Ми завжди додаємо підтримку CXProvider для коректного відображення вхідного виклику. Замовте аудит вашого поточного WebRTC-рішення — це займе 1-2 дні та дасть план дій.

Як забезпечити якість звуку

WebRTC включає кодек Opus, ехоподавлення (AEC), шумозаглушення (NS) та автоматичне регулювання посилення (AGC) за замовчуванням. Для моніторингу якості в реальному часі — 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 мс та loss > 5% — поріг помітного погіршення якості голосу. Ми налаштовуємо адаптивну буферизацію та джиттер-буфер для компенсації втрат.

Flutter

flutter_webrtc пакет обгортає нативні WebRTC SDK. API схожий з нативним, але з додатковим прошарком. Production-досвід: пакет працює стабільно, але оновлюється із затримкою відносно нативних SDK — при критичних уразливостях у WebRTC чекати оновлення пакета іноді доводиться кілька тижнів. Тому для критичних проектів ми рекомендуємо нативну реалізацію.

Порівняння WebRTC та готових API
Параметр WebRTC Twilio/Vonage
Контроль над інфраструктурою Повний Обмежений
Вартість при 10 000 хвилин/міс ~$200 (сервер) $500+
Затримка (P2P vs relay) <100 мс (P2P) 150-300 мс
Складність інтеграції Висока Середня
Прив'язка до вендору Немає Так

Що входить у нашу роботу та терміни

  1. Аудит поточного додатку та вибір стеку (Android/iOS/Flutter)
  2. Розгортання TURN/STUN інфраструктури (coturn) з моніторингом
  3. Розробка сигнального сервера (WebSocket, можлива інтеграція з Firebase)
  4. Інтеграція WebRTC SDK з обробкою станів з'єднання
  5. Підключення CallKit (iOS) та ConnectionService (Android)
  6. Налаштування якості: джиттер-буфер, AGC, моніторинг Stats
  7. Навантажувальне тестування: симуляція 1000+ одночасних дзвінків
  8. Документація та передача знань команді замовника

Орієнтовно 3–6 тижнів на інтеграцію аудіо/відеодзвінків з урахуванням інфраструктури та інтеграції з системними дзвінковими API. Вартість розраховується індивідуально після аналізу поточного стеку. Наша команда має 7 років досвіду, виконала 50+ проектів з WebRTC, працює на ринку з 2017 року.

Типові помилки при інтеграції WebRTC

  • Неправильний вибір ICE-серверів: лише STUN без TURN → 20-30% користувачів без дзвінка
  • Відсутність обробки disconnected та failed → завислі виклики без повідомлення
  • Невірна SDP семантика (plan B замість unified plan) → проблеми в Safari/Edge
  • Ігнорування Codec negotiation → конфлікти при Priority codec
  • Відсутність CallKit/ConnectionService → дзвінок без повідомлення у згорнутому додатку
  • Моніторинг Stats не налаштований → неможливо відлагодити якість

Отримайте консультацію: зв'яжіться з нами, щоб обговорити деталі вашого проекту. Ми допоможемо обрати оптимальне рішення та уникнути типових помилок.