Софтфон с технологией WebRTC
В статье мы рассмотрим пример сборки собственного софтфона использующего технологию WebRTC на базе JS библиотеки jssip. Все инструкции тестировались на следующем оборудовании: CentOS Linux release 7.5.1804 Asterisk 13.22.0 Apache/2.4.6 Используемые сторонние библиотеки: Bootstrap 4.5.0 JQuery 3.5.1 JSSIP 3.5.1 SweetAlert 2.1.2 Easytimer FontAwesome 5.13.0 Сразу стоит сказать, что WebRTC работает совместно с другими протоколами и по […]
В статье мы рассмотрим пример сборки собственного софтфона использующего технологию WebRTC на базе JS библиотеки jssip.
Все инструкции тестировались на следующем оборудовании:
- CentOS Linux release 7.5.1804
- Asterisk 13.22.0
- Apache/2.4.6
Используемые сторонние библиотеки:
- Bootstrap 4.5.0
- JQuery 3.5.1
- JSSIP 3.5.1
- SweetAlert 2.1.2
- Easytimer
- FontAwesome 5.13.0
Сразу стоит сказать, что WebRTC работает совместно с другими протоколами и по сути является надстройкой. Как следствие невозможны соединения вида peer-to-peer. Из положения помогают выходить промежуточные шлюзы, например FreeSwitch или, как в нашем случае, Asterisk.
Допустим, вы являетесь счастливым обладателем программной АТС на базе дистрибутива FreePBX. Для работы с WebRTC проведём следующие подготовительные работы.
- Настроим дополнительный web-сервер, который будет принимать соединения на порт 8089
Для этого открываем интерфейс администрирования FreePBX и переходим на вкладку Settings->Advanced settings. Здесь отмечаем всё как показано ниже:
После этого ниже отобразятся новые настройки. Заполняем поля, как на примере:
Отвлечёмся и добавим на АТС наш SSL-сертификат. Сделать это можно перейдя по ссылке:
Здесь выбираем загрузку сертификата:
В появившейся форме даём своё название сертификату и описание. После чего в назначенные поля вносим содержимое сертификата и его приватного ключа.
Сохраняем и применяем изменения. Так же не забываем отметить использование нашего добавленного сертификата в качестве значения по-умолчанию.
Теперь нам нужно вернуться на вкладку с расширенными настройками Settings->Advanced settings и указать абсолютный путь к файлам ключа и сертификата:
Разрешим использование TLS на основании того же сертификата. Переходим по ссылке: Settings->Asterisk SIP settings-> TLS/SSL/SRTP Settings и указываем созданный ранее сертификат.
Теперь в качестве эксперимента можно прописать на сервере и удалённой машине, с которой осуществляется доступ для настройки в файлах hosts доменное имя и попытаться по нему обратиться. Для windows это:
Для Centos и, соответственно, нашего Asterisk:
После чего пробуем подключиться уже через доменное имя и проверить доверенность сертификата.
Последние действия, которые нам предстоит провести на АТС это несколько скорректировать настройки внутреннего номера, а именно:
- Отмечаем все пункты, как показано ниже
2. Добавляем в транспортные протоколы поддержку WSS
3. И обозначаем реквизиты для DTLS
На этом настройки со стороны сервера закончены и можно переходить к инструкциям по самому софтфону. Останавливаться на простых вещах вроде вёрстки и дизайна не будем, заметим лишь что достаточно будет двух форм:
Превая должна содержать типичные поля для регистрации пира на внутренний номер asterisk.
Вторая непосредственно служащая рабочим интерфейсом:
Теперь же заглянем под капот. Скрыто от глаз наличие на этой форме трёх элементов тэга <audio>.
- Служит для проигрывания сигналов, такие как гудки, рингтон звонка и пр.
- Проигрывает голосовой поток вашего собеседника
- Используется при поддержке видеосвязи, поэтому опустим пояснения (muted)
Разберём основные фрагменты js-скрипта, который осуществляет взаимодействие с библиотекой jssip.
Объявляем глобальные переменные для хранения ссылок на объекты сессии и устройства:
let phone;
let session;
Таким же образом сразу получаем ссылки на элементы воспроизведения.
let localDevice = $("#localVoice");
let localDetail = localDevice[0];
let remoteDevice = $("#remoteVoice");
let remoteDetail = remoteDevice[0];
let soundDevice = $("#songs");
let soundDetail = soundDevice[0];
Зададим основные параметры звонка и ответа:
let callOptions = {
pcConfig: {
hackStripTcp: true,
iceServers: []
},
mediaConstraints: {
audio: true,
video: false
},
rtcOfferConstraints: {
offerToReceiveAudio: true,
offerToReceiveVideo: false
}
}
Здесь мы сообщаем об индивидуальной поддержке аудио и запрете передачи видео. Пояснения к параметрам можно найти на сайте разработчика библиотеки по этому адресу.
Так же одними из важных настроек являются параметры передачи DTMF.
let DTMFOptions = {
duration: 100,
interToneGap: 500,
transportType: "RFC2833"
}
Далее нам нужно добавить функцию получения и присвоения голосового потока в элементы аудио.
function streamReroute() {
session.connection.addEventListener("addstream", function(e) {
let localStream = session.connection.getLocalStreams();
if (localStream.length) localDetail.srcObject = localStream[0];
if (e.stream) remoteDetail.srcObject = (e.stream);
});
}
И последнее из дополнительных «самописных» элементов: функции проигрывания сигналов и их остановки:
function playSong(src="", loop=false) {
soundDevice.prop("loop", loop);
soundDevice.attr("src", src);
setTimeout(function() {
soundDevice.trigger("play");
}, 100);
}
function stopSong(){
soundDevice.trigger("pause");
}
Теперь функции взаимодействия с самой библиотекой. Получаем из html-формы посредством jquery значения регистрационных данных и сохраняем в переменные.
let host = $("#host").val();
let port = $("#port").val();
let user = $("#user").val();
let secret = $("#secret").val();
let peer = "sip:" + user + "@" + host;
Создаём из полученных данных экземпляр сокета, а его и ряд настроек в свою очередь используем для создания экземпляра устройства.
let socket = new JsSIP.WebSocketInterface("wss://" + host + ":" + port + "/ws");
let regOptions = {
"sockets" : [ socket ],
"uri" : peer,
"contact_uri" : peer,
"password" : secret,
"register_expires" : 180
};
// JsSIP.debug.enable("JsSIP:*");
phone = new JsSIP.UA(regOptions);
phone.start();
На этом моменте у вас уже должен быть зарегистрирован номер на устройстве. Если это не так или произошли ошибки, обратитесь в лог браузера и asterisk.
Следующее, что стоит упомянуть, это обработчики событий регистрации. Вот они:
phone.on("registered", () => {
#code here
});
phone.on("registrationFailed", (e) => {
alert(e.cause);
});
phone.on("unregistered", () => {
#code here
});
В каждом, на усмотрение разработчика, может быть добавлен собственный код. Например, было бы полезно фиксировать статус регистрации на интерфейсе. Отдельно отметим лишь событие registrationFailed для него, в примере выше, браузер выведет предупреждение с причиной сбоя.
Помимо регистрации нам ещё нужно ознакомиться с событиями сессии и их обработчиками:
phone.on("newRTCSession", (e) => {
let newSession = e.session;
if (session) session.terminate();
session = newSession;
session.on('peerconnection', function() {
// Если звонок входящий, распределяем потоки
if (session.direction === 'incoming') streamReroute();
});
session.on("progress", () => {
// Если идёт дозвон, проигрываем гудки
playSong("sounds/ringing.mp3", true);
$("#status").html("Ringing...");
});
session.on("confirmed", () => {
// Если звонок принят, останавливаем гудки
stopSong();
});
session.on("ended", (e) => {
// Если звонок завершён, проигрываем сигнал отбоя и очищаем сессию
session = null;
playSong("sounds/busy.mp3", false);
});
session.on("failed", (e) => {
// Аналогично при сбросе звонка
session = null;
playSong("sounds/busy.mp3", false);
});
if(session.direction === "incoming"){
// здесь нужно разместить код оповещения о входящем вызове
}
});
Покажем, как инициировать вызов. Для этого вызывается код:
number = $("#number").val();
if (number != "") {
session = phone.call(number, callOptions);
streamReroute();
}
Для отбоя нужно предварительно проверить наличие активной сессии после чего инициировать сброс:
if (session && (session.isEstablished() || session.isInProgress())) session.terminate();
И последнее о чём стоит упомянуть, это отмена регистрации. Для её выполнения достаточно вызвать следующий метод:
phone.stop();
Заключение: таким образом собрав всё в общий листинг, скомпоновав и украсив на свой вкус мы получаем софтфон который может работать в любом браузере и на любом устройстве. Не в последнюю очередь можно заметить, что данное приложение можно встроить в CRM-систему или статистику.
И теперь вы можете скачать и посмотреть небольшой демонстрационный фрагмент:
Остались вопросы?
Я - Виталий Шелест, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.
категории
- DECT
- Linux
- Вспомогательный софт при работе с Asterisk
- Интеграция с CRM и другими системами
- Интеграция с другими АТС
- Использование Elastix
- Использование FreePBX
- Книга
- Мониторинг и траблшутинг
- Настройка Asterisk
- Настройка IP-телефонов
- Настройка VoIP-оборудования
- Новости и Статьи
- Подключение операторов связи
- Разработка под Asterisk
- Установка Asterisk
VoIP оборудование
ближайшие курсы
Новые статьи
10 доводов в пользу Asterisk
Распространяется бесплатно.
Asterisk – программное обеспечение с открытым исходным кодом, распространяется по лицензии GPL. Следовательно, установив один раз Asterisk вам не придется дополнительно платить за новых абонентов, подключение новых транков, расширение функционала и прочие лицензии. Это приближает стоимость владения станцией к нулю.
Безопасен в использовании.
Любое программное обеспечение может стать объектом интереса злоумышленников, в том числе телефонная станция. Однако, сам Asterisk, а также операционная система, на которой он работает, дают множество инструментов защиты от любых атак. При грамотной настройке безопасности у злоумышленников нет никаких шансов попасть на станцию.
Надежен в эксплуатации.
Время работы серверов некоторых наших клиентов исчисляется годами. Это значит, что Asterisk работает несколько лет, ему не требуются никакие перезагрузки или принудительные отключения. А еще это говорит о том, что в районе отличная ситуация с электроэнергией, но это уже не заслуга Asterisk.
Гибкий в настройке.
Зачастую возможности Asterisk ограничивает только фантазия пользователя. Ни один конструктор шаблонов не сравнится с Asterisk по гибкости настройки. Это позволяет решать с помощью Asterisk любые бизнес задачи, даже те, в которых выбор в его пользу не кажется изначально очевидным.
Имеет огромный функционал.
Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.
Интегрируется с любыми системами.
То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.
Позволяет телефонизировать офис за считанные часы.
В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.
Отличная масштабируемость.
Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.
Повышает управляемость бизнеса.
Asterisk дает не просто набор полезных функций, он повышает управляемость организации, качества и комфортности управления, а также увеличивает прозрачность бизнеса для руководства. Достичь этого можно, например, за счет автоматизации отчетов, подключения бота в Telegram, санкционированного доступа к станции из любой точки мира.
Снижает расходы на связь.
Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.