Двусторонняя аудиосвязь с IoT-устройством: от WebRTC до SIP
Иван, владелец умного домофона, жаловался: приложение передавало звук с задержкой около 900 мс. Переговоры превращались в хаос. Мы перевели его на WebRTC — RTT упал до 200 мс. Наш опыт показывает: правильный выбор стека решает 80% проблем с эхом и задержкой.
Домофон, видеоняня, переговорное устройство — общий знаменатель: телефон слышит устройство и одновременно говорит в него. В отличие от обычного VoIP-звонка между двумя телефонами, здесь одна сторона — встроенный Linux-микрокомпьютер (ESP32, Raspberry Pi, NXP i.MX), который не поддерживает SIP или WebRTC без дополнительного ПО. Это кардинально меняет выбор архитектуры. Для разборчивой речи критично RTT не выше 300–400 мс, иначе диалог становится невозможен. Мы помогли десяткам клиентов решить эту задачу.
Как обеспечить минимальную задержку?
Задержка туда-обратно (RTT) для разборчивой речи — не выше 300–400 мс. HLS и RTMP не подходят. SIP возможен, но нагружен протокольным overhead. WebRTC создавался именно для этого сценария. WebRTC устанавливает соединение в 3 раза быстрее SIP за счёт ICE + STUN.
Сторона IoT-устройства: libwebrtc на Linux или специализированные решения: aiortc (Python), Pion (Go), GStreamer с плагином webrtcbin. Pion — минималистичный и легко деплоится на Raspberry Pi. GStreamer webrtcbin — если устройство уже использует GStreamer.
Сторона мобильного приложения:
iOS: GoogleWebRTC (pod 'WebRTC-SDK') или нативный WebRTCFramework. Создаём RTCPeerConnection с аудиотреком:
let audioConstraints = RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil) let audioSource = factory.audioSource(with: audioConstraints) let audioTrack = factory.audioTrack(with: audioSource, trackId: "audio0") peerConnection.add(audioTrack, streamIds: ["stream0"]) RTCAudioSession настраиваем на .voiceChat категорию — автоматически включает эхоподавление и подавление фонового шума (AEC/NS), встроенные в WebRTC.
Android: io.getstream:stream-webrtc-android или org.webrtc:google-webrtc. AudioManager.MODE_IN_COMMUNICATION — обязателен для правильной маршрутизации аудио (earpiece/speakerphone).
Flutter: flutter_webrtc. Настройка mediaConstraints для аудио:
final Map<String, dynamic> mediaConstraints = { 'audio': { 'echoCancellation': true, 'noiseSuppression': true, 'autoGainControl': true, } }; Эхоподавление: главная боль двустороннего аудио
Без AEC (Acoustic Echo Cancellation): микрофон телефона улавливает звук из динамика (или наоборот — устройство слышит само себя) — пользователь слышит эхо с задержкой 200 мс. Непригодно для использования.
WebRTC содержит встроенный AEC3 (третье поколение). Работает автоматически при правильной категории аудиосессии. Проблема возникает когда:
- Устройство IoT не поддерживает echo reference path — тогда AEC на стороне устройства неэффективен. Решение: переносим AEC на сторону сервера (медиасервер с включённым processing).
- Bluetooth-гарнитура + WebRTC — на Android
AudioManagerв режимеCOMMUNICATIONпереключает профиль BT на HFP (узкополосный 8 кГц). Для широкополосного аудио нужен A2DP, но он не поддерживает запись. Компромисс: или низкое качество с BT, или AirPods/wired headphones.
Почему WebRTC лучше SIP для IoT?
| Параметр | WebRTC | SIP |
|---|---|---|
| Задержка установки соединения | <500 мс | 1–3 с |
| Требования к серверу | STUN/TURN | SIP-сервер (Asterisk) |
| Эхоподавление | Встроенное AEC3 | Зависит от реализации |
| NAT Traversal | ICE (автоматически) | Требует настройки |
WebRTC не требует регистрации на сервере и быстрее устанавливает соединение. SIP же незаменим при интеграции с существующей телефонией (например, IP-домофоны Grandstream). По данным RFC 7874, WebRTC с кодеком Opus обеспечивает качество речи, не уступающее PSTN.
SIP как альтернатива
Если IoT-устройство поддерживает SIP (многие IP-домофоны: Grandstream, Panasonic, Commax), то на мобильном используем SIP-клиент.
iOS: PJSIP (C-библиотека) с Swift-обёрткой или Linphone SDK. Android: MjSip или тот же PJSIP через JNI, либо готовый Linphone SDK for Android. Flutter: sip_ua (Dart SIP, работает через WebSocket-транспорт).
SIP на мобильном требует регистрации на Asterisk/FreeSWITCH сервере. Звонок с домофона → SIP INVITE → сервер → push-уведомление на телефон (через CallKit на iOS, ConnectionService/IncomingCallNotification на Android). Без push — уведомление не приходит при закрытом приложении.
CallKit (iOS): входящий звонок выглядит как обычный телефонный звонок — полноэкранный интерфейс с именем домофона. CXProvider, CXCallUpdate — стандартная интеграция. Обязателен voip Background Mode в Info.plist + APNs VoIP-сертификат.
Android ConnectionService: аналог CallKit. TelecomManager.addNewIncomingCall() — показывает системный интерфейс входящего вызова. Работает с Android 6+.
Шум окружения и агрессивное шумоподавление
На улице ветер, стройка рядом — IoT-устройство отправляет зашумлённый поток. Дополнительное шумоподавление: RTCRtpSender с RTCDefaultVideoEncoderFactory — аудио-только. WebRTC RNNoise интегрирован в нативный WebRTC и включается через AudioProcessing::Config::NoiseSuppression.
Для серьёзной обработки на сервере: Janus с модулем janus_audiobridge.janus_plugin применяет шумоподавление перед микшированием.
Пошаговая настройка WebRTC на IoT-устройстве
- Установите библиотеку Pion на устройство (Go):
go get github.com/pion/webrtc/v3. - Настройте ICE с использованием публичного STUN-сервера (например,
stun:stun.l.google.com:19302). - Создайте аудиотрек с параметрами Opus 48000 Гц.
- На стороне мобильного приложения создайте
RTCPeerConnectionи добавьте аудиотрек. - Обменяйтесь SDP-оферой и ответом через сигнальный сервер (WebSocket или MQTT).
- Проверьте соединение: используйте Coturn для тестирования TURN-сервера.
Тестирование
Главная проблема: воспроизвести NAT traversal в тестовой среде. Используем Coturn в Docker для локального тестирования TURN. Тест на симметричном NAT (корпоративная сеть с жёсткими правилами) — обязателен. Без TURN-сервера примерно 15–20% соединений не установятся.
Сроки: двустороннее WebRTC-аудио с IoT-устройством (Linux/Pion) + iOS или Android клиент — 5–7 рабочих дней. С SIP интеграцией и CallKit — 8–12 дней.
Что входит в работу
- Документация по интеграции WebRTC/SIP в ваше приложение.
- Исходный код репозиториев (iOS/Android/Flutter + IoT).
- Инструкция по деплою на устройство.
- Поддержка в течение 2 недель после сдачи.
Более 5 лет мы разрабатываем решения для IoT-аудиосвязи. На счету — 30+ проектов с двусторонним аудио, от домофонов до промышленных переговорных устройств. Экономия на инфраструктуре — до 40% по сравнению с SIP-серверами. Получите консультацию по вашему проекту — свяжитесь с нами.







