Freeswitch+Sip.js实现软电话功能

版本:
sip.js : 0.13.8
freeswitch: 1.6


freeswitch相关配置

  • 修改 acl.conf.xml(笔者之前有遇到分机呼不通的情况,后来修改了此配置)

     <list name="lan" default="allow"><node type="deny" cidr="192.168.42.0/24"/><node type="allow" cidr="192.168.42.42/32"/><!-- use cidr= if you wish to allow ip ranges to this domains acl. --><node type="allow" cidr="0.0.0.0/0"/>   <!-- 允许所有ip 此处根据自己的需要设置 -->
    </list>
  • 修改 internal.xml
    修改,如没有则添加

    <param name="apply-candidate-acl" value="lan"/>

Sip.js相关代码及说明

 <!DOCTYPE html><html><head><meta charset="utf-8"><title>sipjstest</title><link rel="stylesheet" href="css/style.css"/></head><body><div><input id="number" value="1000" type="text"/><button id="startCall">Start Call</button><button id="endCall">End Call</button><button id="transfer">transfer</button><button id="hold">hold</button><button id="unhold">unhold</button><button id="mute">mute</button><button id="unmute">unmute</button></div><br><div><input id="msg" value="你好" type="text"/><button id="sendMessage">Send Message</button><audio id="ringtone" loop src="./sounds/ringtone.wav"></audio>            <!--//来电提示音--><audio id="ringbacktone" loop src="./sounds/ringbacktone.wav"></audio>    <!--//电话呼叫后声音--><audio id="dtmfTone" src="./sounds/dtmf.wav"></audio><video id="remoteVideo" autoplay="autoplay"></video><video id="localVideo" autoplay="autoplay" muted="muted"></video><!-- DTMF --><div id="dtmf-buttons"><button onclick="sendDtmf('1');">1</button><button onclick="sendDtmf('2');">2</button><button onclick="sendDtmf('3');">3</button><button onclick="sendDtmf('4');">4</button><button onclick="sendDtmf('5');">5</button><button onclick="sendDtmf('6');">6</button><button onclick="sendDtmf('7');">7</button><button onclick="sendDtmf('8');">8</button><button onclick="sendDtmf('9');">9</button><button onclick="sendDtmf('0');">0</button><button onclick="sendDtmf('#');">#</button><button onclick="sendDtmf('*');">*</button></div></div><script src="./js/sip-0.13.8.js"></script><script>var extCode = "1012"; //分机号var extPass = "1012"; //分机密码var config = {uri: "sip:" +extCode + '@192.168.0.253:5066',authorizationUser: extCode,password: extPass,displayName: extCode,log: {builtinEnabled: true,level: 3 // log日志级别},transportOptions: {//  wsServers: ['ws://192.168.0.253:5066'], // ws协议wsServers: ['wss://192.168.0.253:7443'], //wss协议traceSip: true  //开启sip日志,用于排查问题},allowLegacyNotifications: true,hackWssInTransport: true, // 设置为true 则注册时 transport=wss; false:transport=ws;/*** sip.js生成的随机contact字符串 设置后会以此为后缀 可以搭配 cusContactName使用,根据自身业务进行使用*  设置前: sofia/internal/sip:admin10@df7jal23ls0d.invalid;*  设置后: sofia/internal/sip:admin10@192.168.0.253;**/hackIpInContact: "192.168.0.253",userAgentString: "myAwesomeApp",registerOptions: {expires: 300,registrar: 'sip:registrar.mydomain.com',},/*** 此处是笔者自定义的参数,因为注册到fs时,sip.js会随机生成contact字符串,如:sofia/internal/sip:admin10@df7jal23ls0d.invalid;*  笔者自己添加了一个参数,对sip.js的源码进行了修改 ,修改后效果  sofia/internal/sip:1012@192.168.0.253 不需要的可以不理会此参数* 此处纠正问题,官方提供了一个参数[contactName],使用此参数即可,sip.js使用官方的即可* contactName:"1012"*/// cusContactName: "1012"};var ua = new SIP.UA(config);var sessionall;var startCall = document.getElementById('startCall');var endCall = document.getElementById('endCall');var transfer = document.getElementById('transfer');var hold = document.getElementById('hold');var unhold = document.getElementById('unhold');var sendMessage = document.getElementById('sendMessage');var mute = document.getElementById('mute');var unmute = document.getElementById('unmute');var Ring={/*** 振铃*/startRingTone: function () {let play = document.getElementById("ringtone").play();play.then(()=>{}).catch((err)=>{});},/*** 停止振铃*/stopRingTone: function () {document.getElementById("ringtone").pause();},startRingbackTone: function () {let play = document.getElementById("ringbacktone").play();play.then(()=>{}).catch((err)=>{});},stopRingbackTone: function () {document.getElementById("ringbacktone").pause();}};/***  绑定方法* @param obj 要绑定事件的元素* @param ev 绑定的事件* @param fn  绑定事件的函数*/function bindEvent(obj, ev, fn) {if (obj.attachEvent) {obj.attachEvent("on" + ev, fn);}else {obj.addEventListener(ev, fn, false);}}/***  发送DTMF* @param num 按键*/function sendDtmf(num) {sessionall.dtmf(num);}/*** 拨打电话*/bindEvent(startCall, 'click', function () {var number = document.getElementById("number").value;//创建一个新的出站(用户代理客户端)会话sessionall = ua.invite(number, {sessionDescriptionHandlerOptions: {constraints: {audio: true,video: false},alwaysAcquireMediaFirst: true // 此参数是sip.js官方修复在firefox遇到的bug所设置}});//开始嘟嘟嘟Ring.startRingbackTone();var remoteVideo = document.getElementById('remoteVideo');var localVideo = document.getElementById('localVideo');//每次收到成功的最终(200-299)响应时都会触发。sessionall.on("accepted", function (response, cause) {console.log(response);Ring.stopRingbackTone();var pc = this.sessionDescriptionHandler.peerConnection;var remoteStream;if (pc.getReceivers) {remoteStream = new window.MediaStream();pc.getReceivers().forEach(function (receiver) {var track = receiver.track;if (track) {remoteStream.addTrack(track);}});} else {remoteStream = pc.getRemoteStreams()[0];}remoteVideo.srcObject = remoteStream;var localStream_1;if (pc.getSenders) {localStream_1 = new window.MediaStream();pc.getSenders().forEach(function (sender) {var track = sender.track;if (track && track.kind === "video") {localStream_1.addTrack(track);}});}else {localStream_1 = pc.getLocalStreams()[0];}localVideo.srcObject = localStream_1;})//挂机时会触发sessionall.on("bye", function (response, cause) {Ring.stopRingbackTone();console.log(response);})//请求失败时触发,无论是由于最终响应失败,还是由于超时,传输或其他错误。sessionall.on("failed", function (response, cause) {Ring.stopRingbackTone();console.log(response);})/****/sessionall.on("terminated", function (message, cause) {Ring.stopRingbackTone();})/*** 对方拒绝*/sessionall.on('rejected', function (response, cause) {Ring.stopRingbackTone();})})//挂断事件bindEvent(endCall, 'click', function () {if (!sessionall) {return;} else if (sessionall.startTime) { // Connectedsessionall.bye();} else if (sessionall.reject) { // Incomingsessionall.reject();} else if (sessionall.cancel) { // Outboundsessionall.cancel();}})//电话转移盲转bindEvent(transfer, 'click', function () {if (!sessionall) {return;}var number = document.getElementById("number").value;sessionall.refer(number, {receiveResponse: function (msg, ss) {console.error(msg);console.error(ss);}});})//电话保持bindEvent(hold, 'click', function () {if (!sessionall) {return;}sessionall.hold();})//恢复电话保持bindEvent(unhold, 'click', function () {if (!sessionall) {return;}sessionall.unhold();})//发送消息bindEvent(sendMessage, 'click', function () {// Sends a new messagevar number = document.getElementById("number").value;var message = document.getElementById("msg").value;ua.message(number, message);// When receiving a message, prints it outua.on('message', function (message) {console.log(message.body);});})// 静音bindEvent(mute, 'click', function () {if (!sessionall) {console.warn("No session to toggle mute");return;}var pc = sessionall.sessionDescriptionHandler.peerConnection;if (pc.getSenders) {pc.getSenders().forEach(function (sender) {if (sender.track) {sender.track.enabled = false;}});} else {pc.getLocalStreams().forEach(function (stream) {stream.getAudioTracks().forEach(function (track) {track.enabled = false;});stream.getVideoTracks().forEach(function (track) {track.enabled = false;});});}})// 解除静音bindEvent(unmute, 'click', function () {if (!sessionall) {console.warn("No session to toggle mute");return;}var pc = sessionall.sessionDescriptionHandler.peerConnection;if (pc.getSenders) {pc.getSenders().forEach(function (sender) {if (sender.track) {sender.track.enabled = true;}});} else {pc.getLocalStreams().forEach(function (stream) {stream.getAudioTracks().forEach(function (track) {track.enabled = true;});stream.getVideoTracks().forEach(function (track) {track.enabled = true;});});}})// 接受入站(用户代理服务器)会话ua.on('invite', function (session) {// 开始振铃Ring.startRingTone();var url = session.remoteIdentity.uri.toString() + "来电了,是否接听";var remoteVideo = document.getElementById('remoteVideo');var localVideo = document.getElementById('localVideo');session.on("terminated", function (message, cause) {Ring.stopRingTone();console.error(message);})/****/session.on('accepted', function (response, cause) {console.error(response);console.error(session);Ring.stopRingTone();// If there is a video track, it will attach the video and audio to the same elementvar pc = this.sessionDescriptionHandler.peerConnection;console.error(this.sessionDescriptionHandler);var remoteStream;if (pc.getReceivers) {remoteStream = new window.MediaStream();pc.getReceivers().forEach(function (receiver) {var track = receiver.track;if (track) {remoteStream.addTrack(track);}});} else {remoteStream = pc.getRemoteStreams()[0];}remoteVideo.srcObject = remoteStream;var localStream_1;if (pc.getSenders) {localStream_1 = new window.MediaStream();pc.getSenders().forEach(function (sender) {var track = sender.track;if (track && track.kind === "video") {localStream_1.addTrack(track);}});}else {localStream_1 = pc.getLocalStreams()[0];}localVideo.srcObject = localStream_1;localVideo.volume = 0;})session.on('bye', function (resp, cause) {Ring.stopRingTone();});var isaccept = confirm(url);if (isaccept) {//接受来电session.accept({sessionDescriptionHandlerOptions: {constraints: {audio: true,video: false}}});sessionall = session;}else {//拒绝来电session.reject();}});</script></body></html>

