Guest User

Untitled

a guest
Apr 21st, 2020
306
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'use strict';
  2.  
  3. /// SELECT DEVICES
  4. /// https://webrtc.github.io/samples/src/content/devices/input-output/
  5.  
  6. const audioInputSelect = document.querySelector('select#audioSource');
  7. const audioOutputSelect = document.querySelector('select#audioOutput');
  8. const videoSelect = document.querySelector('select#videoSource');
  9. const selectors = [audioInputSelect, audioOutputSelect, videoSelect];
  10.  
  11. /// This disables the selectfield for output if no output devices are found, seen on firefox for example
  12. audioOutputSelect.disabled = !('sinkId' in HTMLMediaElement.prototype);
  13.  
  14. /// This populates the all select fields for all possible devices
  15. function gotDevices(deviceInfos) {
  16.   // Handles being called several times to update labels. Preserve values.
  17.   const values = selectors.map(select => select.value);
  18.   selectors.forEach(select => {
  19.     while (select.firstChild) {
  20.       select.removeChild(select.firstChild);
  21.     }
  22.   });
  23.   for (let i = 0; i !== deviceInfos.length; ++i) {
  24.     const deviceInfo = deviceInfos[i];
  25.     const option = document.createElement('option');
  26.     option.value = deviceInfo.deviceId;
  27.     if (deviceInfo.kind === 'audioinput') {
  28.       option.text = deviceInfo.label || `microphone ${audioInputSelect.length + 1}`;
  29.       audioInputSelect.appendChild(option);
  30.     } else if (deviceInfo.kind === 'audiooutput') {
  31.       option.text = deviceInfo.label || `speaker ${audioOutputSelect.length + 1}`;
  32.       audioOutputSelect.appendChild(option);
  33.     } else if (deviceInfo.kind === 'videoinput') {
  34.       option.text = deviceInfo.label || `camera ${videoSelect.length + 1}`;
  35.       videoSelect.appendChild(option);
  36.     } else {
  37.       console.log('Some other kind of source/device: ', deviceInfo);
  38.     }
  39.   }
  40.   selectors.forEach((select, selectorIndex) => {
  41.     if (Array.prototype.slice.call(select.childNodes).some(n => n.value === values[selectorIndex])) {
  42.       select.value = values[selectorIndex];
  43.       //console.log(values[selectorIndex]);
  44.     }
  45.   });
  46. }
  47.  
  48. navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
  49.  
  50. // Attach audio output device to video element using device/sink ID.
  51. function attachSinkId(element, sinkId) {
  52.   if (typeof element.sinkId !== 'undefined') {
  53.     element.setSinkId(sinkId)
  54.         .then(() => {
  55.           console.log(`Success, audio output device attached: ${sinkId}`);
  56.         })
  57.         .catch(error => {
  58.           let errorMessage = error;
  59.           if (error.name === 'SecurityError') {
  60.             errorMessage = `You need to use HTTPS for selecting audio output device: ${error}`;
  61.           }
  62.           console.error(errorMessage);
  63.           // Jump back to first output device in the list as it's the default.
  64.           audioOutputSelect.selectedIndex = 0;
  65.         });
  66.   } else {
  67.     console.warn('Browser does not support output device selection.');
  68.   }
  69. }
  70.  
  71. /// Changes audio output by attaching a new sink id
  72. function changeAudioDestination() {
  73.   const audioDestination = audioOutputSelect.value;
  74.   attachSinkId(remoteVideo, audioDestination);
  75. }
  76.  
  77. /// General handle error, actually not very useful, can be probably removed
  78. function handleError(error) {
  79.   console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
  80. }
  81.  
  82. // Useful: https://webrtc.org/getting-started/media-devices
  83. /// Changes the device
  84. function ChangeDevice() {
  85.  
  86.   if (localStream) {
  87.     localStream.getTracks().forEach(track => {
  88.       track.stop();
  89.     });
  90.   }
  91.  
  92.   var audioSource = audioInputSelect.value;
  93.   var videoSource = videoSelect.value;
  94.  
  95.   console.log(videoSource);
  96.   console.log(audioSource);
  97.  
  98.   const newConstraints = {
  99.     audio: {deviceId: audioSource ? {exact: audioSource} : undefined},
  100.     video: {deviceId: videoSource ? {exact: videoSource} : undefined}
  101.   };
  102.  
  103.   navigator.mediaDevices.getUserMedia(newConstraints).then(gotStream).then(gotDevices).catch(handleError);
  104. }
  105.  
  106. audioInputSelect.onchange = ChangeDevice;
  107. audioOutputSelect.onchange = changeAudioDestination;
  108. videoSelect.onchange = ChangeDevice;
  109.  
  110. /// END SELECT DEVICES
  111.  
  112. var isChannelReady = false;
  113. var isInitiator = false;
  114. var isStarted = false;
  115. var localStream;
  116. var pc;
  117. var remoteStream;
  118. var turnReady;
  119.  
  120. var pcConfig = {
  121.   'iceServers': [
  122.     {
  123.       'urls': 'stun:stun.example.com:3478'
  124.     },
  125.     {
  126.       'urls': 'turn:turn.example.com:3478',
  127.       'credential': 'example',
  128.       'username': 'example'
  129.     }
  130.   ]
  131. };
  132.  
  133. // Set up audio and video regardless of what devices are present.
  134. var sdpConstraints = {
  135.   offerToReceiveAudio: true,
  136.   offerToReceiveVideo: true
  137. };
  138.  
  139. /////////////////////////////////////////////
  140.  
  141. /// Initial room name
  142. var room;
  143. if (window.location.href.indexOf("?room") > -1) {
  144.   room = window.location.href.split("?room=")[1];
  145. } else {
  146.   room = makeid(10);
  147.   window.location.href = window.location.href + "?room=" + room;
  148. }
  149.  
  150. var socket = io.connect();
  151.  
  152. if (room !== '') {
  153.   socket.emit('create or join', room);
  154.   console.log('Attempted to create or  join room', room);
  155. }
  156.  
  157. /*socket.on('disconnect', function(reason) {
  158.   console.log('Disconnected: ', reason);
  159. });*/
  160.  
  161. socket.on('created', function(room) {
  162.   console.log('Created room ' + room);
  163.   isInitiator = true;
  164. });
  165.  
  166. socket.on('full', function(room) {
  167.   console.log('Room ' + room + ' is full');
  168. });
  169.  
  170. socket.on('join', function (room){
  171.   console.log('Another peer made a request to join room ' + room);
  172.   console.log('This peer is the initiator of room ' + room + '!');
  173.   isChannelReady = true;
  174. });
  175.  
  176. socket.on('joined', function(room) {
  177.   console.log('joined: ' + room);
  178.   isChannelReady = true;
  179. });
  180.  
  181. socket.on('log', function(array) {
  182.   console.log.apply(console, array);
  183. });
  184.  
  185. ////////////////////////////////////////////////
  186.  
  187. function sendMessage(message) {
  188.   console.log('Client sending message: ', message);
  189.   socket.emit('message', message);
  190. }
  191.  
  192. // This client receives a message
  193. // Note message can be an object or a string (got user media)
  194. socket.on('message', function(message) {
  195.   console.log('Client received message:', message);
  196.   console.log('Client received message isStarted:', isStarted);
  197.  
  198.   if (message[0] === 'got user media') {
  199.     console.log('message was got user media');
  200.     maybeStart();
  201.   } else if (message[0].type === 'offer') {
  202.     if (!isInitiator && !isStarted) {
  203.       maybeStart();
  204.     }
  205.     pc.setRemoteDescription(new RTCSessionDescription(message[0]));
  206.     doAnswer();
  207.   } else if (message[0].type === 'answer' && isStarted) {
  208.     pc.setRemoteDescription(new RTCSessionDescription(message[0]));
  209.   } else if (message[0].type === 'candidate' && isStarted) {
  210.     var candidate = new RTCIceCandidate({
  211.       sdpMLineIndex: message[0].label,
  212.       candidate: message[0].candidate
  213.     });
  214.     pc.addIceCandidate(candidate);
  215.   } else if (message[0] === 'bye' && isStarted) {
  216.     handleRemoteHangup();
  217.   }
  218. });
  219.  
  220. ////////////////////////////////////////////////////
  221.  
  222. var localVideo = document.querySelector('#localVideo');
  223. var remoteVideo = document.querySelector('#remoteVideo');
  224.  
  225. // I added this block
  226. navigator.mediaDevices.getUserMedia = navigator.mediaDevices.getUserMedia
  227.   || navigator.mediaDevices.mozGetUserMedia || navigator.mediaDevices.webkitGetUserMedia;
  228.  
  229. var constraints = {
  230.   audio: true,
  231.   video: true
  232. };
  233.  
  234. navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
  235.  
  236. function gotStream(stream) {
  237.  
  238.   console.log('Adding local stream.');
  239.   localStream = stream;
  240.   localVideo.srcObject = stream;
  241.   sendMessage(['got user media', room]);
  242.   if (isInitiator) {
  243.     maybeStart();
  244.   }
  245.   return navigator.mediaDevices.enumerateDevices(); // I added this
  246.  
  247. }
  248.  
  249. if (location.hostname !== 'localhost') {
  250.   requestTurn(
  251.     'https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913'
  252.   );
  253. }
  254.  
  255. function maybeStart() {
  256.   console.log('>>>>>>> maybeStart() ', isStarted, localStream, isChannelReady);
  257.   if (!isStarted && typeof localStream !== 'undefined' && isChannelReady) {
  258.     console.log('>>>>>> creating peer connection');
  259.     createPeerConnection();
  260.     pc.addStream(localStream);
  261.     isStarted = true;
  262.     console.log('isInitiator', isInitiator);
  263.     if (isInitiator) {
  264.       doCall();
  265.     }
  266.   }
  267. }
  268.  
  269. // I removed this block
  270. //window.onbeforeunload = function() {
  271. //  sendMessage(['bye', room]);
  272. //};
  273.  
  274. /////////////////////////////////////////////////////////
  275.  
  276. function createPeerConnection() {
  277.   try {
  278.     pc = new RTCPeerConnection(pcConfig); // I added pcConfig, was null
  279.     pc.onicecandidate = handleIceCandidate;
  280.     pc.onaddstream = handleRemoteStreamAdded;
  281.     pc.onremovestream = handleRemoteStreamRemoved;
  282.     console.log('Created RTCPeerConnnection');
  283.   } catch (e) {
  284.     console.log('Failed to create PeerConnection, exception: ' + e.message);
  285.     alert('Cannot create RTCPeerConnection object.');
  286.     return;
  287.   }
  288. }
  289.  
  290. function handleIceCandidate(event) {
  291.   console.log('icecandidate event: ', event);
  292.   if (event.candidate) {
  293.     sendMessage([{
  294.       type: 'candidate',
  295.       label: event.candidate.sdpMLineIndex,
  296.       id: event.candidate.sdpMid,
  297.       candidate: event.candidate.candidate
  298.     }, room]);
  299.   } else {
  300.     console.log('End of candidates.');
  301.   }
  302. }
  303.  
  304. function handleCreateOfferError(event) {
  305.   console.log('createOffer() error: ', event);
  306. }
  307.  
  308. function doCall() {
  309.   console.log('Sending offer to peer');
  310.   pc.createOffer(setLocalAndSendMessage, handleCreateOfferError);
  311. }
  312.  
  313. function doAnswer() {
  314.   console.log('Sending answer to peer.');
  315.   pc.createAnswer().then(
  316.     setLocalAndSendMessage,
  317.     onCreateSessionDescriptionError
  318.   );
  319. }
  320.  
  321. function setLocalAndSendMessage(sessionDescription) {
  322.   pc.setLocalDescription(sessionDescription);
  323.   console.log('setLocalAndSendMessage sending message', sessionDescription);
  324.   sendMessage([sessionDescription, room]);
  325. }
  326.  
  327. function onCreateSessionDescriptionError(error) {
  328.   trace('Failed to create session description: ' + error.toString());
  329. }
  330.  
  331. function requestTurn(turnURL) {
  332.   var turnExists = false;
  333.   for (var i in pcConfig.iceServers) {
  334.     if (pcConfig.iceServers[i].urls.substr(0, 5) === 'turn:') {
  335.       console.log('Using turn: ' + pcConfig.iceServers[i].urls);
  336.       turnExists = true;
  337.       turnReady = true;
  338.       break;
  339.     }
  340.   }
  341.   if (!turnExists) {
  342.     console.log('Getting TURN server from ', turnURL);
  343.     // No TURN server. Get one from computeengineondemand.appspot.com:
  344.     var xhr = new XMLHttpRequest();
  345.     xhr.onreadystatechange = function() {
  346.       if (xhr.readyState === 4 && xhr.status === 200) {
  347.         var turnServer = JSON.parse(xhr.responseText);
  348.         console.log('Got TURN server: ', turnServer);
  349.         pcConfig.iceServers.push({
  350.           'urls': 'turn:' + turnServer.username + '@' + turnServer.turn,
  351.           'credential': turnServer.password
  352.         });
  353.         turnReady = true;
  354.       }
  355.     };
  356.     xhr.open('GET', turnURL, true);
  357.     xhr.send();
  358.   }
  359. }
  360.  
  361. function handleRemoteStreamAdded(event) {
  362.   console.log('Remote stream added.');
  363.   remoteStream = event.stream;
  364.   remoteVideo.srcObject = event.stream; // I changed form remoteStream to event.stream
  365. }
  366.  
  367. function handleRemoteStreamRemoved(event) {
  368.   console.log('Remote stream removed. Event: ', event);
  369. }
  370.  
  371. function hangup() {
  372.   console.log('Hanging up.');
  373.   stop();
  374.   sendMessage(['bye', room]);
  375. }
  376.  
  377. function handleRemoteHangup() {
  378.   console.log('Session terminated.');
  379.   stop();
  380.   isInitiator = false;
  381. }
  382.  
  383. function stop() {
  384.   isStarted = false;
  385.   //isChannelReady = false; // I added this
  386.   pc.close();
  387.   pc = null;
  388. }
  389.  
  390. /******************
  391.  * Make a random ID
  392.  ******************/
  393. function makeid(length) {
  394.   var result           = '';
  395.   var characters       = '0123456789';
  396.   var charactersLength = characters.length;
  397.   for ( var i = 0; i < length; i++ ) {
  398.      result += characters.charAt(Math.floor(Math.random() * charactersLength));
  399.   }
  400.   return result;
  401. }
RAW Paste Data