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.

load-test-participant.js 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* global $, config, JitsiMeetJS */
  2. import 'jquery';
  3. import { setConfigFromURLParams } from '../../react/features/base/config/functions';
  4. import { parseURLParams } from '../../react/features/base/util/parseURLParams';
  5. import { parseURIString } from '../../react/features/base/util/uri';
  6. setConfigFromURLParams(config, {}, {}, window.location);
  7. const params = parseURLParams(window.location, false, 'hash');
  8. const { isHuman = false } = params;
  9. const {
  10. localAudio = config.startWithAudioMuted !== true,
  11. localVideo = config.startWithVideoMuted !== true,
  12. remoteVideo = isHuman,
  13. remoteAudio = isHuman,
  14. autoPlayVideo = config.testing.noAutoPlayVideo !== true
  15. } = params;
  16. const { room: roomName } = parseURIString(window.location.toString());
  17. let connection = null;
  18. let isJoined = false;
  19. let room = null;
  20. let numParticipants = 1;
  21. let localTracks = [];
  22. const remoteTracks = {};
  23. let maxFrameHeight = 0;
  24. window.APP = {
  25. conference: {
  26. getStats() {
  27. return room.connectionQuality.getStats();
  28. },
  29. getConnectionState() {
  30. return room && room.getConnectionState();
  31. }
  32. },
  33. get room() {
  34. return room;
  35. },
  36. get connection() {
  37. return connection;
  38. },
  39. get numParticipants() {
  40. return numParticipants;
  41. },
  42. get localTracks() {
  43. return localTracks;
  44. },
  45. get remoteTracks() {
  46. return remoteTracks;
  47. },
  48. get params() {
  49. return {
  50. roomName,
  51. localAudio,
  52. localVideo,
  53. remoteVideo,
  54. remoteAudio,
  55. autoPlayVideo
  56. };
  57. }
  58. };
  59. /**
  60. * Simple emulation of jitsi-meet's screen layout behavior
  61. */
  62. function updateMaxFrameHeight() {
  63. let newMaxFrameHeight;
  64. if (numParticipants <= 2) {
  65. newMaxFrameHeight = 720;
  66. } else if (numParticipants <= 4) {
  67. newMaxFrameHeight = 360;
  68. } else {
  69. newMaxFrameHeight = 180;
  70. }
  71. if (room && maxFrameHeight !== newMaxFrameHeight) {
  72. maxFrameHeight = newMaxFrameHeight;
  73. room.setReceiverVideoConstraint(maxFrameHeight);
  74. }
  75. }
  76. /**
  77. *
  78. */
  79. function setNumberOfParticipants() {
  80. $('#participants').text(numParticipants);
  81. updateMaxFrameHeight();
  82. }
  83. /**
  84. * Handles local tracks.
  85. * @param tracks Array with JitsiTrack objects
  86. */
  87. function onLocalTracks(tracks = []) {
  88. localTracks = tracks;
  89. for (let i = 0; i < localTracks.length; i++) {
  90. if (localTracks[i].getType() === 'video') {
  91. $('body').append(`<video ${autoPlayVideo ? 'autoplay="1" ' : ''}id='localVideo${i}' />`);
  92. localTracks[i].attach($(`#localVideo${i}`)[0]);
  93. } else {
  94. $('body').append(
  95. `<audio autoplay='1' muted='true' id='localAudio${i}' />`);
  96. localTracks[i].attach($(`#localAudio${i}`)[0]);
  97. }
  98. if (isJoined) {
  99. room.addTrack(localTracks[i]);
  100. }
  101. }
  102. }
  103. /**
  104. * Handles remote tracks
  105. * @param track JitsiTrack object
  106. */
  107. function onRemoteTrack(track) {
  108. if (track.isLocal()
  109. || (track.getType() === 'video' && !remoteVideo) || (track.getType() === 'audio' && !remoteAudio)) {
  110. return;
  111. }
  112. const participant = track.getParticipantId();
  113. if (!remoteTracks[participant]) {
  114. remoteTracks[participant] = [];
  115. }
  116. const idx = remoteTracks[participant].push(track);
  117. const id = participant + track.getType() + idx;
  118. if (track.getType() === 'video') {
  119. $('body').append(`<video autoplay='1' id='${id}' />`);
  120. } else {
  121. $('body').append(`<audio autoplay='1' id='${id}' />`);
  122. }
  123. track.attach($(`#${id}`)[0]);
  124. }
  125. /**
  126. * That function is executed when the conference is joined
  127. */
  128. function onConferenceJoined() {
  129. isJoined = true;
  130. }
  131. /**
  132. *
  133. * @param id
  134. */
  135. function onUserLeft(id) {
  136. numParticipants--;
  137. setNumberOfParticipants();
  138. if (!remoteTracks[id]) {
  139. return;
  140. }
  141. const tracks = remoteTracks[id];
  142. for (let i = 0; i < tracks.length; i++) {
  143. const container = $(`#${id}${tracks[i].getType()}${i + 1}`)[0];
  144. if (container) {
  145. tracks[i].detach(container);
  146. container.parentElement.removeChild(container);
  147. }
  148. }
  149. }
  150. /**
  151. * That function is called when connection is established successfully
  152. */
  153. function onConnectionSuccess() {
  154. room = connection.initJitsiConference(roomName.toLowerCase(), config);
  155. room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
  156. room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
  157. room.on(JitsiMeetJS.events.conference.USER_JOINED, id => {
  158. numParticipants++;
  159. setNumberOfParticipants();
  160. remoteTracks[id] = [];
  161. });
  162. room.on(JitsiMeetJS.events.conference.USER_LEFT, onUserLeft);
  163. const devices = [];
  164. if (localVideo) {
  165. devices.push('video');
  166. }
  167. if (localAudio) {
  168. devices.push('audio');
  169. }
  170. if (devices.length > 0) {
  171. JitsiMeetJS.createLocalTracks({ devices })
  172. .then(onLocalTracks)
  173. .then(() => {
  174. room.join();
  175. })
  176. .catch(error => {
  177. throw error;
  178. });
  179. } else {
  180. room.join();
  181. }
  182. updateMaxFrameHeight();
  183. }
  184. /**
  185. * This function is called when the connection fail.
  186. */
  187. function onConnectionFailed() {
  188. console.error('Connection Failed!');
  189. }
  190. /**
  191. * This function is called when we disconnect.
  192. */
  193. function disconnect() {
  194. console.log('disconnect!');
  195. connection.removeEventListener(
  196. JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
  197. onConnectionSuccess);
  198. connection.removeEventListener(
  199. JitsiMeetJS.events.connection.CONNECTION_FAILED,
  200. onConnectionFailed);
  201. connection.removeEventListener(
  202. JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
  203. disconnect);
  204. }
  205. /**
  206. *
  207. */
  208. function unload() {
  209. for (let i = 0; i < localTracks.length; i++) {
  210. localTracks[i].dispose();
  211. }
  212. room.leave();
  213. connection.disconnect();
  214. }
  215. $(window).bind('beforeunload', unload);
  216. $(window).bind('unload', unload);
  217. JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
  218. JitsiMeetJS.init(config);
  219. config.serviceUrl = config.bosh = `${config.websocket || config.bosh}?room=${roomName.toLowerCase()}`;
  220. connection = new JitsiMeetJS.JitsiConnection(null, null, config);
  221. connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED, onConnectionSuccess);
  222. connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_FAILED, onConnectionFailed);
  223. connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED, disconnect);
  224. connection.connect();