##参考资料: https://www.sipjs.com/
##参考资料: https://freeswitch.org/confluence/display/FREESWITCH/ACL
##参考资料: https://freeswitch.org/confluence/display/FREESWITCH/WebRTC#WebRTC-InstallCertificates
##源码连接: https://download.csdn.net/download/weixin_42275389/12919279
##码云地址:
如果文章帮到了你,请点个赞给笔者一个鼓励。如果有疑问,欢迎留言

Freeswitch+Sip.js实现软电话功能相关推荐

  1. Freeswitch+Sip.js 早期媒体(回铃音)

    Freeswitch+Sip.js 早期媒体(Early Media) 在笔者早期的文章里,没有对早期媒体进行处理,选择了本地的媒体进行播放,在当时看来还可以接受,但是目前来看,体验很差,所以笔者花费 ...

  2. JS调用拨打电话功能

    1.通过window.location.href 示例: window.location.href=tel://123456789: 2.通过a标签 示例: uniapp调用拨打电话功能:使用uni. ...

  3. sip软电话yate client的编译过程

    yate是一个开源的sip服务器以及软电话,其软电话yateclient是基于QT开发的.以下是在VS2005下编译的记录(需要先装好QT4.6). 1 设置yate项目路径 2 删除编译选项HAVE ...

  4. 呼叫系统使用webRTC网页软电话到底好不好?

    webRTC作为一个新的互联网技术,在通信系统中得到越来越广泛的应用. 不管是用电脑,还是手机,不用安装任何软件,打开网页,直接语音/视频,简单方便,是不是很美好? 在呼叫中心领域,webRTC的一个 ...

  5. 呼叫中心的软电话架构

              软电话系统白皮书 日期:2011-5-19 一.            软电话系统概述 软电话系统是CTI中间件和业务系统的中间纽带,在呼叫中心系统中起着至关重要的作用.它会将CT ...

  6. freeswitch配置软电话

    配置内部号码 1.编辑vars.xml ----修改默认密码 <X-PRE-PROCESS cmd="set" data="default_password=tes ...

  7. freeswitch软电话配置、结合讯时网关,外线电话呼入、呼出配置

    文章目录 软电话配置 配置外部电话呼入sip软电话 配置sip软电话呼出 交换机后台配置 参考资料 软电话配置 不同的软电话配置大同小异.FreeSWITCH 默认配置了 1000 ~ 1019 共 ...

  8. 【个人作品】推荐一个SIP客户端-软电话,基于SIP协议,语言C++,界面QT4 开源,asterisk,tribox测试成功

    推荐一个SIP客户端-软电话,基于SIP协议,语言C++,界面QT4 开源,asterisk,tribox测试成功 属于个人独创作品,欢迎使用测试,欢迎与作者联系,共同研究.如果大家喜欢将拿出源码. ...

  9. android 软电话 开发包-JNI 封装 SIP 协议,可进行二次开发应用于VOIP

    android 软电话 开发包-JNI 封装 SIP 协议,可进行二次开发应用于VOIP 该开发包为android平台下的JNI开发包,符合标准SIP协议,支持G729语音编码. 下载地址:源代码地址 ...

  10. FreeSWITCH软电话互打

    环境:Window/VS2015/FreeSWITCH-1.6.19源码 1:启动FreeSWITCH服务器 D:\VS\freeswitch-1.6.19\Win32\Debug目录以管理员身份运行 ...

