Как принимать SIP-звонки прямо в браузере через WebRTC

Представьте ситуацию: клиент нажимает кнопку «Позвонить» на вашем сайте, а звук приходит прямо в вкладку браузера у оператора. Никаких приложений, никаких плагинов, никаких «установите программу». Звучит как фантастика? Нет, это стандартная практика, и реализовать её проще, чем кажется. Разберёмся, как это работает и что нужно сделать.

Почему вообще не нужны плагины

Раньше для звонков в браузере ставили Flash, Java-апплеты или десктопные софтфоны. Это было неудобно: пользователь должен был что-то скачать, разрешения выдать, антивирус успокоить. Конверсия в звонок падала на каждом шаге.

WebRTC встроен в каждый современный браузер — Chrome, Firefox, Safari, Edge. Это значит, что браузер уже умеет захватывать микрофон, передавать аудио и видео по сети и подключаться к SIP-серверу. Ничего устанавливать не нужно. Пользователь заходит на страницу, нажимает кнопку — и говорит.

Как устроен «прямой вход» звонка

Схема выглядит так:

  1. Клиент звонит через веб-интерфейс (нажимает кнопку на сайте).
  2. Звонок приходит на SIP-сервер (Asterisk, FreeSWITCH, или облачная АТС).
  3. Сервер маршрутизирует вызов на веб-клиент оператора.
  4. li>Оператор в браузере видит входящий звонок и отвечает.

Ключевой момент — связка между SIP-сервером и браузером. Браузер говорит по WebRTC, а сервер по SIP. Нужен промежуточный слой, который переведёт одно на другое. Это называется WebRTC-шлюз или SIP-over-WebSocket.

Что нужно для реализации

Разложим по полочкам, из чего состоит система:

  • SIP-сервер — обрабатывает вызовы, хранит учётные записи, маршрутизирует звонки. Чаще всего это Asterisk или FreeSWITCH.
  • WebRTC-шлюз — компонент, который принимает SIP-вызовы и конвертирует их в WebRTC-сессии для браузера. Может быть частью SIP-сервера или отдельным сервисом.
  • Веб-клиент — JavaScript-приложение, которое работает в браузере оператора. Использует библиотеку SIP.js или JsSIP для подключения к серверу через WebSocket.
  • HTTPS — обязателен. Браузеры не дают доступ к микрофону без защищённого соединения.
  • Сертификат — нужен валидный SSL/TLS для вашего домена. Самоподписанный не подойдёт для продакшена.

Пошаговая настройка на примере Asterisk

Возьмём самый распространённый стек: Asterisk + SIP.js. Это не единственный вариант, но он хорошо документирован и работает стабильно.

Шаг 1. Установите и настройте Asterisk

Установите Asterisk на сервер (Linux, желательно Debian или CentOS). Убедитесь, что версия поддерживает WebRTC — это Asterisk 12 и выше, но лучше брать 16 или 18.

В файле pjsip.conf создайте endpoint с поддержкой WebRTC:

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0

[transport-ws]
type=transport
protocol=ws
bind=0.0.0.0:8089

