jssip + webRtc + Freeswitch 实现web端接打电话功能(接听,挂断,静音,取消静音)

做这些功能的前提,先要把freeswitch和webRtc搭建好

**
注意:
服务器域名必须是https
如果不使用摄像头,把video调成false
**

一:先上jssip官网 https://tryit.jssip.net/

官网测通之后,实际代码走起
我是按着这个文档一步一步弄的:https://www.cnblogs.com/gxp69/articles/12028002.html
真的好用,为了防止文章丢失我还是再粘贴一遍吧

<!DOCTYPE html>
<html>
<head><title>JsSIP + WebRTC + freeSWITCH</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="Author" content="foruok" /><meta name="description" content="JsSIP based example web application." /><script src="./jssip-3.3.11.min.js" type="text/javascript"></script><style type="text/css"></style>
</head><body><div id="login-page" style="width: 424px; height: 260px; background-color: #f2f4f4; border: 1px solid grey; padding-top: 4px"><table border="0" frame="void" width="418px"><tr><td class="td_label" width="160px" align="right"><label for="sip_uri">SIP URI:</label></td><td width="258px"><input style="width:250px" id="sip_uri" type="text" placeholder="SIP URI (i.e: sip:alice@example.com)" value=""/></td></tr><tr><td class="td_label"  align="right"><label for="sip_password">SIP Password:</label></td><td><input style="width:250px" id="sip_password" type="password" placeholder="SIP password" value=""/></td></tr><tr><td class="td_label" align="right"><label for="ws_uri">WSS URI:</label></td><td><input style="width:250px" id="ws_uri" class="last unset" type="text" placeholder="WSS URI (i.e: wss://example.com)" value=""/></td></tr><tr><td class="td_label"  align="right"><label class="input_label" for="sip_phone_number">SIP Phone Info:</label></td><td><input style="width:250px" id="sip_phone_number" type="text" placeholder="sip:3000@192.168.40.96:5060" value=""></td></tr><tr><td colspan="2" align="center"><button onclick="testStart()"> Initialize </button></td></tr><tr><td colspan="2" align="center"><button onclick="testCall()"> Call </button></td></tr><tr><td  colspan="2" align="center"><button onclick="captureLocalMedia()"> Capture Local Media</button></td></tr></table>
</div><div style="width: 424px; height: 324px;background-color: #333333; border: 2px solid blue; padding:0px; margin-top: 4px;"><video id="video" width="420px" height="320px" autoplay ></video><audio id="audio" controls></audio>
</div></body>
<script type="text/javascript">var outgoingSession = null;var incomingSession = null;var currentSession = null;var audio = document.getElementById('audio');var constraints = {audio: true,video: true,mandatory: {maxWidth: 640,maxHeight: 360}};URL = window.URL || window.webkitURL;var localStream = null;var userAgent = null;function gotLocalMedia(stream) {console.info('Received local media stream');localStream = stream;audio.src = URL.createObjectURL(stream);}function captureLocalMedia() {console.info('Requesting local video & audio');navigator.webkitGetUserMedia(constraints, gotLocalMedia, function(e){alert('getUserMedia() error: ' + e.name);});}function testStart(){var sip_uri_ = document.getElementById("sip_uri").value.toString();var sip_password_ = document.getElementById("sip_password").value.toString();var ws_uri_ = document.getElementById("ws_uri").value.toString();console.info("get input info: sip_uri = ", sip_uri_, " sip_password = ", sip_password_, " ws_uri = ", ws_uri_);var socket = new JsSIP.WebSocketInterface(ws_uri_);var configuration = {sockets: [ socket ],outbound_proxy_set: ws_uri_,uri: sip_uri_,//与用户代理关联的SIP URI(字符串)。这是您的提供商提供给您的SIP地址password: sip_password_,//SIP身份验证密码register: true,//指示启动时JsSIP用户代理是否应自动注册session_timers: false//启用会话计时器(根据RFC 4028)};userAgent = new JsSIP.UA(configuration);//成功注册成功,data:Response JsSIP.IncomingResponse收到的SIP 2XX响应的实例userAgent.on('registered', function(data){console.info("registered: ", data.response.status_code, ",", data.response.reason_phrase);});//由于注册失败而被解雇,data:Response JsSIP.IncomingResponse接收到的SIP否定响应的实例,如果失败是由这样的响应的接收产生的,否则为空userAgent.on('registrationFailed', function(data){console.log("registrationFailed, ", data);//console.warn("registrationFailed, ", data.response.status_code, ",", data.response.reason_phrase, " cause - ", data.cause);});//1.在注册到期之前发射几秒钟。如果应用程序没有为这个事件设置任何监听器,JsSIP将像往常一样重新注册。// 2.如果应用程序订阅了这个事件,它负责ua.register()在registrationExpiring事件中调用(否则注册将过期)。// 3.此事件使应用程序有机会在重新注册之前执行异步操作。对于那些在REGISTER请求中的自定义SIP头中使用外部获得的“令牌”的环境很有用。userAgent.on('registrationExpiring', function(){console.warn("registrationExpiring");});//为传入或传出会话/呼叫激发。data://     originator:'remote',新消息由远程对等方生成;'local',新消息由本地用户生成。//      session:JsSIP.RTCSession 实例。//      request:JsSIP.IncomingRequest收到的MESSAGE请求的实例;JsSIP.OutgoingRequest传出MESSAGE请求的实例userAgent.on('newRTCSession', function(data){console.info('onNewRTCSession: ', data);if(data.originator == 'remote'){ //incoming callconsole.info("incomingSession, answer the call");incomingSession = data.session;//回答传入会话。此方法仅适用于传入会话。//answer设置的自动接听//RTCSession 的 answer 方法做了自动接听。实际开发中,你需要弹出一个提示框,让用户选择是否接听data.session.answer({'mediaConstraints' : { 'audio': true, 'video': true },// 'mediaStream': localStream});//拿到远程的音频流data.session.connection.addEventListener("addstream", function (ev) {console.info('onaddstream from remote - ', ev.stream);audio.srcObject  = ev.stream;});}else{console.info("outgoingSession");outgoingSession = data.session;outgoingSession.on('connecting', function(data){console.info('onConnecting - ', data.request);currentSession = outgoingSession;outgoingSession = null;});}//接受呼叫时激发data.session.on('accepted', function(data){console.info('onAccepted - ', data);if(data.originator == 'remote' && currentSession == null){currentSession = incomingSession;incomingSession = null;console.info("setCurrentSession - ", currentSession);}});//确认呼叫后激发data.session.on('confirmed', function(data){console.info('onConfirmed - ', data);if(data.originator == 'remote' && currentSession == null){currentSession = incomingSession;incomingSession = null;console.info("setCurrentSession - ", currentSession);}});//在将远程SDP传递到RTC引擎之前以及在发送本地SDP之前激发。此事件提供了修改传入和传出SDP的机制。data.session.on('sdp', function(data){console.info('onSDP, type - ', data.type, ' sdp - ', data.sdp);//data.sdp = data.sdp.replace('UDP/TLS/RTP/SAVPF', 'RTP/SAVPF');//console.info('onSDP, changed sdp - ', data.sdp);});//接收或生成对邀请请求的1XX SIP类响应(>100)时激发。该事件在SDP处理之前触发(如果存在),以便在需要时对其进行微调,甚至通过删除数据对象中响应参数的主体来删除它data.session.on('progress', function(data){console.info('onProgress - ', data.originator);if(data.originator == 'remote'){console.info('onProgress, response - ', data.response);}});//创建基础RTCPeerConnection后激发。应用程序有机会通过在peerconnection上添加RTCDataChannel或设置相应的事件侦听器来更改peerconnection。data.session.on('peerconnection', function(data){console.info('onPeerconnection - ', data.peerconnection);data.peerconnection.onaddstream = function(ev){console.info('onaddstream from remote - ', ev);audio.src = URL.createObjectURL(ev.stream);audio.onloadstart = () => {audio.play();};audio.onerror = () => {alert('录音加载失败...');};};});});//为传入或传出消息请求激发。data://     originator:'remote',新消息由远程对等方生成;'local',新消息由本地用户生成。//      message:JsSIP.Message 实例。//      request:JsSIP.IncomingRequest收到的MESSAGE请求的实例;JsSIP.OutgoingRequest传出MESSAGE请求的实例userAgent.on('newMessage', function(data){if(data.originator == 'local'){console.info('onNewMessage , OutgoingRequest - ', data.request);}else{console.info('onNewMessage , IncomingRequest - ', data.request);}});console.info("call register");//连接到信令服务器,并恢复以前的状态,如果以前停止。重新开始时,如果UA配置中的参数设置为register:true,则向SIP域注册。userAgent.start();}// Register callbacks to desired call eventsvar eventHandlers = {'progress': function(e) {console.log('call is in progress');},'failed': function(e) {console.log('call failed: ', e);},'ended': function(e) {console.log('call ended : ', e);},'confirmed': function(e) {console.log('call confirmed');}};function testCall(){var sip_phone_number_ = document.getElementById("sip_phone_number").value.toString();var options = {'eventHandlers'    : eventHandlers,'mediaConstraints' : { 'audio': true, 'video': false ,},//'mediaStream': localStream};//outgoingSession = userAgent.call('sip:3000@192.168.40.96:5060', options);/** 拨打多媒体电话。不需要自己调用 getUserMedia 来捕获音视频了, JsSIP 会根据你传给JsSIP.UA.call方法的参数来自己调用参数Target 通话的目的地。String表示目标用户名或完整的SIP URI或JsSIP.URI实例。Options 可选Object附加参数(见下文)。options对象中的字段;mediaConstraints Object有两个有效的字段(audio和video)指示会话是否打算使用音频和/或视频以及要使用的约束。默认值是audio并且video设置为true。mediaStream MediaStream 传送到另一端。eventHandlers Object事件处理程序的可选项将被注册到每个呼叫事件。为每个要通知的事件定义事件处理程序。*/outgoingSession = userAgent.call(sip_phone_number_, options);}
</script>
</html>

测试的时候发现有个地方有错误URL:audio.src = URL.createObjectURL(stream);
修改了一下可以测通

 try {audio.src = stream;} catch (error) {audio.src = URL.createObjectURL(stream);}

jssip + webRtc + Freeswitch 实现web端接打电话功能相关推荐

  1. jssip+webRtc+freeswitch 实现web端语音通话

    该文章只说明前端代码逻辑,如有错误,感谢指出. jssip官方网站 jssip中文文档api html部分代码 主要通过ontrack事件监听媒体流,实现语音实时通话 <template> ...

  2. [Web端接入经验分享] 腾讯云即时通信TIM、实时音视频TRTC

    [Web端接入经验分享] 腾讯云即时通信TIM.实时音视频TRTC 即时通信TIM官网地址 即时通信TIM SDK API文档地址 实时音视频TRTC官网地址 实时音视频TRTC SDK API文档地 ...

  3. iOS 调用系统发短信以及打电话功能

    先介绍一种最简单的方法: 调用打电话功能 [[UIApplicationsharedApplication] openURL:[NSURL URLWithString:@"tel://100 ...

  4. IOS 程序内调用本地打电话功能-make a phone call

    利用openURL接口来调用打电话功能.代码还具备根据正则表达式判断电话好吗输入的合法性. 1 - (void)makeCall:(NSString *)number 2 { 3 NSString * ...

  5. Android打电话功能权限报错,从打电话权限报错看Android6.0权限变化

    引言:去年Android 6.0发布后,其新引入的(Requesting Permissions at Run Time)运行时权限就备受开发者关注,随着今年国内手机厂商对6.0系统的普及,觉得大家有 ...

  6. 使用QuickPart时应用自定义属性和Web Part Connection功能的演示视频

    QuickPart的目标之一,就是让使用它创建出来的Web Part不丧失任何Web Part已有的功能,包括Web Part自定义属性.Web Part Connection等.QuickPart对 ...

  7. 在vue.js中实现a标签href tel的打电话功能

    在vue.js中实现a标签href tel的打电话功能 div v-for="p in persons"> <p> name: {{ p.name }} < ...

  8. android远程打电话,Android打电话功能 Android实战教程第三篇之简单实现拨打电话功能...

    想了解Android实战教程第三篇之简单实现拨打电话功能的相关内容吗,杨道龙在本文为您仔细讲解Android打电话功能的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Android拨打电话 ...

  9. XiaomiRouter自学之路(13-U-boot支持web更新firmware功能)

    XiaomiRouter自学之路(13-U-boot支持web更新firmware功能) 上一章节说明小米路由器3触发了web更新firmware的功能,因为下载的源码中已经支持改功能了,只不过小米路 ...

最新文章

  1. 基于Docker的TensorFlow机器学习框架搭建和实例源码解读
  2. 实时计算 Flink性能调优
  3. Android开发之PCM音频流采集| 音频流录制与PCM音频流播放的实现方法
  4. 6 如何查看MESSAGE消息
  5. Kudu : tablet=null, server=null, status=Timed out: can not complete before timeout: Batch
  6. 微服务 mysql 连接池_【mysql】druid,连接池和微服务的问题
  7. 创建型设计模式(1)—— 单例模式(Singleton Pattern)
  8. jsp上传文件到数据库和从数据库下载文件
  9. 持续集成jenkins工具介绍(一)
  10. Linux内核部件分析 更强的链表klist
  11. jsp分页功能的位置有可能会影响到翻页时的查询条件
  12. 【论文笔记】韩家炜团队AutoPhrase:自动短语挖掘
  13. 【附Python版教学】“那些年用过的奇葩辞职理由”哈哈哈,看完笑掉牙。
  14. linux 命令是什么的缩写,Linux一部分命令解释(命令缩写代表什么意思)
  15. ubuntu php代码编辑器,Linux_ubuntu16.04编辑器vi该怎么使用?,vi编辑器,ubuntu中最基本的文 - phpStudy...
  16. 服务器通过ilo安装系统,如何通过ilo开启服务器远程桌面
  17. 为什么这项技术一经Google推出问世就迅速成为主流?
  18. 88e1111 phy芯片在arm平台的配置及接口介绍
  19. 潘多拉-视频播放器,一个轻量的视频播放器
  20. [小说]魔王冢(48)诏告

热门文章

  1. 永磁同步电机矢量控制(七)——基于id=0的矢量控制的动态解耦策略
  2. 获取并播放youtube data视频
  3. 定积分证明题例题_定积分证明题.doc
  4. 余额宝利息是多少对余额宝有何风险吗?
  5. java计算机毕业设计WEB儿童运动馆业务信息系统MyBatis+系统+LW文档+源码+调试部署
  6. 微信公众号教程(12)公众账号接收非文字消息 下
  7. Linux shell jq格式化查看 Json 文件
  8. OpenCV小游戏-《跑跑卡丁车》项目实践-1
  9. python定时开关机的代码_用python写一个windows下的定时关机脚本(推荐)
  10. Maya(Qtp)十月笔记