<!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获取到了早期媒体。
参考资料: