index.html 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <link rel="stylesheet" type="text/css" href="./css/index.css" />
  8. <title>IM通话</title>
  9. <style>
  10. html, body {
  11. height: 100%;
  12. }
  13. body {
  14. margin: 0;
  15. }
  16. video {
  17. width: 100%;
  18. height: 100%;
  19. position: absolute;
  20. left: 0;
  21. top: 0;
  22. z-index: -1;
  23. }
  24. </style>
  25. </head>
  26. <body>
  27. <video class="Bvideo" id="Big_video" autoplay></video>
  28. <!-- <video class="Svideo" id="sm_video" preload muted autoplay onclick="Svideoselc()"></video> -->
  29. <!-- <audio id="my_audio" autoplay></audio> -->
  30. <div class="bottomView" style="width: 100%;">
  31. <div class="contentColumnC">
  32. <img class="guadanImg" style="margin-top: 5px;" src="./img/guaduandd.png" alt="" onclick="guaduan()"/>
  33. <div class="contentInRowC" style="width: 100%;margin-top: 10px;">
  34. <div id="markNote"></div>
  35. <img class="calling" src="./img/loading2.gif" alt="" />
  36. </div>
  37. </div>
  38. </div>
  39. </body>
  40. <script type="text/javascript" src="./js/lib/uniwebviewsdk.js"></script>
  41. <script>
  42. let localStream = null;
  43. let localCall = 0;
  44. let localCandidata=null;
  45. let peer = null;
  46. let video=null;
  47. //const Big_video = document.getElementById('Big_video');
  48. // const sm_video = document.getElementById('sm_video');
  49. // const my_audio = document.getElementById('my_audio');
  50. const markNote = document.getElementById('markNote');
  51. //====================================================
  52. // function Bvideoselc(){
  53. // if(localStream!=null){
  54. // //Big_video.srcObject =localStream;
  55. // Big_video.setAttribute('autoplay', true); /* THIS */
  56. // }
  57. // }
  58. function Svideoselc(){
  59. if(localStream!=null){
  60. //sm_video.srcObject =localStream;
  61. sm_video.setAttribute('autoplay', true); /* THIS */
  62. }
  63. }
  64. function guaduan(){
  65. uni.postMessage({
  66. data: {
  67. data:'', // 回传
  68. type:88
  69. },
  70. });
  71. }
  72. //====================================================
  73. function appAct (obj) {
  74. if(obj.type==1){//主动发起im通话
  75. localCall=1;
  76. startWebRct(obj.type);
  77. markNote.innerHTML='拨打中'
  78. }
  79. else if(obj.type==2){//收到推送消息
  80. if(localCall==1){
  81. markNote.innerHTML='接通中'
  82. RCremoteData(obj.payload);
  83. }
  84. else{
  85. RCstartWebRct(obj.payload);
  86. }
  87. }
  88. else if(obj.type==3){//收到candidate
  89. markNote.innerHTML='接通中'
  90. for(var i=0;i<obj.payload.length;i++){
  91. peer.addIceCandidate(obj.payload[i]);
  92. }
  93. if(localCall!=1){
  94. uni.postMessage({
  95. data: {
  96. data:localCandidata, //应答方回应candidate
  97. type:3
  98. },
  99. });
  100. }
  101. }
  102. }
  103. async function startCapture(displayMediaOptions) {
  104. try {
  105. localStream = await navigator.mediaDevices.getUserMedia(displayMediaOptions);
  106. // var otherVideos = document.querySelector('#Big_video');
  107. // otherVideos.srcObject = localStream;
  108. uni.postMessage({
  109. data: {
  110. data:'', // 回传
  111. type:99
  112. },
  113. });
  114. } catch(err) {
  115. console.error(err);
  116. }
  117. }
  118. async function startWebRct(type){
  119. peer = new RTCPeerConnection(
  120. {
  121. iceServers:[
  122. {
  123. urls:'stun:stun.l.google.com:19302',
  124. }
  125. ]
  126. }
  127. );
  128. //添加本地音视频
  129. localStream.getTracks().forEach((track) => {
  130. peer.addTrack(track, localStream)
  131. });
  132. //创建本地offer
  133. const offer = peer.createOffer({
  134. offerToReceiveAudio:1,
  135. offerToReceiveVideo:1
  136. });
  137. //记录本地offer
  138. offer.then(value => {
  139. peer.setLocalDescription(value);
  140. uni.postMessage({
  141. data: {
  142. data:value, // 回传并推送offer
  143. type:2
  144. },
  145. });
  146. }).catch(error => {
  147. });
  148. peer.oniceconnectionstatechange = function (ev) {
  149. if(peer.connectionState=="closed"){
  150. markNote.innerHTML='结束通话'
  151. }
  152. if(peer.connectionState=="connected"){
  153. markNote.innerHTML='已接通'
  154. }
  155. if(peer.connectionState=="connecting"){
  156. markNote.innerHTML='连接中'
  157. }
  158. if(peer.connectionState=="disconnected"){
  159. markNote.innerHTML='对方挂断'
  160. }
  161. };
  162. localCandidata=[]
  163. peer.onicecandidate = function (event) {
  164. if (event.candidate){
  165. localCandidata.push(event.candidate);
  166. }
  167. }
  168. startCommunicate();
  169. }
  170. async function RCremoteData(rcData){//收到remoteAnswer
  171. //记录远端offer
  172. await peer.setRemoteDescription(rcData)
  173. uni.postMessage({
  174. data: {
  175. data:localCandidata, // 发起方先发candidate
  176. type:3
  177. },
  178. });
  179. }
  180. function startCommunicate(){
  181. peer.ontrack = (e) => {
  182. if(e.streams[0]){
  183. //var otherVideos = document.querySelector('#my_audio');
  184. var otherVideos = document.querySelector('#Big_video');
  185. otherVideos.srcObject = e.streams[0];
  186. //markNote.innerHTML=e.streams[0];
  187. //Big_video.srcObject=e.streams[0];
  188. //Big_video.setAttribute('autoplay', true); /* THIS */
  189. }
  190. // sm_video.srcObject =localStream;
  191. // sm_video.setAttribute('autoplay', true); /* THIS */
  192. // if(video!=null){
  193. // video.srcObject = e.streams[0];
  194. // video.setAttribute('autoplay', true); /* THIS */
  195. // }
  196. // else{
  197. // video = document.createElement("video");
  198. // video.srcObject = e.streams[0];
  199. // video.setAttribute('autoplay', true); /* THIS */
  200. // document.body.appendChild(video);
  201. // }
  202. }
  203. }
  204. async function RCstartWebRct(payload){
  205. peer = new RTCPeerConnection(
  206. {
  207. iceServers:[
  208. {
  209. urls:'stun:stun.l.google.com:19302',
  210. }
  211. ]
  212. }
  213. );
  214. //添加本地音视频
  215. localStream.getTracks().forEach((track) => {
  216. peer.addTrack(track, localStream)
  217. })
  218. localCandidata=[];
  219. peer.onicecandidate = function (event) {
  220. if (event.candidate){
  221. //let strcandidate=JSON.stringify(event.candidate);
  222. localCandidata.push(event.candidate);
  223. }
  224. }
  225. startCommunicate();
  226. //记录远端offer
  227. await peer.setRemoteDescription(payload)
  228. const remoteAnswer = await peer.createAnswer();
  229. //记录本地offer
  230. await peer.setLocalDescription(remoteAnswer);
  231. //推送remoteAnswer
  232. uni.postMessage({
  233. data: {
  234. data:remoteAnswer, // 回传并推送offer
  235. type:2
  236. },
  237. });
  238. }
  239. function initRtc() {
  240. markNote.innerHTML='IM通话'
  241. setTimeout(() => {
  242. startCapture({ video: true, audio: true});
  243. //startCapture({audio: true});
  244. }, 1000)
  245. return;
  246. }
  247. function releaseTack(){
  248. if(peer){
  249. peer.close();
  250. }
  251. }
  252. window.onload=initRtc;
  253. window.onunload=releaseTack;
  254. </script>
  255. </html>