<!DOCTYPE html> <html> <head> <title>SIP + WebRTC + freeSWITCH</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="./assets/js/jquery-1.10.2.min.js"></script> <script src="./assets/js/sip-0.7.7.js" type="text/javascript"></script> <script src="./assets/js/discard.js?v=1"></script> </head> <body> <div id="app"> <audio id="remoteAudio"></audio> <audio id="localAudio"></audio> <button class="login" data-action="logout">登陸</button> <button class="logout" data-action="logout">登出</button> <button class="register" data-action="register">就緒</button> <button class="unregister" data-action="unregister" style="margin-right: 10px;">取消就緒</button> <button class="call" data-action="call">撥打</button> <button class="hang-up" data-action="hangup">掛斷</button> <button class="answer" data-action="answer">接聽</button> </div> </body> </html>
'use strict'; var softPhoneUA = null; var currentSession = null; const options = { wsAddress: 'xxxxx', // 即時通訊地址 wsPort: 'xxxx', // 即時通訊端口 number: 'xxxx', // 分機號 password: 'xxx', // 密碼 displayName: 'xx', // 顯示名 convrsationOptions: { media: { constraints: { audio: true, video: false }, render: { remote: document.getElementById('remoteAudio'), // local: document.getElementById('localAudio') } } } } const softPhone = { /** * 登陸軟電話 */ start() { var config = { uri: `${options.number}@${options.wsAddress}`, wsServers: `wss://${options.wsAddress}:${options.wsPort}`, authorizationUser: options.number, // 授權號 displayName: options.displayName, // 顯示名稱 password: options.password, // 登陸密碼 allowLegacyNotifications:true, autostart: true, // 自動連接 register: false, // 自動就緒 rel100: SIP.C.supported.SUPPORTED, // 該選項開啟接收早期媒體(采坑記錄) }; softPhoneUA = new SIP.UA(config); softPhone.UAEvent(softPhoneUA); // 有電話呼入 softPhoneUA.on('invite', function (session) { console.log('invite') currentSession = session; softPhone.sessionEvent(session); }) }, /** 就緒 */ register() { softPhoneUA.register({ // 注冊 register:true }); }, /** 取消就緒 */ unregister() { softPhoneUA.unregister(); }, /** * 綁定ua事件 * @param {*} ua */ UAEvent(ua) { // 開始嘗試連接 ua.on('connecting', function (args) { console.log('%c connecting', 'color: #f00'); }); // 連接完畢 ua.on('connected', function () { console.log('%c connected', 'color: #f00'); }); // 主動取消注冊或注冊后定期重新注冊失敗 ua.on('unregistered', function (response, cause) { console.log('%c unregistered', 'color: #f00'); }); // 注冊成功 ua.on('registered', function () { console.log('%c registered', 'color: #f00'); }) // websocket 連接失敗 ua.on('disconnected', function () { console.log('%c disconnected', 'color: #f00'); }) }, /** * 綁定session事件 * @param {} session */ sessionEvent(session) { session.on("rejected" , function (response, cause){ console.log('%c invite-rejected', 'color: #f00'); }); session.on("bye" , function (response, cause){ console.log('%c invite-bye', 'color: #f00'); }); session.on("accepted" , function (response, cause){ console.log('%c invite-accepted', 'color: #f00'); }); session.on("cancel" , function (response, cause){ console.log('%c invite-cancel', 'color: #f00'); }); }, /** * 撥打 */ call() { console.log('callOut') const telNumber = 'xxxx'; currentSession = softPhoneUA.invite(`${telNumber}@${options.wsAddress}`, options.convrsationOptions) currentSession.on("rejected" , function (response, cause) { console.log('%c rejected', 'color: #f00'); }); currentSession.on("bye" , function (response, cause) { // 本次通話結束 console.log('%c bye', 'color: #f00'); }); currentSession.on("accepted" , function (response, cause) { // 對方接聽 console.log('%c accepted', 'color: #f00'); }); currentSession.on("cancel" , function (response, cause) { // 取消通話 console.log('%c cancel', 'color: #f00'); }); }, /** * 掛斷 */ hangUp() { if (currentSession instanceof Object) { if (currentSession.hasAnswer) { currentSession.bye(); } else if (currentSession.isCanceled == false) { currentSession.cancel(); } else { currentSession.reject(); } } }, /** * 接聽 */ answer() { currentSession.accept(options.convrsationOptions) }, /** * 登出 */ logout() { if (softPhoneUA instanceof Object) { softPhoneUA.unregister(); // 注銷 softPhoneUA.stop({ register:true }); } }, } function addEvent() { $('.login').on('click', softPhone.start); $('.logout').on('click', softPhone.logout); $('.register').on('click', softPhone.register); $('.unregister').on('click', softPhone.unregister); $('.call').on('click', softPhone.call); $('.hang-up').on('click', softPhone.hangUp); $('.answer').on('click', softPhone.answer); } $(function() { addEvent(); })
說明: 基本以上的代碼就是一份簡略版的demo了,按照參數配置輸入即可完成登錄后撥打接聽功能。
依賴庫:
jquery-1.10.2
軟電話使用:
登陸fs服務器:
最繁瑣的就是登陸流程,登陸流程接收的參數很多,沒有一個好的demo很容易采坑,官方給出的demo都不完整。
登陸中的config配置在代碼上基本都注釋了含義,這里文字說明下登陸后返回的對象和對象所擁有的事件
UA對象:
new SIP.UA(config) 后會返回一個UA對象
主要用途和方法: 就緒軟電話、監聽軟電話連接狀態、監聽電話呼入、撥打電話、登出軟電話系統
session對象(webRTC):
當前軟電話建立一個通話時創建:UA.invite()
主要用途和方法: 接聽當前來電、掛斷當前通話、監聽當前通話狀態
以上代碼親測有效可以進行簡單撥打,更詳細的內容可以參考下
sip.js官方文檔
PS: jsSIP 和 SIP.js 是兩個插件。起先我們項目使用了jsSIP,因為他官方的文檔和demo好理解,但是后面發現一個早期媒體問題一直無法解決。最終換了sip.js獲取到了早期媒體。
參考資料: