Web Call Server поддерживает аудио и видеозвонки из браузера на SIP устройства, PBX серверы, SIP-GSM-шлюзы, VoIP конференции и другие устройства с поддержкой протокола SIP. Таким образом, веб-приложение в браузере может работать, как программный телефон с поддержкой протокола SIP, принимать и инициировать голосовые и видеозвонки.
Описание
Поддерживаемые платформы и браузеры
Chrome | Firefox | Safari 11 | Edge | |
---|---|---|---|---|
Windows | + | + | + | |
Mac OS | + | + | + | |
Android | + | + | ||
iOS | - | - | + |
Поддерживаемые протоколы
- WebRTC
- RTP
- SIP
Поддерживаемые кодеки
- H.264
- VP8
- G.711
- Speex
- G.729
- Opus
Поддерживаемые SIP функции
- DTMF
- Удержание звонка
- Перевод звонка
SIP функции управляются при помощи REST API.
Схема работы
1: SIP-сервер как прокси-сервер для передачи вызовов и RTP медиа
2: SIP-сервер только как сервер для передачи вызовов
- Браузер начинает звонок с помощью REST-вызова /call/startup
- WCS соединяется с SIP-сервером
- SIP-сервер соединяется с SIP-устройством, принимающим звонок
- Браузер и SIP-устройство обмениваются аудио- и видеопотоками
Последовательность выполнения операций (Call Flow)
Ниже описана последовательность вызовов при использовании примера Phone для создания звонка
1. Отправка REST-запроса /call/startup при помощи JavaScript API:
session.createCall(), call.call() code
var outCall = session.createCall({ callee: $("#callee").val(), visibleName: $("#sipLogin").val(), localVideoDisplay: localDisplay, remoteVideoDisplay: remoteDisplay, constraints: constraints, receiveAudio: true, receiveVideo: false ... }); outCall.call();
2. Установка соединения с SIP-сервером
3. Установка соединения с адресатом
4. Получение подтверждения от SIP-устройства
5. Получение подтверждения от SIP-сервера
6. Получение от сервера события, подтверждающего успешное соединение.
CallStatusEvent ESTABLISHED code
var outCall = session.createCall({ callee: $("#callee").val(), visibleName: $("#sipLogin").val(), localVideoDisplay: localDisplay, remoteVideoDisplay: remoteDisplay, constraints: constraints, receiveAudio: true, receiveVideo: false }).on(CALL_STATUS.RING, function(){ ... }).on(CALL_STATUS.ESTABLISHED, function(){ setStatus("#callStatus", CALL_STATUS.ESTABLISHED); $("#holdBtn").prop('disabled',false); onAnswerOutgoing(); }).on(CALL_STATUS.HOLD, function() { ... }).on(CALL_STATUS.FINISH, function(){ ... }).on(CALL_STATUS.FAILED, function(){ ... }); outCall.call();
7. Стороны звонка обмениваются аудио- и видеопотоками
8. Завершение звонка
call.hangup() code
function onConnected(session) { $("#connectBtn, #connectTokenBtn").text("Disconnect").off('click').click(function(){ $(this).prop('disabled', true); if (currentCall) { showOutgoing(); disableOutgoing(true); setStatus("#callStatus", ""); currentCall.hangup(); } session.disconnect(); }).prop('disabled', false); }
9. Отправка команды на SIP-сервер
10. Отправка команды на SIP-устройство
11. Получение подтверждения от SIP-устройства
12. Получение подтверждения от SIP-сервера
Исходящий звонок из браузера на SIP-устройство
1. Для тестирования используем:
- два SIP-аккаунта;
- веб-приложение Phone Video для совершения звонка;
- программный телефон для ответа на звонок.
2. Откройте веб-приложение Phone Video. Введите данные SIP-аккаунта, звонящего из браузера:
3. Запустите программный телефон, введите данные SIP-аккаунта, принимающего звонок:
4. Нажмите в браузере кнопку Connect, будет установлено соединение с сервером. Затем введите идентификатор SIP-аккаунта, принимающего звонок, и нажмите кнопку Call:
5. Примите звонок в программном телефоне, нажав кнопку ответа на звонок с использованием видео:
В отдельном окне отобразится видео, транслируемое из браузера:
6. В браузере также отобразится видео:
7. Для завершения звонка нажмите кнопку Hangup в браузере, либо кнопку завершения звонка в программном телефоне.
Прием входящего звонка с SIP-устройства в браузере
1. Для тестирования используем:
- два SIP-аккаунта;
- программный телефон для совершения звонка;
- веб-приложение Phone Video для ответа на звонок.
2. Откройте веб-приложение Phone Video. Введите данные SIP-аккаунта, принимающего звонок в браузере:
3. Запустите программный телефон, введите данные звонящего SIP-аккаунта:
4. Нажмите в браузере кнопку Connect, будет установлено соединение с сервером. В программном телефоне введите идентификатор SIP-аккаунта, принимающего звонок, и нажмите кнопку вызова:
5. Примите звонок в браузере, нажав кнопку Answer:
6. В браузере отобразится видео:
7. В отдельном окне программного телефона также отобразится видео, транслируемое из браузера:
8. Для завершения звонка нажмите кнопку Hangup в браузере, либо кнопку завершения звонка в программном телефоне
Управление камерой, микрофоном и устройствами вывода звука
Выбор и переключение устройств ввода и вывода
Как и при захвате видеопотока, при совершении звонка из браузера можно выбрать камеру, микрофон и (только в браузере Chrome) устройство вывода звука. Кроме того, устройства можно переключать во время звонка.
1. Выбор камеры, микрофона, устройства вывода звука code:
Flashphoner.getMediaDevices(null, true, MEDIA_DEVICE_KIND.ALL).then(function (list) { for (var type in list) { if (list.hasOwnProperty(type)) { list[type].forEach(function(device) { if (device.type == "mic") { ... } else if (device.type == "speaker") { ... } else if (device.type == "camera") { ... } }); } } ... }).catch(function (error) { $("#notifyFlash").text("Failed to get media devices "+error); });
2. Переключение устройства вывода звука во время звонка code:
$( "#speakerList" ).change(function() { if (currentCall) { currentCall.setAudioOutputId($(this).val()); } });
3. Переключение микрофона во время звонка code:
$("#switchMicBtn").click(function() { if (currentCall) { currentCall.switchMic().then(function(id) { $('#micList option:selected').prop('selected', false); $("#micList option[value='"+ id +"']").prop('selected', true); }).catch(function(e) { console.log("Error " + e); }); } }).prop('disabled', true);
4. Переключение камеры во время звонка code:
$("#switchCamBtn").click(function() { if (currentCall) { currentCall.switchCam().then(function(id) { $('#cameraList option:selected').prop('selected', false); $("#cameraList option[value='"+ id +"']").prop('selected', true); }).catch(function(e) { console.log("Error " + e); }); } }).prop('disabled', true);
Установка размера видео
При создании звонка, может быть указан размер исходящего видео
code:
function getConstraints() { var constraints = { ... video: { deviceId: {exact: $('#cameraList').find(":selected").val()}, width: parseInt($('#sendWidth').val()), height: parseInt($('#sendHeight').val()) } }; if (Browser.isSafariWebRTC() && Browser.isiOS() && Flashphoner.getMediaProviders()[0] === "WebRTC") { constraints.video.width = {min: parseInt($('#sendWidth').val()), max: 640}; constraints.video.height = {min: parseInt($('#sendHeight').val()), max: 480}; } return constraints; }
Совершение звонка без микрофона и камеры
В некоторых случаях, когда звонок не предполагает двухсторонней коммуникации, например, при звонке на голосовое меню, можно позвонить, не используя микрофон и камеру.
Для этого необходимо отключить таймер активности RTP настройкой в файле flashphoner.properties
rtp_activity_detecting=false
и отключить аудио и видео в настройке граничных параметров исходящего звонка в браузерах Chrome, Safari, MS Edge:
var constraints = { audio: false, video: false }; var outCall = session.createCall({ callee: $("#callee").val(), visibleName: $("#sipLogin").val(), constraints: constraints, ... })
В браузере Firefox необходимо создать пустой аудиопоток:
var constraints = { audio: false, video: false }; if(Browser.isFirefox()) { var audioContext = new AudioContext(); var emptyAudioStream = audioContext.createMediaStreamDestination().stream; constraints.customStream = emptyAudioStream; } var outCall = session.createCall({ callee: $("#callee").val(), visibleName: $("#sipLogin").val(), constraints: constraints, ... })
Отображение WebRTC-статистики
Во время SIP-звонка клиентское приложение получает WebRTC-статистику в соответствии со стандартом. Эта статистика может быть отображена в браузере, например:
Отметим, что в браузере Safari отображается только статистика аудио.
1. Отображение статистики во время звонка
call.getStats() code:
currentCall.getStats(function (stats) { if (stats && stats.outboundStream) { if (stats.outboundStream.videoStats) { $('#videoStatBytesSent').text(stats.outboundStream.videoStats.bytesSent); $('#videoStatPacketsSent').text(stats.outboundStream.videoStats.packetsSent); $('#videoStatFramesEncoded').text(stats.outboundStream.videoStats.framesEncoded); } else { ... } if (stats.outboundStream.audioStats) { $('#audioStatBytesSent').text(stats.outboundStream.audioStats.bytesSent); $('#audioStatPacketsSent').text(stats.outboundStream.audioStats.packetsSent); } else { ... } } });
Настройка используемых кодеков
WCS указывает поддерживаемые кодеки в INVITE SDP согласно следующим параметрам в файле flashphoner.properties.
1. В INVITE SDP включаются кодеки, указанные параметром codecs
, по умолчанию
codecs=opus,alaw,ulaw,g729,speex16,g722,mpeg4-generic,telephone-event,h264,vp8,flv,mpv
2. Из INVITE SDP исключаются кодеки, указанные параметром codecs_exclude_sip
, по умолчанию
codecs_exclude_sip=mpeg4-generic,flv,mpv
3. Из INVITE SDP исключаются кодеки, указанные браузером, если установлен параметр
allow_outside_codecs=false
4. Из INVITE SDP исключаются кодеки, указанные параметром stripCodecs
в клиентском приложении, например:
var outCall = session.createCall({ callee: $("#callee").val(), ... stripCodecs: "SILK,G722" ... }); outCall.call();
Передача дополнительных параметров в SDP в запросе INVITE и ответе 200 OK
При создании звонка при помощи JavaScript API могут быть определены дополнительные параметры для управления пропускной способностью канала через SDP для исходящих (в запросе INVITE)
var sdpAttributes = ["b=AS:3000","b=TIAS:2500000","b=RS:1000","b=RR:3000"]; var outCall = session.createCall({ sipSDP: sdpAttributes, ... });
и входящих звонков (в ответе 200 OK)
var sdpAttributes = ["b=AS:3000","b=TIAS:2500000","b=RS:1000","b=RR:3000"]; inCall.answer({ sipSDP: sdpAttributes, ... });
Эти параметры проставляются в SDP после connection information ("c=IN IP4 <WCS IP>") и до time description ("t=0 0"):
v=0 o=Flashphoner 0 1541068898263 IN IP4 192.168.1.5 s=Flashphoner/1.0 c=IN IP4 192.168.1.5 b=AS:3000 b=TIAS:2500000 b=RS:1000 b=RR:3000 t=0 0 m=audio
Известные проблемы
1. Невозможно совершить SIP-звонок при некорректно заданных параметрах звонка SIP Login, SIP Authentification name
Симптомы: звонок не совершается, зависает в статусе PENDING
Решение: согласно стандарту, SIP Login и SIP Authentification name не должны содержать неэкранированных пробелов, спецсимволов и не должны заключаться в угловые скобки '<>'.
Например, такое заполнение полей не соответствует стандарту
sipLogin='Ralf C12441@host.com' sipAuthenticationName='Ralf C' sipPassword='demo' sipVisibleName='null'
а такое соответствует
sipLogin='Ralf_C12441' sipAuthenticationName='Ralf_C' sipPassword='demo' sipVisibleName='Ralf C'
2. Проблемы со звуком при звонках из браузера Edge.
Симптомы:
а) исходящий звук периодически то резко приглушается, то идет нормально.
б) входящий звук слышен, только если говорить в микрофон.
Решение:
Отключить для браузера Edge использование кодеков SILK и G.722 в SIP звонках при помощи опции stripCodecs:
var outCall = session.createCall({ callee: $("#callee").val(), visibleName: $("#sipLogin").val(), localVideoDisplay: localDisplay, remoteVideoDisplay: remoteDisplay, constraints: constraints, receiveAudio: true, receiveVideo: false, stripCodecs: "SILK,G722" ... }); outCall.call();
или при помощи настройки
codecs_exclude_sip=g722,mpeg4-generic,flv,mpv
3. Не работает переключение микрофона в браузере Safari.
Симптомы: не переключается микрофон при помощи метода switchMic() WCS WebSDK.
Решение: использовать другой браузер, поскольку Safari всегда использует микрофон sound input, выбранный в настройках звука системы sound menu (для входа необходимо зажать клавишу Option (Alt) и щелкнуть по иконке звука в меню). После выбора другого микрофона в sound menu требуется перезагрузка Mac.
Если не работает микрофон Logitech USB camera (когда выбран в sound input), может помочь изменение format / sample rate в Audio MIDI Setup и перезагрузка.
4. Не устанавливается исходящий видеозвонок из браузера, если размер INVITE SDP превышает размер MTU
Симптомы: при попытке установить исходящий видеозвонок SIP-сторона возвращает 408 Request timeout, аудиозвонки при этом устанавливаются успешно
Решение: уменьшить количество кодеков в INVITE SDP таким образом, чтобы SDP укладывалось в размер пакета, определенный MTU (как правило, 1500 байт), при помощи настроек
codecs_exclude_sip=mpeg4-generic,flv,mpv,opus,ulaw,h264,g722,g729 allow_outside_codecs=false
Следует оставить только те кодеки, которые поддерживаются обеими сторонами звонка, в данном случае это VP8 и PCMA (alaw).