sip.js + freeswitch 軟電話(webRTC)demo


<!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獲取到了早期媒體。
 
 
參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM