You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

example.js 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /* global $, JitsiMeetJS */
  2. const options = {
  3. hosts: {
  4. domain: 'jitsi-meet.example.com',
  5. muc: 'conference.jitsi-meet.example.com' // FIXME: use XEP-0030
  6. },
  7. bosh: '//jitsi-meet.example.com/http-bind', // FIXME: use xep-0156 for that
  8. clientNode: 'http://jitsi.org/jitsimeet' // The name of client node advertised in XEP-0115 'c' stanza
  9. };
  10. const confOptions = {
  11. openSctp: true
  12. };
  13. let connection = null;
  14. let isJoined = false;
  15. let room = null;
  16. let localTracks = [];
  17. const remoteTracks = {};
  18. /**
  19. * Handles local tracks.
  20. * @param tracks Array with JitsiTrack objects
  21. */
  22. function onLocalTracks(tracks) {
  23. localTracks = tracks;
  24. for (let i = 0; i < localTracks.length; i++) {
  25. localTracks[i].addEventListener(
  26. JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
  27. audioLevel => console.log(`Audio Level local: ${audioLevel}`));
  28. localTracks[i].addEventListener(
  29. JitsiMeetJS.events.track.TRACK_MUTE_CHANGED,
  30. () => console.log('local track muted'));
  31. localTracks[i].addEventListener(
  32. JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED,
  33. () => console.log('local track stoped'));
  34. localTracks[i].addEventListener(
  35. JitsiMeetJS.events.track.TRACK_AUDIO_OUTPUT_CHANGED,
  36. deviceId =>
  37. console.log(
  38. `track audio output device was changed to ${deviceId}`));
  39. if (localTracks[i].getType() == 'video') {
  40. $('body').append(`<video autoplay='1' id='localVideo${i}' />`);
  41. localTracks[i].attach($(`#localVideo${i}`)[0]);
  42. } else {
  43. $('body').append(`<audio autoplay='1' muted='true' id='localAudio${i}' />`);
  44. localTracks[i].attach($(`#localAudio${i}`)[0]);
  45. }
  46. if (isJoined) {
  47. room.addTrack(localTracks[i]);
  48. }
  49. }
  50. }
  51. /**
  52. * Handles remote tracks
  53. * @param track JitsiTrack object
  54. */
  55. function onRemoteTrack(track) {
  56. if (track.isLocal()) {
  57. return;
  58. }
  59. const participant = track.getParticipantId();
  60. if (!remoteTracks[participant]) {
  61. remoteTracks[participant] = [];
  62. }
  63. const idx = remoteTracks[participant].push(track);
  64. track.addEventListener(
  65. JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
  66. audioLevel => console.log(`Audio Level remote: ${audioLevel}`));
  67. track.addEventListener(
  68. JitsiMeetJS.events.track.TRACK_MUTE_CHANGED,
  69. () => console.log('remote track muted'));
  70. track.addEventListener(
  71. JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED,
  72. () => console.log('remote track stoped'));
  73. track.addEventListener(JitsiMeetJS.events.track.TRACK_AUDIO_OUTPUT_CHANGED,
  74. deviceId =>
  75. console.log(
  76. `track audio output device was changed to ${deviceId}`));
  77. const id = participant + track.getType() + idx;
  78. if (track.getType() == 'video') {
  79. $('body').append(`<video autoplay='1' id='${participant}video${idx}' />`);
  80. } else {
  81. $('body').append(`<audio autoplay='1' id='${participant}audio${idx}' />`);
  82. }
  83. track.attach($(`#${id}`)[0]);
  84. }
  85. /**
  86. * That function is executed when the conference is joined
  87. */
  88. function onConferenceJoined() {
  89. console.log('conference joined!');
  90. isJoined = true;
  91. for (let i = 0; i < localTracks.length; i++) {
  92. room.addTrack(localTracks[i]);
  93. }
  94. }
  95. function onUserLeft(id) {
  96. console.log('user left');
  97. if (!remoteTracks[id]) {
  98. return;
  99. }
  100. const tracks = remoteTracks[id];
  101. for (let i = 0; i < tracks.length; i++) {
  102. tracks[i].detach($(`#${id}${tracks[i].getType()}`));
  103. }
  104. }
  105. /**
  106. * That function is called when connection is established successfully
  107. */
  108. function onConnectionSuccess() {
  109. room = connection.initJitsiConference('conference', confOptions);
  110. room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
  111. room.on(JitsiMeetJS.events.conference.TRACK_REMOVED, track => {
  112. console.log(`track removed!!!${track}`);
  113. });
  114. room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
  115. room.on(JitsiMeetJS.events.conference.USER_JOINED, id => {
  116. console.log('user join');
  117. remoteTracks[id] = [];
  118. });
  119. room.on(JitsiMeetJS.events.conference.USER_LEFT, onUserLeft);
  120. room.on(JitsiMeetJS.events.conference.TRACK_MUTE_CHANGED, track => {
  121. console.log(`${track.getType()} - ${track.isMuted()}`);
  122. });
  123. room.on(JitsiMeetJS.events.conference.DISPLAY_NAME_CHANGED, (userID, displayName) => {
  124. console.log(`${userID} - ${displayName}`);
  125. });
  126. room.on(JitsiMeetJS.events.conference.TRACK_AUDIO_LEVEL_CHANGED,
  127. (userID, audioLevel) => {
  128. console.log(`${userID} - ${audioLevel}`);
  129. });
  130. room.on(JitsiMeetJS.events.conference.RECORDER_STATE_CHANGED, () => {
  131. console.log(`${room.isRecordingSupported()} - ${
  132. room.getRecordingState()} - ${
  133. room.getRecordingURL()}`);
  134. });
  135. room.on(JitsiMeetJS.events.conference.PHONE_NUMBER_CHANGED, () => {
  136. console.log(
  137. `${room.getPhoneNumber()} - ${
  138. room.getPhonePin()}`);
  139. });
  140. room.join();
  141. }
  142. /**
  143. * This function is called when the connection fail.
  144. */
  145. function onConnectionFailed() {
  146. console.error('Connection Failed!');
  147. }
  148. /**
  149. * This function is called when the connection fail.
  150. */
  151. function onDeviceListChanged(devices) {
  152. console.info('current devices', devices);
  153. }
  154. /**
  155. * This function is called when we disconnect.
  156. */
  157. function disconnect() {
  158. console.log('disconnect!');
  159. connection.removeEventListener(JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED, onConnectionSuccess);
  160. connection.removeEventListener(JitsiMeetJS.events.connection.CONNECTION_FAILED, onConnectionFailed);
  161. connection.removeEventListener(JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED, disconnect);
  162. }
  163. function unload() {
  164. for (let i = 0; i < localTracks.length; i++) {
  165. localTracks[i].stop();
  166. }
  167. room.leave();
  168. connection.disconnect();
  169. }
  170. let isVideo = true;
  171. function switchVideo() { // eslint-disable-line no-unused-vars
  172. isVideo = !isVideo;
  173. if (localTracks[1]) {
  174. localTracks[1].dispose();
  175. localTracks.pop();
  176. }
  177. JitsiMeetJS.createLocalTracks({ devices: isVideo ? [ 'video' ] : [ 'desktop' ] })
  178. .then(tracks => {
  179. localTracks.push(tracks[0]);
  180. localTracks[1].addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED,
  181. () => {
  182. console.log('local track muted');
  183. });
  184. localTracks[1].addEventListener(JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED,
  185. () => {
  186. console.log('local track stoped');
  187. });
  188. localTracks[1].attach($('#localVideo1')[0]);
  189. room.addTrack(localTracks[1]);
  190. })
  191. .catch(error => console.log(error));
  192. }
  193. function changeAudioOutput(selected) { // eslint-disable-line no-unused-vars
  194. JitsiMeetJS.mediaDevices.setAudioOutputDevice(selected.value);
  195. }
  196. $(window).bind('beforeunload', unload);
  197. $(window).bind('unload', unload);
  198. // JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
  199. const initOptions = {
  200. disableAudioLevels: true,
  201. // The ID of the jidesha extension for Chrome.
  202. desktopSharingChromeExtId: 'mbocklcggfhnbahlnepmldehdhpjfcjp',
  203. // Whether desktop sharing should be disabled on Chrome.
  204. desktopSharingChromeDisabled: false,
  205. // The media sources to use when using screen sharing with the Chrome
  206. // extension.
  207. desktopSharingChromeSources: [ 'screen', 'window' ],
  208. // Required version of Chrome extension
  209. desktopSharingChromeMinExtVersion: '0.1',
  210. // The ID of the jidesha extension for Firefox. If null, we assume that no
  211. // extension is required.
  212. desktopSharingFirefoxExtId: null,
  213. // Whether desktop sharing should be disabled on Firefox.
  214. desktopSharingFirefoxDisabled: true,
  215. // The maximum version of Firefox which requires a jidesha extension.
  216. // Example: if set to 41, we will require the extension for Firefox versions
  217. // up to and including 41. On Firefox 42 and higher, we will run without the
  218. // extension.
  219. // If set to -1, an extension will be required for all versions of Firefox.
  220. desktopSharingFirefoxMaxVersionExtRequired: -1,
  221. // The URL to the Firefox extension for desktop sharing.
  222. desktopSharingFirefoxExtensionURL: null
  223. };
  224. JitsiMeetJS.init(initOptions)
  225. .then(() => {
  226. connection = new JitsiMeetJS.JitsiConnection(null, null, options);
  227. connection.addEventListener(
  228. JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
  229. onConnectionSuccess);
  230. connection.addEventListener(
  231. JitsiMeetJS.events.connection.CONNECTION_FAILED,
  232. onConnectionFailed);
  233. connection.addEventListener(
  234. JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
  235. disconnect);
  236. JitsiMeetJS.mediaDevices.addEventListener(
  237. JitsiMeetJS.events.mediaDevices.DEVICE_LIST_CHANGED,
  238. onDeviceListChanged);
  239. connection.connect();
  240. JitsiMeetJS.createLocalTracks({ devices: [ 'audio', 'video' ] })
  241. .then(onLocalTracks)
  242. .catch(error => {
  243. throw error;
  244. });
  245. })
  246. .catch(error => console.log(error));
  247. if (JitsiMeetJS.mediaDevices.isDeviceChangeAvailable('output')) {
  248. JitsiMeetJS.mediaDevices.enumerateDevices(devices => {
  249. const audioOutputDevices = devices.filter(d => d.kind === 'audiooutput');
  250. if (audioOutputDevices.length > 1) {
  251. $('#audioOutputSelect').html(
  252. audioOutputDevices.map(d => `<option value="${d.deviceId}">${d.label}</option>`).join('\n')
  253. );
  254. $('#audioOutputSelectWrapper').show();
  255. }
  256. });
  257. }