Після інтеграції 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 не налаштований → неможливо відлагодити якість
Отримайте консультацію: зв'яжіться з нами, щоб обговорити деталі вашого проекту. Ми допоможемо обрати оптимальне рішення та уникнути типових помилок.