最新文章

  1. mysql 安装问题一:由于找不到MSVCR120.dll,无法继续执行代码.重新安装程序可能会解决此问题。
  2. MATLAB中多个一维数组的合并
  3. 15天内数据迁移!广东省能源局发布通知,这类数据中心面临停工风险!
  4. split函数python_Python字符串split函数知多少【Python每日一个知识点第75期】
  5. asp.net MVC 应用程序的生命周期
  6. java第二版课后题答案_Java语言程序设计第2版第16章 课后习题答案
  7. oracle 群集 无存储,存储的群集注意事项 - Oracle® ZFS Storage Appliance 管理指南
  8. 【设计思想解读开源框架】mysql官方文档中文版下载免费
  9. sqlite3 出错
  10. GridView实战一:自定义分页、排序、修改、插入、删除
  11. 我开着超市,不好好做自己的生意,每天却为社区团购平台打工
  12. 【java笔记】System类
  13. matlab遥感代码,遥感融合定量评价matlab程序代码
  14. 浅谈计算机网络安全问题和对策
  15. 证明:在N维欧式空间中,两两互成钝角的非零向量不多于N+1个
  16. javascript英语单词音节拆分_英语单词音节的划分法
  17. android 键盘自适应,Android输入框布局如何随键盘变化
  18. 名片识别,史上最简单的集成攻略来啦!附有SDK包
  19. 蓝桥杯JAVA答题技巧,第九届蓝桥杯大赛个人赛省赛(软件类)C/C++ 大学B组比赛心得(还在更新)...
  20. 图谱实战 | 为什么我们需要医学知识图谱?

热门文章

  1. 成都百知教育关于Shopee 平台政策规则解读!
  2. zigbee三种组网形式及终端、路由、协调器理解
  3. 换个角度感受华为云的GPU云服务器
  4. fid和is_【GAN】用于生成图像的评价指标——IS和FID
  5. Excel--单元格格式设置
  6. 如何在开始菜单创建快捷方式
  7. linux查询本机IP地址(可用于SSH访问)
  8. HTML表格——使用CSS冻结行和列
  9. bzoj3668: [Noi2014]起床困难综合症
  10. 栈和队列的共同点和不同点