Bez popisu

mobileSip.js 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. var outgoingSession = null,incomingSession = null,currentSession = null,calState,nativeStream =null,callVideoState = null, callVideoFail = null;
  2. var myVideoView = document.getElementById('myVideo'); //我的本地视频
  3. var yourVideoView = document.getElementById('yourVideo'); //对方视频信息
  4. var getWidthScale = document.documentElement.clientWidth;
  5. var bigVideoStyle = {"background-color":"#000000","width":"100%","height":"100%","top":"0","right":"0","z-index":"1"}
  6. var smallVideoStyle = {"background-color":"#EEEEEE","width":"20%","height":"20%","top":"10px","right":"10px","z-index":"2"}
  7. var localStream = null,userAgent = null,superviseMan =null,videoInputDevices = [],currentVideoIndex = 0,isswitch = 0;
  8. $(function(){
  9. $(".videoYour video").css({
  10. "width":getWidthScale*2.7+"px",
  11. "margin-left":-getWidthScale*2.7/2+"px"
  12. })
  13. $(".videoMy video").css({
  14. "width":getWidthScale*1.5*0.2+"px",
  15. "margin-left":-getWidthScale*1.5*0.2/2+"px"
  16. })
  17. $(this).attr("index","1")
  18. $(".videoMy").removeAttr("index")
  19. mediumInfo() //获取摄像头信息
  20. })
  21. //切换摄像头
  22. function shotCut(){
  23. if (currentVideoIndex == 1) {
  24. currentVideoIndex = 0;
  25. } else {
  26. currentVideoIndex = 1;
  27. };
  28. try {
  29. isswitch = 1;
  30. //muteSession
  31. var ls = muteSession.connection.getLocalStreams()[0];
  32. ls.getTracks().forEach(function(track) {
  33. if(track.kind=='video'){
  34. track.stop();
  35. }
  36. });
  37. //currentSession.connection.removeStream(ls);
  38. navigator.getUserMedia({
  39. audio: false,
  40. video: {
  41. deviceId: {
  42. exact: videoInputDevices[currentVideoIndex].deviceId
  43. }
  44. },
  45. }, function(stream) {
  46. //currentSession.connection.addStream(stream);
  47. //const tracks = stream.getTracks();
  48. const tracks = stream.getVideoTracks()[0];
  49. // currentSession.connection.getSenders()
  50. // .forEach(sender => {
  51. // const newTrack = tracks.find(track => track.kind === sender.track.kind)
  52. // sender.replaceTrack(newTrack)
  53. // })
  54. var sender=muteSession.connection.getSenders().find(function(s){return s.track.kind==tracks.kind;});
  55. sender.replaceTrack(tracks);
  56. myVideoView.srcObject = stream;
  57. }, function(e) {
  58. alert('getUserMedia() error3: ' + JSON.stringify(e));
  59. });
  60. } catch (e) {
  61. alert(JSON.stringify(e));
  62. }
  63. }
  64. function mediumInfo(){
  65. navigator.mediaDevices.enumerateDevices()
  66. .then(gotDevices).catch(handleError);
  67. function gotDevices(deviceInfos) {
  68. //alert(JSON.stringify(deviceInfos));
  69. deviceInfos.forEach(function(n) {
  70. if (n.kind === 'videoinput') {
  71. videoInputDevices.push(n);
  72. }
  73. })
  74. }
  75. function handleError(error) {
  76. //alert(JSON.stringify(error));
  77. }
  78. }
  79. //注册成功事件
  80. function registered(){
  81. $(".registStatus").show()
  82. if($(".superviseBtn").text()=="我是市民"){
  83. $(".registStatus").text("登录成功")
  84. $(".loginbtn").hide();
  85. $(".videoCall").show();
  86. } else if($(".superviseBtn").text()=="我是督办专员"){
  87. $(".registStatus").text("连接成功")
  88. $("#account").val(extenNum)
  89. }
  90. }
  91. //电话呼入事件
  92. function newRTCSession(){
  93. $(".mui-content").hide();
  94. $(".callHtml").show();
  95. $(".answerIcon").show();
  96. captureLocalMediaVideo();
  97. localMediaStream()
  98. }
  99. //确认呼叫后触发
  100. function confirmed(){
  101. $(".dropIcon").show()
  102. $(".answerIcon").hide()
  103. }
  104. //peerconnection 媒体传输事件
  105. function peerconnection(){
  106. $(".videoYour").show();
  107. $(".customerImg").show();
  108. $(".rightImg").hide();
  109. }
  110. $(".videoYour").click(function(){
  111. if(!$(this).attr("index")){
  112. $(this).css(bigVideoStyle)
  113. $(".videoYour video").css({
  114. "width":getWidthScale*2.7+"px",
  115. "margin-left":-getWidthScale*2.7/2+"px"
  116. })
  117. $(".videoMy").css(smallVideoStyle)
  118. $(".videoMy video").css({
  119. "width":getWidthScale*1.5*0.2+"px",
  120. "margin-left":-getWidthScale*1.5*0.2/2+"px"
  121. })
  122. $(this).attr("index","1")
  123. $(".videoMy").removeAttr("index")
  124. }
  125. })
  126. $(".videoMy").click(function(){
  127. if(!$(this).attr("index")){
  128. $(this).css(bigVideoStyle)
  129. $(".videoMy video").css({
  130. "width":getWidthScale*1.5+"px",
  131. "margin-left":-getWidthScale*1.5/2+"px"
  132. })
  133. $(".videoYour").css(smallVideoStyle)
  134. $(".videoYour video").css({
  135. "width":getWidthScale*2.7*0.2+"px",
  136. "margin-left":-getWidthScale*2.7*0.2/2+"px"
  137. })
  138. $(this).attr("index","1")
  139. $(".videoYour").removeAttr("index")
  140. }
  141. })
  142. //视频呼叫
  143. $(".videoCall").click(function(){
  144. callVideoState = true ;
  145. callVideoFail = true;
  146. calState = $(this).attr("data-attr");
  147. captureLocalMediaVideo();
  148. localMediaStream()
  149. //videoCall()
  150. })
  151. //静音
  152. $(".muteBtn").click(function(){
  153. console.log(muteSession.isMuted())
  154. muteSession.mute(
  155. {
  156. 'audio': true, // Local audio is muted
  157. }
  158. )
  159. $(".muteBtn").hide();
  160. $(".unMuteBtn").show();
  161. })
  162. //取消静音
  163. $(".unMuteBtn").click(function(){
  164. console.log(muteSession.isMuted())
  165. muteSession.unmute(
  166. {
  167. 'audio': true, // Local audio is muted
  168. }
  169. )
  170. $(".muteBtn").show();
  171. $(".unMuteBtn").hide();
  172. })
  173. //关闭摄像头
  174. $(".cameraBtn").click(function(){
  175. console.log(muteSession.isMuted())
  176. muteSession.mute(
  177. {
  178. 'video': true, // Local audio is muted
  179. }
  180. )
  181. $(".cameraBtn").hide();
  182. $(".unCameraBtn").show();
  183. })
  184. //取消关闭摄像头
  185. $(".unCameraBtn").click(function(){
  186. console.log(muteSession.isMuted())
  187. muteSession.unmute(
  188. {
  189. 'video': true, // Local audio is muted
  190. }
  191. )
  192. $(".cameraBtn").show();
  193. $(".unCameraBtn").hide();
  194. })
  195. function videoCall(){
  196. $(".mui-content").hide();
  197. $(".callHtml").show();
  198. console.log(calState)
  199. //var sip_phone_number_ = $("#callIuput").val().toString();
  200. var sip_phone_number_ = callNum.toString();
  201. console.log(sip_phone_number_)
  202. var options = {
  203. 'eventHandlers': eventHandlers,
  204. 'mediaConstraints': {
  205. 'audio': true,
  206. 'video': {
  207. 'width': 320,
  208. 'height': 240
  209. }
  210. },
  211. 'mediaStream': localStream
  212. };
  213. callVideoState = false ;
  214. dbCallVideoState = false;
  215. outgoingSession = userAgent.call(sip_phone_number_, options);
  216. }
  217. //接听
  218. function answerCall() {
  219. console.log(incomingSession)
  220. if (incomingSession) {
  221. incomingSession.answer({
  222. 'mediaConstraints': {
  223. 'audio': true,
  224. 'video': {
  225. 'width': 320,
  226. 'height': 240
  227. }
  228. },
  229. 'mediaStream': localStream
  230. });
  231. incomingSession = null;
  232. }
  233. }
  234. //挂断
  235. function hangupCall() {
  236. console.log('挂断----------->');
  237. if ($(".superviseBtn").text()=="我是督办专员") {
  238. obj={};
  239. obj.Type = "VideoDesExten";
  240. obj.AgentID = RandomTimeData;
  241. obj.AgentExten = extenNum.toString()
  242. Send(); /*2018-05-19zhangshaungnan注释*/
  243. $(".registStatus").html("已注销")
  244. } else if($(".superviseBtn").text()=="我是市民"){
  245. window.location.href="superviseMan.html?extenNum="+$("#account").val()+"&telephone="+$("#telephone").val()
  246. }
  247. closeMediaVideo(); //我的媒体信息
  248. $(".mui-content").show();
  249. $(".callHtml").hide();
  250. console.log(extenNum)
  251. // music.pause();
  252. userAgent.terminateSessions();
  253. }
  254. //注销
  255. function unReg() {
  256. closeMediaVideo();
  257. if(!superviseMan){
  258. console.log('注销----------->');
  259. userAgent.unregister(true);
  260. $(".registStatus").html("已注销")
  261. } else {
  262. window.location.href="superviseMan.html?extenNum="+$("#account").val()+"&telephone="+$("#telephone").val()
  263. }
  264. $(".mui-content").show();
  265. $(".callHtml").hide();
  266. $(".dropIcon").hide()
  267. $(".answerIcon").hide()
  268. }
  269. //开启本地摄像头
  270. function captureLocalMediaVideo() {
  271. navigator.getUserMedia({
  272. video: {
  273. deviceId: {
  274. exact: videoInputDevices[currentVideoIndex].deviceId
  275. }
  276. },
  277. audio: false
  278. }, function(stream) {
  279. nativeStream = stream;
  280. myVideoView.srcObject = stream;
  281. }, function(e) {
  282. alert('getUserMedia() error: ' + e.name);
  283. });
  284. }
  285. //获取本地媒体流
  286. function localMediaStream() {
  287. navigator.getUserMedia({
  288. video: {
  289. deviceId: {
  290. exact: videoInputDevices[currentVideoIndex].deviceId
  291. }
  292. },
  293. audio: true
  294. }, function(stream) {
  295. localStream = stream;
  296. if(callVideoState){extenBind()}
  297. if(dbCallVideoState){videoReqExten()}
  298. }, function(e) {
  299. alert('getUserMedia() error: ' + e.name);
  300. });
  301. }
  302. // 关闭摄像头
  303. function closeMediaVideo() {
  304. //console.log("1213")
  305. if(nativeStream){
  306. nativeStream.getTracks().forEach(function(track) {
  307. track.stop();
  308. });
  309. }
  310. if(localStream){
  311. localStream.getTracks().forEach(function(track) {
  312. track.stop();
  313. });
  314. }
  315. }
  316. //testStart()
  317. function testStart() {
  318. console.info("get input info: sip_uri = ", sip_uri_, " sip_password = ", sip_password_, " ws_uri = ", ws_uri_);
  319. var socket = new JsSIP.WebSocketInterface(ws_uri_);
  320. var configuration = {
  321. sockets: [socket],
  322. outbound_proxy_set: ws_uri_,
  323. uri: sip_uri_, //与用户代理关联的SIP URI(字符串)。这是您的提供商提供给您的SIP地址
  324. password: sip_password_, //SIP身份验证密码
  325. contact_uri: 'sip:1007@'+returnCitySN["cip"]+';transport=ws',
  326. //stun_servers: "stun1.l.google.com:19302",
  327. register: true, //指示启动时JsSIP用户代理是否应自动注册
  328. session_timers: false //启用会话计时器(根据RFC 4028)
  329. };
  330. userAgent = new JsSIP.UA(configuration);
  331. //JsSIP.debug.enable('JsSIP:*');
  332. JsSIP.debug.disable('JsSIP:*');
  333. //成功注册成功,data:Response JsSIP.IncomingResponse收到的SIP 2XX响应的实例
  334. userAgent.on('registered', function(data) {
  335. console.info("registered: ", data.response.status_code, ",", data.response.reason_phrase);
  336. registered();
  337. });
  338. //由于注册失败而被解雇,data:Response JsSIP.IncomingResponse接收到的SIP否定响应的实例,如果失败是由这样的响应的接收产生的,否则为空
  339. userAgent.on('registrationFailed', function(data) { });
  340. //1.在注册到期之前发射几秒钟。如果应用程序没有为这个事件设置任何监听器,JsSIP将像往常一样重新注册。
  341. // 2.如果应用程序订阅了这个事件,它负责ua.register()在registrationExpiring事件中调用(否则注册将过期)。
  342. // 3.此事件使应用程序有机会在重新注册之前执行异步操作。对于那些在REGISTER请求中的自定义SIP头中使用外部获得的“令牌”的环境很有用。
  343. userAgent.on('registrationExpiring', function() {
  344. //==console.warn("registrationExpiring");
  345. });
  346. //每次传输连接尝试均触发。
  347. userAgent.on('connecting ',function(data){
  348. console.log('每次传输连接尝试均触发6666'+data);
  349. })
  350. //建立传输连接时触发。
  351. userAgent.on('connected ',function(data){
  352. console.log('建立传输连接时触发666'+data);
  353. })
  354. //当传输连接尝试(或自动重新尝试)失败时触发。。
  355. userAgent.on('disconnected ',function(data){
  356. console.log('当传输连接尝试(或自动重新尝试)失败时触发。666'+data);
  357. })
  358. //为传入或传出会话/呼叫激发。data:
  359. // originator:'remote',新消息由远程对等方生成;'local',新消息由本地用户生成。
  360. // session:JsSIP.RTCSession 实例。
  361. // request:JsSIP.IncomingRequest收到的MESSAGE请求的实例;JsSIP.OutgoingRequest传出MESSAGE请求的实例
  362. userAgent.on('newRTCSession', function(data) {
  363. muteSession = data.session
  364. console.log(muteSession)
  365. console.info('onNewRTCSession: ', data);
  366. var originator = data.originator;
  367. var session = data.session;
  368. var request = data.request;
  369. if (data.originator == 'remote') { //incoming call
  370. console.log("电话呼入--1");
  371. console.info("incomingSession, answer the call");
  372. incomingSession = data.session;
  373. newRTCSession();
  374. //console.info("incomingSession, answer the call");
  375. //回答传入会话。此方法仅适用于传入会话。
  376. } else {
  377. //console.info("outgoingSession");
  378. outgoingSession = data.session;
  379. outgoingSession.on('connecting', function(data) {
  380. //console.info('onConnecting - ', data.request);
  381. currentSession = outgoingSession;
  382. outgoingSession = null;
  383. });
  384. }
  385. //接受呼叫时激发
  386. data.session.on('accepted', function(data) {
  387. console.info("onAccepted-----接受呼叫时激发");
  388. //console.info('onAccepted - ', data);
  389. if (data.originator == 'remote' && currentSession == null) {
  390. currentSession = incomingSession;
  391. incomingSession = null;
  392. //console.info("setCurrentSession - ", currentSession);
  393. }
  394. });
  395. //确认呼叫后激发
  396. data.session.on('confirmed', function(data) {
  397. console.info("confirmed-----确认呼叫后激发");
  398. //console.info('onConfirmed - ', data);
  399. $(".leftText").html("通话中");
  400. console.log(data)
  401. confirmed();
  402. if (data.originator == 'remote' && currentSession == null) {
  403. currentSession = incomingSession;
  404. incomingSession = null;
  405. //console.info("setCurrentSession - ", currentSession);
  406. }
  407. });
  408. //在将远程SDP传递到RTC引擎之前以及在发送本地SDP之前激发。此事件提供了修改传入和传出SDP的机制。
  409. data.session.on('sdp', function(data) {
  410. console.info("sdp-----在将远程SDP传递到RTC引擎之前以及在发送本地SDP之前激发");
  411. });
  412. //接收或生成对邀请请求的1XX SIP类响应(>100)时激发。该事件在SDP处理之前触发(如果存在),以便在需要时对其进行微调,甚至通过删除数据对象中响应参数的主体来删除它
  413. data.session.on('progress', function(data) {
  414. console.info("progress-----接收或生成对邀请请求的1XX SIP类响应(>100)时激发。该事件在SDP处理之前触发");
  415. //console.info('onProgress - ', data);
  416. if (data.originator == 'remote') {}
  417. });
  418. data.session.on('addstream', function(data) {
  419. console.info("addstream-----接收或生成对邀请请求的1XX SIP类响应(>100)时激发。该事件在SDP处理之前触发");
  420. yourVideoView.srcObject = data.stream;
  421. });
  422. //创建基础RTCPeerConnection后激发。应用程序有机会通过在peerconnection上添加RTCDataChannel或设置相应的事件侦听器来更改peerconnection。
  423. data.session.on('peerconnection', function(data) {
  424. console.info('onPeerconnection ----创建基础RTCPeerConnection后激发 ');
  425. // peerConnection.removeStream(peerConnection.getLocalStreams()[0]);
  426. // peerConnection.addLocalStream(stream);
  427. // pc.getSenders()[1].replaceTrack(videoTracks[0]);
  428. console.log(data.peerconnection.getSenders())
  429. data.peerconnection.onaddstream = function(ev) {
  430. //console.info('onaddstream from remote - ', ev); onaddtrack onaddstream
  431. //music.pause();
  432. peerconnection()
  433. callVideoFail = false
  434. console.log(ev.stream);
  435. yourVideoView.srcObject = ev.stream;
  436. };
  437. });
  438. });
  439. //为传入或传出消息请求激发。data:
  440. userAgent.on('newMessage', function(data) {
  441. if (data.originator == 'local') {
  442. //console.info('onNewMessage , OutgoingRequest - ', data.request);
  443. } else {
  444. //console.info('onNewMessage , IncomingRequest - ', data.request);
  445. }
  446. });
  447. console.info("call register");
  448. //连接到信令服务器,并恢复以前的状态,如果以前停止。重新开始时,如果UA配置中的参数设置为register:true,则向SIP域注册。
  449. userAgent.start();
  450. }
  451. // Register callbacks to desired call events
  452. var eventHandlers = {
  453. 'progress': function(e) {
  454. console.log('call is in progress');
  455. //music.play();
  456. },
  457. 'failed': function(e) {
  458. if(callVideoFail){
  459. setTimeout(function(){videoCall()},2000)
  460. }
  461. console.log('call failed: ', e);
  462. },
  463. 'ended': function(e) {
  464. console.log('call ended : ', e);
  465. unReg();
  466. },
  467. 'confirmed': function(e) {
  468. console.log('call confirmed');
  469. }
  470. };