Після інтеграції 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). На кожному етапі можливі збої, якщо не врахувати нюанси:
- Викликаючий створює
PeerConnection, генеруєoffer(SDP — Session Description Protocol) -
offerпередається співрозмовнику через сигнальний канал (WebSocket) - Співрозмовник створює
PeerConnection, застосовуєoffer, генеруєanswer -
answerповертається через сигнальний канал - Обидва клієнти обмінюються ICE candidates — потенційними мережевими шляхами
- 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) Відео додається аналогічно через VideoCapturer — Camera2Capturer для нативної камери.
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 мс |
| Складність інтеграції | Висока | Середня |
| Прив'язка до вендору | Немає | Так |
Що входить у нашу роботу та терміни
- Аудит поточного додатку та вибір стеку (Android/iOS/Flutter)
- Розгортання TURN/STUN інфраструктури (coturn) з моніторингом
- Розробка сигнального сервера (WebSocket, можлива інтеграція з Firebase)
- Інтеграція WebRTC SDK з обробкою станів з'єднання
- Підключення CallKit (iOS) та ConnectionService (Android)
- Налаштування якості: джиттер-буфер, AGC, моніторинг Stats
- Навантажувальне тестування: симуляція 1000+ одночасних дзвінків
- Документація та передача знань команді замовника
Орієнтовно 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 не налаштований → неможливо відлагодити якість
Отримайте консультацію: зв'яжіться з нами, щоб обговорити деталі вашого проекту. Ми допоможемо обрати оптимальне рішення та уникнути типових помилок.







