<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[интеграция WebRTC с CUBE (SBC)]]></title><description><![CDATA[<p dir="auto">Здравствуйте всем, кто-нибудь успешно внедрил интеграцию WebRTC с SBC/CUBE? Если да, не могли бы вы поделиться примером конфигурации и ссылками на соответствующую документацию Cisco? Спасибо.</p>
]]></description><link>https://sla247.ru/forum/topic/1444/интеграция-webrtc-с-cube-sbc</link><generator>RSS for Node</generator><lastBuildDate>Fri, 15 May 2026 07:21:34 GMT</lastBuildDate><atom:link href="https://sla247.ru/forum/topic/1444.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 18 Feb 2026 21:08:50 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:09:01 GMT]]></title><description><![CDATA[<p dir="auto">Хорошо. Я их соберу и свяжусь с вами. А пока вам нужно установить Ubuntu. Я установил Ubuntu версии 25.</p>
]]></description><link>https://sla247.ru/forum/post/9868</link><guid isPermaLink="true">https://sla247.ru/forum/post/9868</guid><dc:creator><![CDATA[collinks2]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:09:01 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:09:00 GMT]]></title><description><![CDATA[<p dir="auto">Да, и я использовал Asterisk в качестве SIP-шлюза. Есть и другие SIP-шлюзы, такие как opensips и kamailio.</p>
]]></description><link>https://sla247.ru/forum/post/9867</link><guid isPermaLink="true">https://sla247.ru/forum/post/9867</guid><dc:creator><![CDATA[collinks2]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:09:00 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:59 GMT]]></title><description><![CDATA[<p dir="auto">Насколько я знаю, Cube не поддерживает WebRTC. Во всех найденных мной источниках упоминается шлюз WebRTC-SIP, который интегрирован с SBC с помощью SIP-транка для последующего подключения к Communication Manager. ![Response Signature]</p>
<p dir="auto"><img src="/forum/uploads/files/cisco/3d2c161685abf8b6c342d1d5392b031139f68e86.png" alt="" class=" img-fluid img-markdown" /></p>
]]></description><link>https://sla247.ru/forum/post/9866</link><guid isPermaLink="true">https://sla247.ru/forum/post/9866</guid><dc:creator><![CDATA[Roger Kallberg]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:59 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:58 GMT]]></title><description><![CDATA[<p dir="auto">Не могли бы вы поделиться более подробной информацией о вашей установке и конфигурациях? ![Response Signature]</p>
<p dir="auto"><img src="/forum/uploads/files/cisco/b65c9419769e5ae5fae7d123edff4f7e9e611e7f.png" alt="" class=" img-fluid img-markdown" /></p>
]]></description><link>https://sla247.ru/forum/post/9865</link><guid isPermaLink="true">https://sla247.ru/forum/post/9865</guid><dc:creator><![CDATA[Nithin Eluvathingal]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:58 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:57 GMT]]></title><description><![CDATA[<p dir="auto">Я не знаю, поддерживает ли CUBE wss, но я уверен, что CUBE поддерживает sip-звонки.<br />
Asterisk и некоторые другие SIP-серверы поддерживают WSS-звонки.<br />
Поэтому вы можете установить Asterisk на Ubuntu и настроить SIP-транк для CUBE с помощью<br />
плана набора номера.<br />
Как только Asterisk получит WebRTC-звонки, предназначенные для конечной точки в CUBE, он<br />
направит эти звонки на эту конечную точку. Сообщите мне, если вы хотите<br />
установить Asterisk в качестве SIP-шлюза, чтобы я мог поделиться с вами шагами, которые я использовал.</p>
]]></description><link>https://sla247.ru/forum/post/9864</link><guid isPermaLink="true">https://sla247.ru/forum/post/9864</guid><dc:creator><![CDATA[collinks2]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:57 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:56 GMT]]></title><description><![CDATA[<p dir="auto">Вау! Поздравляю. Не могли бы вы поделиться информацией о том, как это настроено в CUBE, и ссылками на документацию по настройке?</p>
]]></description><link>https://sla247.ru/forum/post/9863</link><guid isPermaLink="true">https://sla247.ru/forum/post/9863</guid><dc:creator><![CDATA[jvcumpa11]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:56 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:55 GMT]]></title><description><![CDATA[<p dir="auto">Наконец, мне удалось интегрировать webrtc с CUCM через шлюз Asterisk SIP.</p>
]]></description><link>https://sla247.ru/forum/post/9862</link><guid isPermaLink="true">https://sla247.ru/forum/post/9862</guid><dc:creator><![CDATA[collinks2]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:55 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:54 GMT]]></title><description><![CDATA[<p dir="auto">Я хочу развернуть Webrtc, чтобы пользователи могли использовать браузер и звонить агентам uccx. Я пытался настроить его с помощью opensips в качестве шлюза Webrtc, но медиа не проходит. В результате я начал думать о CUBE, чтобы посмотреть, может ли он обрабатывать звонки Webrtc и перенаправлять их в cucm. Таким образом, пользователь будет совершать звонки webrtc в cucm через CUBE.</p>
]]></description><link>https://sla247.ru/forum/post/9861</link><guid isPermaLink="true">https://sla247.ru/forum/post/9861</guid><dc:creator><![CDATA[collinks2]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:54 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:53 GMT]]></title><description><![CDATA[<p dir="auto">Каков вариант использования? 2.12.0.0 ![Response Signature]</p>
<p dir="auto"><img src="/forum/uploads/files/cisco/b65c9419769e5ae5fae7d123edff4f7e9e611e7f.png" alt="" class=" img-fluid img-markdown" /></p>
]]></description><link>https://sla247.ru/forum/post/9860</link><guid isPermaLink="true">https://sla247.ru/forum/post/9860</guid><dc:creator><![CDATA[Nithin Eluvathingal]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:53 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:52 GMT]]></title><description><![CDATA[<p dir="auto">Здравствуйте, удалось ли вам интегрировать Webrtc с CUBE? Если да, то не могли бы вы поделиться инструкциями.</p>
]]></description><link>https://sla247.ru/forum/post/9859</link><guid isPermaLink="true">https://sla247.ru/forum/post/9859</guid><dc:creator><![CDATA[collinks2]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:52 GMT</pubDate></item><item><title><![CDATA[Reply to интеграция WebRTC с CUBE (SBC) on Wed, 18 Feb 2026 21:08:51 GMT]]></title><description><![CDATA[<p dir="auto">![cucm_asterisk_sip_trunk_status.PNG]<br />
Установка Asterisk Шаг 1: Установите зависимости<br />
sudo apt-get update<br />
sudo apt-get install -y build-essential libxml2-dev libncurses5-dev libssl-dev libjansson-dev libsqlite3-dev uuid-dev Шаг 2: Загрузите исходный код<br />
Перейдите в /usr/src и загрузите последнюю версию Asterisk 22:<br />
sudo wget<br />
<a href="/forum/uploads/files/cisco/962babdd6a4020d998c3e730330738797dd36060.gz">/forum/uploads/files/cisco/962babdd6a4020d998c3e730330738797dd36060.gz</a> cd /usr/src<br />
tar -xzvf asterisk-22-current.tar.gz Шаг 3: Скомпилируйте Asterisk<br />
sudo tar -xvzf asterisk-21-current.tar.gz<br />
cd asterisk-22*/<br />
sudo contrib/scripts/install_prereq install<br />
sudo ./configure<br />
sudo make menuselect<br />
sudo make &amp;&amp; sudo make install<br />
sudo make samples<br />
sudo make config Шаг 4:<br />
sudo systemctl start asterisk<br />
systemctl status asterisk<br />
sudo asterisk -rvvv Шаг 5: Проверьте, работает ли<br />
Asterisk Запустите Asterisk в фоновом режиме, чтобы убедиться, что он работает: sudo asterisk -vvvvvvvvgc Шаг 6: Остановите Asterisk<br />
В командной строке Asterisk остановите процесс: cli core stop now Шаг 7: Запустите Asterisk в фоновом режиме<br />
Запустите Asterisk в качестве фонового процесса: sudo asterisk Шаг 8: Подключитесь к консоли<br />
Asterisk Чтобы подключиться к запущенной консоли Asterisk:<br />
sudo asterisk -r<br />
Вы можете нажать ctrl z, чтобы выйти Шаг 9 <em><strong>Создание сертификатов</strong> sudo openssl req -nodes -newkey rsa:2048 -keyout /etc/asterisk/keys//asterisk.key -out /etc/asterisk/keys/asterisk.csr<br />
введите свое общее имя и другие данные, когда будет предложено Шаг 10:<br />
предоставление разрешения<br />
sudo chown asterisk:asterisk /etc/asterisk/keys/asterisk.crt<br />
sudo chown asterisk:asterisk /etc/asterisk/keys/asterisk.pem<br />
sudo chmod 644 /etc/asterisk/keys/asterisk.crt<br />
sudo chmod 600 /etc/asterisk/keys/asterisk.pem Шаг 11: опционально (ссылка:<br />
<a href="https://vitalpbx.com/blog/asterisk-webrtc-from-scratch/?srsltid=AfmBOoqsJzR4lmLpmihFfwLDBXxPqwiAcTjdMNz11rcrckxodCfPl4Em" rel="nofollow ugc">https://vitalpbx.com/blog/asterisk-webrtc-from-scratch/?srsltid=AfmBOoqsJzR4lmLpmihFfwLDBXxPqwiAcTjdMNz11rcrckxodCfPl4Em</a><br />
) Создайте пользователя asterisk и добавьте его в группу<br />
groupadd asterisk<br />
useradd -r -d /var/lib/asterisk -g asterisk asterisk<br />
usermod -aG audio,dialout asterisk<br />
chown asterisk. -R /etc/asterisk<br />
chown asterisk. -R /var/{lib,log,spool}/asterisk<br />
chown -R asterisk.asterisk /usr/lib64/asterisk Шаг 12: измените файл http.conf<br />
sudo nano /etc/asterisk/http.conf<br />
добавьте следующее<br />
[general]<br />
enabled=yes<br />
bindaddr=0.0.0.0<br />
bindport=8088<br />
tlsenable=yes<br />
tlsbindaddr=0.0.0.0:8089<br />
tlscertfile=/etc/asterisk/keys/asterisk.cer (замените на свой сертификат)<br />
tlsprivatekey=/etc/asterisk/keys/asterisk.key (замените на свой сертификат) Шаг 13: измените файл pjsip.conf для webrtc и cucm-trunk.<br />
Вы можете заменить cucm-trunk на cube<br />
ip</em><em>определение безопасного транспорта websocket</em>*<br />
[transport-wss]<br />
type=transport<br />
protocol=wss<br />
bind=0.0.0.0:8089<br />
cert_file=/etc/asterisk/keys/asterisk.cer<br />
priv_key_file=/etc/asterisk/keys/asterisk.key ** раздел webrtc**<br />
[webcall]<br />
type=endpoint<br />
context=default<br />
disallow=all<br />
direct_media=no<br />
allow=ulaw,alaw,gsm,h264,VP8<br />
webrtc=yes<br />
aors=webcall<br />
auth=webcall_auth ; Заставить Asterisk доверять CallerID от клиента<br />
trust_id_inbound=yes<br />
trust_id_outbound=yes<br />
send_pai=yes<br />
send_rpid=yes dtls_auto_generate_cert=yes<br />
rtp_engine=asterisk<br />
use_avpf=yes<br />
ice_support=yes<br />
force_rport=yes<br />
rewrite_contact=yes [webcall_auth]<br />
type=auth<br />
auth_type=userpass<br />
password=ваш пароль<br />
username=webcall [webcall]<br />
type=aor<br />
max_contacts=100 [CUCM-Trunk]<br />
type=endpoint<br />
transport=transport-udp ; или transport-tcp, если CUCM требует TCP<br />
context=from-external<br />
disallow=all<br />
allow=ulaw,alaw,gsm,h264,VP8<br />
aors=CUCM-Trunk<br />
outbound_auth=CUCM-Auth<br />
direct_media=no [CUCM-Trunk]<br />
type=aor<br />
contact=sip:IP:5060 ; IP-адрес CUCM или CUBE и порт SIP [CUCM-Auth]<br />
type=auth<br />
auth_type=userpass<br />
username=<br />
password= ; Должно соответствовать конфигурации SIP-транка CUCM ИЛИ CUBE Шаг 14: измените extensions.conf<br />
[default]<br />
exten =&gt; 7100,1,NoOp(Переадресация вызова на CUCM IVR)<br />
same =&gt; n,Dial(PJSIP/7100@CUCM-Trunk)<br />
same =&gt; n,Hangup<br />
шаг 15:<br />
Подключитесь к консоли<br />
Atserik sudo asterisk -r<br />
pjsip reload<br />
dialplan reload<br />
module reload http<br />
Шаг 16: проверьте, работает ли Asterik на 8089<br />
sudo ss -tulnp | grep -E '8088|8089|5060' шаг 17. Настройка клиента webrtc с помощью javascript.<br />
Измените на свои реальные параметры<br />
&lt;!DOCTYPE html&gt;</p>
<p dir="auto">&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Collnetwork Care&lt;/title&gt;<br />
&lt;script src="<br />
<a href="https://webrtc.github.io/adapter/adapter-latest.js" rel="nofollow ugc">https://webrtc.github.io/adapter/adapter-latest.js</a><br />
"&gt;&lt;/script&gt;<br />
&lt;link href="{{ url_for('static', filename='favicon.ico') }}" rel="icon" type="image/x-icon"/&gt;<br />
&lt;link href="<br />
<a href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="nofollow ugc">https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css</a><br />
" rel="stylesheet"/&gt;<br />
&lt;script src="{{ url_for('static', filename='sip.min.js') }}"&gt;&lt;/script&gt;<br />
&lt;style&gt;<br />
body {<br />
background-color: #f0f2f5;<br />
font-family: sans-serif;<br />
display: flex;<br />
flex-direction: column;<br />
align-items: center;<br />
margin: 0;<br />
padding: 20px;<br />
} .keypad {<br />
display: grid;<br />
grid-template-columns: repeat(3, 80px);<br />
gap: 15px;<br />
justify-content: center;<br />
margin-top: 20px;<br />
} .keypad button {<br />
width: 80px;<br />
height: 80px;<br />
font-size: 24px;<br />
font-weight: bold;<br />
border-radius: 50%;<br />
border: none;<br />
background-color: #007bff;<br />
color: white;<br />
cursor: pointer;<br />
transition: background-color 0.3s;<br />
} .keypad button:hover {<br />
background-color: #0056b3;<br />
} /* Наложение клавиатуры на видео<br />
<em>/#dtmfKeypad {<br />
position: absolute;<br />
bottom: 100px;<br />
left: 50%;<br />
transform: translateX(-50%);<br />
background: rgba(255, 255, 255, 0.9);<br />
padding: 20px;<br />
border-radius: 12px;<br />
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);<br />
z-index: 20;<br />
} .header {<br />
margin-bottom: 20px;<br />
} .logo {<br />
height: 50px;<br />
} .call-container {<br />
position: relative;<br />
width: 100%;<br />
max-width: 900px;<br />
background-color: #fff;<br />
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);<br />
border-radius: 8px;<br />
padding: 20px;<br />
} .main-video-wrapper {<br />
width: 100%;<br />
height: 500px;<br />
background-color: #000;<br />
border-radius: 8px;<br />
overflow: hidden;<br />
} #remoteVideo {<br />
width: 100%;<br />
height: 100%;<br />
object-fit: contain;<br />
} .local-video-wrapper {<br />
position: absolute;<br />
top: 30px;<br />
right: 30px;<br />
width: 200px;<br />
height: 150px;<br />
border: 2px solid #fff;<br />
border-radius: 8px;<br />
overflow: hidden;<br />
z-index: 10;<br />
} #localVideo {<br />
width: 100%;<br />
height: 100%;<br />
object-fit: cover;<br />
} .controls-container {<br />
display: flex;<br />
justify-content: center;<br />
margin-top: 20px;<br />
gap: 15px;<br />
} .controls-container button {<br />
background-color: #555;<br />
color: #fff;<br />
border: none;<br />
border-radius: 50%;<br />
width: 50px;<br />
height: 50px;<br />
cursor: pointer;<br />
font-size: 20px;<br />
transition: background-color 0.3s;<br />
} .controls-container button:hover {<br />
background-color: #777;<br />
} .call-btn {<br />
background-color: #28a745 !important;<br />
} .call-btn:hover {<br />
background-color: #218838 !important;<br />
} .hangup-btn {<br />
background-color: #dc3545 !important;<br />
} .hangup-btn:hover {<br />
background-color: #c82333 !important;<br />
} .welcome-message {<br />
height: 500px;<br />
display: flex;<br />
flex-direction: column;<br />
justify-content: center;<br />
align-items: center;<br />
text-align: center;<br />
background-color: #f8f9fa;<br />
color: #495057;<br />
border-radius: 8px;<br />
padding: 20px;<br />
}<br />
&lt;/style&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div class="header"&gt;<br />
&lt;img alt="Логотип Collnetwork" class="logo" src="{{ url_for('static', filename='logo.png') }}"/&gt;<br />
&lt;/div&gt; &lt;div class="call-container"&gt;<br />
&lt;div class="welcome-message" id="welcomeMessage"&gt;<br />
&lt;h2&gt;Добро пожаловать в Collnetwork Care!&lt;/h2&gt;<br />
&lt;p&gt;Введите свои данные, чтобы начать видеозвонок с нашим представителем.&lt;/p&gt; &lt;form id="callForm" style="margin-top: 20px;"&gt;<br />
&lt;div style="margin-bottom: 10px;"&gt;<br />
&lt;label for="callerName"&gt;Ваше имя:&lt;/label&gt;<br />
&lt;input id="callerName" name="callerName" placeholder="например, Джейн Доу" required="" type="text"/&gt;<br />
&lt;/div&gt;<br />
&lt;div style="margin-bottom: 20px;"&gt;<br />
&lt;label for="callerPhone"&gt;Номер телефона:&lt;/label&gt;<br />
&lt;input id="callerPhone" name="callerPhone" placeholder="например, +15551234567" required="" type="tel"/&gt;<br />
&lt;/div&gt;<br />
&lt;/form&gt; &lt;button class="call-btn" id="callButton"&gt;<br />
&lt;i class="fas fa-phone"&gt;&lt;/i&gt; Начать звонок<br />
&lt;/button&gt;<br />
&lt;/div&gt; &lt;div class="main-video-wrapper" style="display:none;"&gt;<br />
&lt;video autoplay="" id="remoteVideo" playsinline=""&gt;&lt;/video&gt;<br />
&lt;/div&gt;<br />
&lt;div class="local-video-wrapper" style="display:none;"&gt;<br />
&lt;video autoplay="" id="localVideo" muted="" playsinline=""&gt;&lt;/video&gt;<br />
&lt;/div&gt; &lt;div class="controls-container"&gt;<br />
&lt;button class="hangup-btn" id="hangupButton" style="display:none;"&gt;<br />
&lt;i class="fas fa-phone-slash"&gt;&lt;/i&gt;<br />
&lt;/button&gt;<br />
&lt;button id="muteButton" style="display:none;" title="Отключить/включить звук"&gt;<br />
&lt;i class="fas fa-microphone"&gt;&lt;/i&gt;<br />
&lt;/button&gt;<br />
&lt;button id="videoButton" style="display:none;" title="Видео вкл./выкл."&gt;<br />
&lt;i class="fas fa-video"&gt;&lt;/i&gt;<br />
&lt;/button&gt;<br />
&lt;button id="screenShareButton" style="display:none;" title="Поделиться экраном"&gt;<br />
&lt;i class="fas fa-desktop"&gt;&lt;/i&gt;<br />
&lt;/button&gt;<br />
&lt;button id="dtmfButton" style="display:none;" title="Клавиатура"&gt;<br />
&lt;i class="fas fa-th"&gt;&lt;/i&gt;<br />
&lt;/button&gt;<br />
&lt;/div&gt; &lt;div id="dtmfKeypad" style="display:none;"&gt;<br />
&lt;div class="keypad"&gt;<br />
&lt;button class="dtmf" data-digit="1"&gt;1&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="2"&gt;2&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="3"&gt;3&lt;/button&gt; &lt;button class="dtmf" data-digit="4"&gt;4&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="5"&gt;5&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="6"&gt;6&lt;/button&gt; &lt;button class="dtmf" data-digit="7"&gt;7&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="8"&gt;8&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="9"&gt;9&lt;/button&gt; &lt;button class="dtmf" data-digit="</em>"&gt;*&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="0"&gt;0&lt;/button&gt;<br />
&lt;button class="dtmf" data-digit="#"&gt;#&lt;/button&gt;<br />
&lt;/div&gt;<br />
&lt;/div&gt; &lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;script&gt;<br />
let userAgent;<br />
let registerer;<br />
let session;<br />
let localStream;<br />
let uaReady = false;<br />
let screenSharing = false; // Переключить вызов<br />
window.toggleCall = async function toggleCall {<br />
if (session) {<br />
session.dispose;<br />
session = null;<br />
resetUI;<br />
return;<br />
} const callerName = document.getElementById('callerName').value || 'WebRTC Client';<br />
const callerPhone = document.getElementById('callerPhone').value || 'anonymous';<br />
const combinedDisplayName = <code>${callerName} (${callerPhone})</code>; if (!userAgent || userAgent.isTerminated) {<br />
userAgent = new SIP.UserAgent({<br />
uri: SIP.UserAgent.makeURI(<code>sip:webcall@172.16.48.3</code>),<br />
transportOptions: { server: 'wss://172.16.48.3:8089/ws', traceSip: true },<br />
displayName: combinedDisplayName,<br />
authorizationUsername: 'webcall',<br />
authorizationPassword: 'your password as you defined in pjsip'<br />
}); userAgent.delegate = {<br />
onTransportError: =&gt; {<br />
console.warn('WebSocket закрыт неожиданно');<br />
alert('Соединение WebSocket закрыто. Обновите страницу.');<br />
},<br />
onInvite: (invitation) =&gt; {<br />
handleSession(invitation);<br />
invitation.accept;<br />
}<br />
}; try {<br />
await userAgent.start;<br />
registerer = new SIP.Registerer(userAgent);<br />
await registerer.register;<br />
console.log('SIP UA registered successfully');<br />
uaReady = true;<br />
} catch (err) {<br />
console.error('Failed to connect/register', err);<br />
alert('Failed to connect/register to SIP server');<br />
return;<br />
}<br />
} const target = SIP.UserAgent.makeURI('sip:0000@cucm ip');<br />
if (!target) {<br />
alert('Неверный SIP URI для target');<br />
return;<br />
} const inviter = new SIP.Inviter(userAgent, target, {<br />
sessionDescriptionHandlerOptions: {<br />
constraints: { audio: true, video: true }<br />
}<br />
}); try {<br />
await inviter.invite;<br />
handleSession(inviter); // Обновление пользовательского<br />
интерфейса document.getElementById('welcomeMessage').style.display = 'none';<br />
document.querySelector('.main-video-wrapper').style.display = 'block';<br />
document.querySelector('.local-video-wrapper').style.display = 'block';<br />
document.getElementById('callButton').style.display = 'none';<br />
document.getElementById('hangupButton').style.display = 'inline-block';<br />
document.getElementById('muteButton').style.display = 'inline-block';<br />
document.getElementById('videoButton').style.display = 'inline-block';<br />
document.getElementById('screenShareButton').style.display = 'inline-block';<br />
document.getElementById('dtmfButton').style.display = 'inline-block';<br />
} catch (e) {<br />
console.error('Failed to make call', e);<br />
alert('Failed to make call');<br />
}<br />
}; document.addEventListener('DOMContentLoaded', async =&gt; {<br />
await startLocalVideo; document.getElementById('callButton').addEventListener('click', (e) =&gt; {<br />
e.preventDefault;<br />
const form = document.getElementById('callForm');<br />
if (!form.checkValidity) {<br />
form.reportValidity;<br />
return;<br />
}<br />
window.toggleCall;<br />
}); document.getElementById('hangupButton').addEventListener('click', =&gt; window.toggleCall);<br />
document.getElementById('screenShareButton').addEventListener('click', toggleScreenShare);<br />
document.getElementById('muteButton').addEventListener('click', toggleMute);<br />
document.getElementById('videoButton').addEventListener('click', toggleVideo);<br />
document.getElementById('dtmfButton').addEventListener('click', toggleDTMFKeypad); document.querySelectorAll('.dtmf').forEach(button =&gt; {<br />
button.addEventListener('click', function {<br />
sendDTMF(this.getAttribute('data-digit'));<br />
});<br />
}); window.addEventListener('beforeunload', =&gt; {<br />
if (userAgent) userAgent.stop.catch(=&gt;{});<br />
});<br />
}); async function startLocalVideo {<br />
try {<br />
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });<br />
localStream = stream;<br />
const localVideo = document.getElementById('localVideo');<br />
if (localVideo) localVideo.srcObject = stream;<br />
} catch (error) {<br />
console.error("Ошибка доступа к мультимедийным устройствам:", error);<br />
alert("Невозможно получить доступ к вашей камере и микрофону.");<br />
}<br />
} function handleSession(newSession) {<br />
session = newSession; session.stateChange.addListener((st) =&gt; {<br />
if (st === SIP.SessionState.Terminated) {<br />
session = null;<br />
resetUI;<br />
}<br />
}); session.sessionDescriptionHandler.peerConnection.ontrack = (ev) =&gt; {<br />
const remoteVideo = document.getElementById('remoteVideo');<br />
if (remoteVideo.srcObject !== ev.streams[0]) {<br />
remoteVideo.srcObject = ev.streams[0];<br />
}<br />
}; localStream.getTracks.forEach((t) =&gt;<br />
session.sessionDescriptionHandler.peerConnection.addTrack(t, localStream)<br />
);<br />
} function resetUI {<br />
// Сбросить интерфейс пользователя в состояние<br />
приветствия document.getElementById('welcomeMessage').style.display = 'flex';<br />
document.querySelector('.main-video-wrapper').style.display = 'none';<br />
document.querySelector('.local-video-wrapper').style.display = 'none';<br />
document.getElementById('callButton').style.display = 'inline-block';<br />
document.getElementById('hangupButton').style.display = 'none';<br />
document.getElementById('muteButton').style.display = 'none';<br />
document.getElementById('videoButton').style.display = 'none';<br />
document.getElementById('screenShareButton').style.display = 'none';<br />
document.getElementById('dtmfButton').style.display = 'none';<br />
document.getElementById('dtmfKeypad').style.display = 'none'; document.getElementById('remoteVideo').srcObject = null;<br />
document.getElementById('callButton').textContent = 'Call'; // Повторно включить ввод данных в<br />
форму document.getElementById('callerName').disabled = false;<br />
document.getElementById('callerPhone').disabled = false;<br />
} function toggleMute {<br />
if (!session) return;<br />
const sender = session.sessionDescriptionHandler.peerConnection.getSenders.find(s =&gt; s.track &amp;&amp; s.track.kind === 'audio');<br />
if (!sender) return;<br />
sender.track.enabled = !sender.track.enabled;<br />
const icon = document.querySelector('#muteButton i');<br />
if (sender.track.enabled) {<br />
icon.classList.remove('fa-microphone-slash');<br />
icon.classList.add('fa-microphone');<br />
} else {<br />
icon.classList.remove('fa-microphone');<br />
icon.classList.add('fa-microphone-slash');<br />
}<br />
} function toggleVideo {<br />
if (!session) return;<br />
const sender = session.sessionDescriptionHandler.peerConnection.getSenders.find(s =&gt; s.track &amp;&amp; s.track.kind === 'video');<br />
if (!sender) return;<br />
sender.track.enabled = !sender.track.enabled;<br />
const icon = document.querySelector('#videoButton i');<br />
const localEl = document.getElementById('localVideo');<br />
if (sender.track.enabled) {<br />
icon.classList.remove('fa-video-slash');<br />
icon.classList.add('fa-video');<br />
localEl.style.display = 'block';<br />
} else {<br />
icon.classList.remove('fa-video');<br />
icon.classList.add('fa-video-slash');<br />
localEl.style.display = 'none';<br />
}<br />
} async function toggleScreenShare {<br />
if (!session) return;<br />
if (screenSharing) {<br />
const camTrack = localStream.getVideoTracks[0];<br />
const sender = session.sessionDescriptionHandler.peerConnection.getSenders.find(s =&gt; s.track &amp;&amp; s.track.kind === 'video');<br />
if (sender &amp;&amp; camTrack) await sender.replaceTrack(camTrack);<br />
screenSharing = false;<br />
document.querySelector('#screenShareButton i').classList.remove('fa-compress');<br />
document.querySelector('#screenShareButton i').classList.add('fa-desktop');<br />
return;<br />
}<br />
try {<br />
const screenStream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });<br />
const screenTrack = screenStream.getVideoTracks[0];<br />
const sender = session.sessionDescriptionHandler.peerConnection.getSenders.find(s =&gt; s.track &amp;&amp; s.track.kind === 'video');<br />
if (sender &amp;&amp; screenTrack) await sender.replaceTrack(screenTrack);<br />
screenSharing = true;<br />
document.querySelector('#screenShareButton i').classList.remove('fa-desktop');<br />
document.querySelector('#screenShareButton i').classList.add('fa-compress');<br />
} catch (e) {<br />
console.error('Screen share failed', e);<br />
alert('Failed to start screen sharing.');<br />
}<br />
} function toggleDTMFKeypad {<br />
const keypad = document.getElementById('dtmfKeypad');<br />
if (keypad.style.display === 'none' || !keypad.style.display) {<br />
keypad.style.display = 'block';<br />
} else {<br />
keypad.style.display = 'none';<br />
}<br />
} function sendDTMF(digit) {<br />
if (session) {<br />
// Найти RTCRtpSender для аудиодорожки<br />
const audioSender = session.sessionDescriptionHandler.peerConnection<br />
.getSenders<br />
.find(sender =&gt; sender.track &amp;&amp; sender.track.kind === 'audio'); // Проверить, существует ли отправитель и имеет ли он объект<br />
DTMF-отправителя if (audioSender &amp;&amp; audioSender.dtmf) {<br />
try {<br />
// Свойство .dtmf ЯВЛЯЕТСЯ объектом<br />
RTCDTMFSender audioSender.dtmf.insertDTMF(digit, 100, 50);<br />
console.log(<code>Отправлен DTMF-тон: ${digit}</code>);<br />
} catch (error) {<br />
console.error('Ошибка при отправке DTMF-тона:', error);<br />
}<br />
} else {<br />
console.warn("RTCDTMFSender недоступен для аудиодорожки.");<br />
}<br />
} else {<br />
console.warn("Нет активной сессии для отправки DTMF.");<br />
}}<br />
&lt;/script&gt;<br />
&lt;/html&gt;<br />
шаг 18:<br />
<a href="https://asteriskip:8089/ws" rel="nofollow ugc">https://asteriskip:8089/ws</a><br />
, чтобы принять самоподписанный сертификат (это не нужно делать, если у вас есть публичный сертификат).<br />
Откройте файл html и попробуйте выполнить вызов.</p>
<p dir="auto"><img src="/forum/uploads/files/cisco/062c2d70f9bb4156ed12bc9f049bdc646c6c2c8c.png" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto"><a href="/forum/uploads/files/cisco/962babdd6a4020d998c3e730330738797dd36060.gz">http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-22-current.tar.gz</a></p>
]]></description><link>https://sla247.ru/forum/post/9858</link><guid isPermaLink="true">https://sla247.ru/forum/post/9858</guid><dc:creator><![CDATA[collinks2]]></dc:creator><pubDate>Wed, 18 Feb 2026 21:08:51 GMT</pubDate></item></channel></rss>