您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

example.js 10.0KB

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