var outgoingSession = null,incomingSession = null,currentSession = null,calState,nativeStream =null,callVideoState = null, callVideoFail = null; var myVideoView = document.getElementById('myVideo'); //我的本地视频 var yourVideoView = document.getElementById('yourVideo'); //对方视频信息 var getWidthScale = document.documentElement.clientWidth; var bigVideoStyle = {"background-color":"#000000","width":"100%","height":"100%","top":"0","right":"0","z-index":"1"} var smallVideoStyle = {"background-color":"#EEEEEE","width":"20%","height":"20%","top":"10px","right":"10px","z-index":"2"} var localStream = null,userAgent = null,superviseMan =null,videoInputDevices = [],currentVideoIndex = 0,isswitch = 0; $(function(){ $(".videoYour video").css({ "width":getWidthScale*2.7+"px", "margin-left":-getWidthScale*2.7/2+"px" }) $(".videoMy video").css({ "width":getWidthScale*1.5*0.2+"px", "margin-left":-getWidthScale*1.5*0.2/2+"px" }) $(this).attr("index","1") $(".videoMy").removeAttr("index") mediumInfo() //获取摄像头信息 }) //切换摄像头 function shotCut(){ if (currentVideoIndex == 1) { currentVideoIndex = 0; } else { currentVideoIndex = 1; }; try { isswitch = 1; //muteSession var ls = muteSession.connection.getLocalStreams()[0]; ls.getTracks().forEach(function(track) { if(track.kind=='video'){ track.stop(); } }); //currentSession.connection.removeStream(ls); navigator.getUserMedia({ audio: false, video: { deviceId: { exact: videoInputDevices[currentVideoIndex].deviceId } }, }, function(stream) { //currentSession.connection.addStream(stream); //const tracks = stream.getTracks(); const tracks = stream.getVideoTracks()[0]; // currentSession.connection.getSenders() // .forEach(sender => { // const newTrack = tracks.find(track => track.kind === sender.track.kind) // sender.replaceTrack(newTrack) // }) var sender=muteSession.connection.getSenders().find(function(s){return s.track.kind==tracks.kind;}); sender.replaceTrack(tracks); myVideoView.srcObject = stream; }, function(e) { alert('getUserMedia() error3: ' + JSON.stringify(e)); }); } catch (e) { alert(JSON.stringify(e)); } } function mediumInfo(){ navigator.mediaDevices.enumerateDevices() .then(gotDevices).catch(handleError); function gotDevices(deviceInfos) { //alert(JSON.stringify(deviceInfos)); deviceInfos.forEach(function(n) { if (n.kind === 'videoinput') { videoInputDevices.push(n); } }) } function handleError(error) { //alert(JSON.stringify(error)); } } //注册成功事件 function registered(){ $(".registStatus").show() if($(".superviseBtn").text()=="我是市民"){ $(".registStatus").text("登录成功") $(".loginbtn").hide(); $(".videoCall").show(); } else if($(".superviseBtn").text()=="我是督办专员"){ $(".registStatus").text("连接成功") $("#account").val(extenNum) } } //电话呼入事件 function newRTCSession(){ $(".mui-content").hide(); $(".callHtml").show(); $(".answerIcon").show(); captureLocalMediaVideo(); localMediaStream() } //确认呼叫后触发 function confirmed(){ $(".dropIcon").show() $(".answerIcon").hide() } //peerconnection 媒体传输事件 function peerconnection(){ $(".videoYour").show(); $(".customerImg").show(); $(".rightImg").hide(); } $(".videoYour").click(function(){ if(!$(this).attr("index")){ $(this).css(bigVideoStyle) $(".videoYour video").css({ "width":getWidthScale*2.7+"px", "margin-left":-getWidthScale*2.7/2+"px" }) $(".videoMy").css(smallVideoStyle) $(".videoMy video").css({ "width":getWidthScale*1.5*0.2+"px", "margin-left":-getWidthScale*1.5*0.2/2+"px" }) $(this).attr("index","1") $(".videoMy").removeAttr("index") } }) $(".videoMy").click(function(){ if(!$(this).attr("index")){ $(this).css(bigVideoStyle) $(".videoMy video").css({ "width":getWidthScale*1.5+"px", "margin-left":-getWidthScale*1.5/2+"px" }) $(".videoYour").css(smallVideoStyle) $(".videoYour video").css({ "width":getWidthScale*2.7*0.2+"px", "margin-left":-getWidthScale*2.7*0.2/2+"px" }) $(this).attr("index","1") $(".videoYour").removeAttr("index") } }) //视频呼叫 $(".videoCall").click(function(){ callVideoState = true ; callVideoFail = true; calState = $(this).attr("data-attr"); captureLocalMediaVideo(); localMediaStream() //videoCall() }) //静音 $(".muteBtn").click(function(){ console.log(muteSession.isMuted()) muteSession.mute( { 'audio': true, // Local audio is muted } ) $(".muteBtn").hide(); $(".unMuteBtn").show(); }) //取消静音 $(".unMuteBtn").click(function(){ console.log(muteSession.isMuted()) muteSession.unmute( { 'audio': true, // Local audio is muted } ) $(".muteBtn").show(); $(".unMuteBtn").hide(); }) //关闭摄像头 $(".cameraBtn").click(function(){ console.log(muteSession.isMuted()) muteSession.mute( { 'video': true, // Local audio is muted } ) $(".cameraBtn").hide(); $(".unCameraBtn").show(); }) //取消关闭摄像头 $(".unCameraBtn").click(function(){ console.log(muteSession.isMuted()) muteSession.unmute( { 'video': true, // Local audio is muted } ) $(".cameraBtn").show(); $(".unCameraBtn").hide(); }) function videoCall(){ $(".mui-content").hide(); $(".callHtml").show(); console.log(calState) //var sip_phone_number_ = $("#callIuput").val().toString(); var sip_phone_number_ = callNum.toString(); console.log(sip_phone_number_) var options = { 'eventHandlers': eventHandlers, 'mediaConstraints': { 'audio': true, 'video': { 'width': 320, 'height': 240 } }, 'mediaStream': localStream }; callVideoState = false ; dbCallVideoState = false; outgoingSession = userAgent.call(sip_phone_number_, options); } //接听 function answerCall() { console.log(incomingSession) if (incomingSession) { incomingSession.answer({ 'mediaConstraints': { 'audio': true, 'video': { 'width': 320, 'height': 240 } }, 'mediaStream': localStream }); incomingSession = null; } } //挂断 function hangupCall() { console.log('挂断----------->'); if ($(".superviseBtn").text()=="我是督办专员") { obj={}; obj.Type = "VideoDesExten"; obj.AgentID = RandomTimeData; obj.AgentExten = extenNum.toString() Send(); /*2018-05-19zhangshaungnan注释*/ $(".registStatus").html("已注销") } else if($(".superviseBtn").text()=="我是市民"){ window.location.href="superviseMan.html?extenNum="+$("#account").val()+"&telephone="+$("#telephone").val() } closeMediaVideo(); //我的媒体信息 $(".mui-content").show(); $(".callHtml").hide(); console.log(extenNum) // music.pause(); userAgent.terminateSessions(); } //注销 function unReg() { closeMediaVideo(); if(!superviseMan){ console.log('注销----------->'); userAgent.unregister(true); $(".registStatus").html("已注销") } else { window.location.href="superviseMan.html?extenNum="+$("#account").val()+"&telephone="+$("#telephone").val() } $(".mui-content").show(); $(".callHtml").hide(); $(".dropIcon").hide() $(".answerIcon").hide() } //开启本地摄像头 function captureLocalMediaVideo() { navigator.getUserMedia({ video: { deviceId: { exact: videoInputDevices[currentVideoIndex].deviceId } }, audio: false }, function(stream) { nativeStream = stream; myVideoView.srcObject = stream; }, function(e) { alert('getUserMedia() error: ' + e.name); }); } //获取本地媒体流 function localMediaStream() { navigator.getUserMedia({ video: { deviceId: { exact: videoInputDevices[currentVideoIndex].deviceId } }, audio: true }, function(stream) { localStream = stream; if(callVideoState){extenBind()} if(dbCallVideoState){videoReqExten()} }, function(e) { alert('getUserMedia() error: ' + e.name); }); } // 关闭摄像头 function closeMediaVideo() { //console.log("1213") if(nativeStream){ nativeStream.getTracks().forEach(function(track) { track.stop(); }); } if(localStream){ localStream.getTracks().forEach(function(track) { track.stop(); }); } } //testStart() function testStart() { 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身份验证密码 contact_uri: 'sip:1007@'+returnCitySN["cip"]+';transport=ws', //stun_servers: "stun1.l.google.com:19302", register: true, //指示启动时JsSIP用户代理是否应自动注册 session_timers: false //启用会话计时器(根据RFC 4028) }; userAgent = new JsSIP.UA(configuration); //JsSIP.debug.enable('JsSIP:*'); JsSIP.debug.disable('JsSIP:*'); //成功注册成功,data:Response JsSIP.IncomingResponse收到的SIP 2XX响应的实例 userAgent.on('registered', function(data) { console.info("registered: ", data.response.status_code, ",", data.response.reason_phrase); registered(); }); //由于注册失败而被解雇,data:Response JsSIP.IncomingResponse接收到的SIP否定响应的实例,如果失败是由这样的响应的接收产生的,否则为空 userAgent.on('registrationFailed', function(data) { }); //1.在注册到期之前发射几秒钟。如果应用程序没有为这个事件设置任何监听器,JsSIP将像往常一样重新注册。 // 2.如果应用程序订阅了这个事件,它负责ua.register()在registrationExpiring事件中调用(否则注册将过期)。 // 3.此事件使应用程序有机会在重新注册之前执行异步操作。对于那些在REGISTER请求中的自定义SIP头中使用外部获得的“令牌”的环境很有用。 userAgent.on('registrationExpiring', function() { //==console.warn("registrationExpiring"); }); //每次传输连接尝试均触发。 userAgent.on('connecting ',function(data){ console.log('每次传输连接尝试均触发6666'+data); }) //建立传输连接时触发。 userAgent.on('connected ',function(data){ console.log('建立传输连接时触发666'+data); }) //当传输连接尝试(或自动重新尝试)失败时触发。。 userAgent.on('disconnected ',function(data){ console.log('当传输连接尝试(或自动重新尝试)失败时触发。666'+data); }) //为传入或传出会话/呼叫激发。data: // originator:'remote',新消息由远程对等方生成;'local',新消息由本地用户生成。 // session:JsSIP.RTCSession 实例。 // request:JsSIP.IncomingRequest收到的MESSAGE请求的实例;JsSIP.OutgoingRequest传出MESSAGE请求的实例 userAgent.on('newRTCSession', function(data) { muteSession = data.session console.log(muteSession) console.info('onNewRTCSession: ', data); var originator = data.originator; var session = data.session; var request = data.request; if (data.originator == 'remote') { //incoming call console.log("电话呼入--1"); console.info("incomingSession, answer the call"); incomingSession = data.session; newRTCSession(); //console.info("incomingSession, answer the call"); //回答传入会话。此方法仅适用于传入会话。 } 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-----接受呼叫时激发"); //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("confirmed-----确认呼叫后激发"); //console.info('onConfirmed - ', data); $(".leftText").html("通话中"); console.log(data) confirmed(); 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("sdp-----在将远程SDP传递到RTC引擎之前以及在发送本地SDP之前激发"); }); //接收或生成对邀请请求的1XX SIP类响应(>100)时激发。该事件在SDP处理之前触发(如果存在),以便在需要时对其进行微调,甚至通过删除数据对象中响应参数的主体来删除它 data.session.on('progress', function(data) { console.info("progress-----接收或生成对邀请请求的1XX SIP类响应(>100)时激发。该事件在SDP处理之前触发"); //console.info('onProgress - ', data); if (data.originator == 'remote') {} }); data.session.on('addstream', function(data) { console.info("addstream-----接收或生成对邀请请求的1XX SIP类响应(>100)时激发。该事件在SDP处理之前触发"); yourVideoView.srcObject = data.stream; }); //创建基础RTCPeerConnection后激发。应用程序有机会通过在peerconnection上添加RTCDataChannel或设置相应的事件侦听器来更改peerconnection。 data.session.on('peerconnection', function(data) { console.info('onPeerconnection ----创建基础RTCPeerConnection后激发 '); // peerConnection.removeStream(peerConnection.getLocalStreams()[0]); // peerConnection.addLocalStream(stream); // pc.getSenders()[1].replaceTrack(videoTracks[0]); console.log(data.peerconnection.getSenders()) data.peerconnection.onaddstream = function(ev) { //console.info('onaddstream from remote - ', ev); onaddtrack onaddstream //music.pause(); peerconnection() callVideoFail = false console.log(ev.stream); yourVideoView.srcObject = ev.stream; }; }); }); //为传入或传出消息请求激发。data: 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 events var eventHandlers = { 'progress': function(e) { console.log('call is in progress'); //music.play(); }, 'failed': function(e) { if(callVideoFail){ setTimeout(function(){videoCall()},2000) } console.log('call failed: ', e); }, 'ended': function(e) { console.log('call ended : ', e); unReg(); }, 'confirmed': function(e) { console.log('call confirmed'); } };