[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0:8089
cert=/etc/asterisk/keys/your_cert.pem
privkey=/etc/asterisk/keys/your_key.pem

[operator]
type=endpoint
transport=transport-wss
context=from-internal
disallow=all
allow=ulaw
allow=opus
auth=operator-auth
aors=operator-aor
webrtc=yes

[operator-auth]
type=auth
auth_type=userpass
password=your_password
username=operator

[operator-aor]
type=aor
max_contacts=1

Обратите внимание на параметр webrtc=yes — он говорит Asterisk использовать DTLS-SRTP для шифрования, что обязательно для WebRTC.

Шаг 2. Настройте веб-клиент

Создайте HTML-страницу с JavaScript-кодом. Подключите библиотеку SIP.js:

<script src="https://cdn.jsdelivr.net/npm/sip.js@0.21.2/dist/sip-0.21.2.min.js"></script>

Инициализируйте UA (User Agent):

const userAgent = new SIP.UA({
  uri: 'sip:operator@yourdomain.com',
  transportOptions: {
    server: 'wss://yourdomain.com:8089/ws'
  },
  authorizationUser: 'operator',
  password: 'your_password',
  register: true
});

userAgent.on('invite', function(session) {
  // Входящий звонок
  showIncomingCall(session);
  
  // Можно автоматически ответить или показать кнопку
  session.on('accepted', function() {
    console.log('Звонок принят');
  });
});

Шаг 3. Обработка звонка в интерфейсе

Когда приходит входящий вызов, показываем пользователю уведомление с кнопками «Ответить» и «Отклонить»:

function showIncomingCall(session) {
  const callerId = session.remoteIdentity.displayName || session.remoteIdentity.uri.user;
  
  // Показываем модальное окно или баннер
  document.getElementById('caller-name').textContent = callerId;
  document.getElementById('incoming-call').style.display = 'block';
  
  document.getElementById('answer-btn').onclick = function() {
    session.accept({
      media: {
        constraints: { audio: true, video: false },
        render: {
          remote: document.getElementById('remote-audio')
        }
      }
    });
  };
  
  document.getElementById('reject-btn').onclick = function() {
    session.reject();
  };
}

Шаг 4. Проверьте кодеки

Браузеры лучше всего работают с Opus и G.711 (ulaw/alaw). Убедитесь, что Asterisk транскодирует звук, если внешний звонок приходит в другом кодеке (например, G.729). Транскодирование нагружает процессор, учитывайте это при расчёте мощности сервера.

Варианты реализации: что выбрать

Есть несколько путей — от полностью самостоятельной настройки до готовых облачных решений. Выбор зависит от ваших ресурсов и задач.

Подход Что это Плюсы Минусы Для кого
Свой сервер + SIP.js Вы поднимаете Asterisk и пишете веб-клиент с нуля Полный контроль, нет абонентской платы Нужен системный администратор, время на настройку Команды с техспециалистами, крупные проекты
Готовая облачная АТС с WebRTC Провайдер даёт виджет или API для звонков в браузере Быстрый запуск, не нужен сервер Ограниченная кастомизация, плата за минуты/каналы Малый бизнес, стартапы, быстрый пилот
CPaaS-платформа (Twilio, Voximplant и т.п.) API для звонков, вы строите интерфейс поверх Масштабируемость, документация, SDK Стоимость растёт с объёмом, зависимость от провайдера Продуктовые компании, сложные сценарии
Готовые JS-фреймворки (sipML5, JsSIP) Библиотеки с примерами, настраиваете под себя Быстрее чем с нуля, сообщество Документация местами устаревшая, отладка сложная Разработчики с опытом в телекоме

Типичные ошибки, которые всё ломают

Вот что чаще всего идёт не так, и как этого избежать:

  • Забыли про HTTPS. Браузер просто не даст доступ к микрофону. Проверяйте, что страница открыта по https, а не http.
  • Самоподписанный сертификат. Для теста сойдёт, но в продакшене браузер заблокирует WebSocket-соединение. Используйте Let’s Encrypt или коммерческий сертификат.
  • Неправильный транспорт. WebRTC требует WSS (WebSocket Secure), а не обычный WS. Если Asterisk слушает на ws://, а браузер пытается подключиться по wss:// — соединение не установится.
  • Файрвол блокирует порты. Убедитесь, что порт 8089 (или тот, что вы настроили) открыт для входящих соединений. Также проверьте порты для RTP (обычно 10000–20000 UDP).
  • Конфликт кодеков. Если браузер предлагает Opus, а Asterisk на стороне оператора разрешил только G.729 — звука не будет. Настройте транскодирование или разрешите оба кодека.
  • Не обработали разрыв соединения. Если пользователь закрывает вкладку, сессия должна корректно завершаться. Иначе на сервере повисают мёртвые вызовы.

Что выбрать в зависимости от ситуации

У вас интернет-магазин, нужен звонок с сайта менеджеру в браузере. Берите облачную АТС с поддержкой WebRTC-софтфона. Настройка займёт день, не нужен админ. Менеджер открывает вкладку, входит в систему — и принимает звонки.

Вы разрабатываете продукт с кол-центром в браузере. Смотрите в сторону CPaaS (Voximplant, Twilio) или стройте своё решение на FreeSWITCH + JsSIP. Потребуется разработчик, зато интерфейс будет именно таким, как вам нужно.

У вас уже стоит Asterisk, хотите добавить приём звонков в браузере. Настройте PJSIP с транспортом WSS и напишите простую страницу на SIP.js. Это займёт пару дней у специалиста, но не потребует перестройки всей телефонии.

Нужно протестировать идею быстро и без вложений. Поднимите Asterisk на VPS за 500 рублей в месяц, настройте с документацией из этой статьи, используйте SIP.js с CDN. За выходные собираете работающий прототип.

Безопасность — не думайте об этом потом

Когда вы открываете доступ к SIP из браузера, вы открываете его всему интернету. Вот что нужно сделать обязательно:

  • Ограничьте доступ к WebSocket-порту по IP, если операторы сидят с фиксированных адресов.
  • Используйте сложные пароли для SIP-аккаунтов. Брутфорс — реальная угроза.
  • Включите fail2ban на сервере, чтобы блокировать подозрительные запросы.
  • Не храните пароли в открытом виде в JavaScript. Лучше используйте серверную авторизацию и выдавайте токены.
  • Обновляйте Asterisk и библиотеки. Уязвимости в WebRTC-стеке находят регулярно.

Как проверить, что всё работает

После настройки проведите тестовый звонок:

  1. Откройте веб-клиент в браузере оператора. Должен быть статус «зарегистрирован».
  2. Совершите звонок на внутренний номер оператора с внешнего телефона или другого SIP-клиента.
  3. В браузере должно прийти уведомление о входящем звонке.
  4. Ответьте — проверьте, что звук идёт в обе стороны.
  5. Проверьте в разных браузерах: Chrome, Firefox, Safari. В Safari бывают нюансы с Opus.
  6. Проверьте мобильный браузер на iOS. WebRTC там работает, но есть ограничения на автовоспроизведение аудио.

Если звук идёт с задержкой или эхом — проверьте настройки эхоподавления в Asterisk (echocancel=yes в параметрах endpoint) и в браузере (SIP.js поддерживает эхоподавление на уровне Web Audio API).

Итог: с чего начать прямо сейчас

Если вы дочитали до сюда и хотите попробовать, вот план на ближайшие дни:

  • Определитесь с подходом: своими силами или через провайдера.
  • Если своими силами — поднимите тестовый сервер с Asterisk 18.
  • Настройте PJSIP с WSS-транспортом и валидным сертификатом.
  • Скачайте пример из репозитория SIP.js и запустите его на своём сервере.
  • Сделайте тестовый звонок. Если заработало — оборачивайте в свой интерфейс.

Технология проверена и работает. Главное — не игнорировать HTTPS, правильно настроить транспорт и не забыть про кодеки. Остальное — дело техники. У вас получится.

Virtual-Sim.ru