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 8.1KB

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