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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. // Whether to create local audio even if muted
  16. autoCreateLocalAudio = config.testing.noAutoLocalAudio !== true
  17. } = params;
  18. const { room: roomName } = parseURIString(window.location.toString());
  19. let connection = null;
  20. let room = null;
  21. let numParticipants = 1;
  22. let localTracks = [];
  23. const remoteTracks = {};
  24. let maxFrameHeight = 0;
  25. window.APP = {
  26. conference: {
  27. getStats() {
  28. return room.connectionQuality.getStats();
  29. },
  30. getConnectionState() {
  31. return room && room.getConnectionState();
  32. }
  33. },
  34. get room() {
  35. return room;
  36. },
  37. get connection() {
  38. return connection;
  39. },
  40. get numParticipants() {
  41. return numParticipants;
  42. },
  43. get localTracks() {
  44. return localTracks;
  45. },
  46. get remoteTracks() {
  47. return remoteTracks;
  48. },
  49. get params() {
  50. return {
  51. roomName,
  52. localAudio,
  53. localVideo,
  54. remoteVideo,
  55. remoteAudio,
  56. autoPlayVideo
  57. };
  58. }
  59. };
  60. /**
  61. * Simple emulation of jitsi-meet's screen layout behavior
  62. */
  63. function updateMaxFrameHeight() {
  64. let newMaxFrameHeight;
  65. if (numParticipants <= 2) {
  66. newMaxFrameHeight = 720;
  67. } else if (numParticipants <= 4) {
  68. newMaxFrameHeight = 360;
  69. } else {
  70. newMaxFrameHeight = 180;
  71. }
  72. if (room && maxFrameHeight !== newMaxFrameHeight) {
  73. maxFrameHeight = newMaxFrameHeight;
  74. room.setReceiverVideoConstraint(maxFrameHeight);
  75. }
  76. }
  77. /**
  78. *
  79. */
  80. function setNumberOfParticipants() {
  81. $('#participants').text(numParticipants);
  82. updateMaxFrameHeight();
  83. }
  84. /**
  85. * Handles local tracks.
  86. * @param tracks Array with JitsiTrack objects
  87. */
  88. function onLocalTracks(tracks = []) {
  89. localTracks = tracks;
  90. for (let i = 0; i < localTracks.length; i++) {
  91. if (localTracks[i].getType() === 'video') {
  92. $('body').append(`<video ${autoPlayVideo ? 'autoplay="1" ' : ''}id='localVideo${i}' />`);
  93. localTracks[i].attach($(`#localVideo${i}`)[0]);
  94. } else {
  95. if (!localAudio) {
  96. localTracks[i].mute();
  97. }
  98. $('body').append(
  99. `<audio autoplay='1' muted='true' id='localAudio${i}' />`);
  100. localTracks[i].attach($(`#localAudio${i}`)[0]);
  101. }
  102. room.addTrack(localTracks[i]);
  103. }
  104. }
  105. /**
  106. * Handles remote tracks
  107. * @param track JitsiTrack object
  108. */
  109. function onRemoteTrack(track) {
  110. if (track.isLocal()
  111. || (track.getType() === 'video' && !remoteVideo) || (track.getType() === 'audio' && !remoteAudio)) {
  112. return;
  113. }
  114. const participant = track.getParticipantId();
  115. if (!remoteTracks[participant]) {
  116. remoteTracks[participant] = [];
  117. }
  118. const idx = remoteTracks[participant].push(track);
  119. const id = participant + track.getType() + idx;
  120. if (track.getType() === 'video') {
  121. $('body').append(`<video autoplay='1' id='${id}' />`);
  122. } else {
  123. $('body').append(`<audio autoplay='1' id='${id}' />`);
  124. }
  125. track.attach($(`#${id}`)[0]);
  126. }
  127. /**
  128. * That function is executed when the conference is joined
  129. */
  130. function onConferenceJoined() {
  131. console.log('Conference joined');
  132. }
  133. /**
  134. * Handles start muted events, when audio and/or video are muted due to
  135. * startAudioMuted or startVideoMuted policy.
  136. */
  137. function onStartMuted() {
  138. // Give it some time, as it may be currently in the process of muting
  139. setTimeout(() => {
  140. const localAudioTrack = room.getLocalAudioTrack();
  141. if (localAudio && localAudioTrack && localAudioTrack.isMuted()) {
  142. localAudioTrack.unmute();
  143. }
  144. const localVideoTrack = room.getLocalVideoTrack();
  145. if (localVideo && localVideoTrack && localVideoTrack.isMuted()) {
  146. localVideoTrack.unmute();
  147. }
  148. }, 2000);
  149. }
  150. /**
  151. *
  152. * @param id
  153. */
  154. function onUserLeft(id) {
  155. numParticipants--;
  156. setNumberOfParticipants();
  157. if (!remoteTracks[id]) {
  158. return;
  159. }
  160. const tracks = remoteTracks[id];
  161. for (let i = 0; i < tracks.length; i++) {
  162. const container = $(`#${id}${tracks[i].getType()}${i + 1}`)[0];
  163. if (container) {
  164. tracks[i].detach(container);
  165. container.parentElement.removeChild(container);
  166. }
  167. }
  168. }
  169. /**
  170. * That function is called when connection is established successfully
  171. */
  172. function onConnectionSuccess() {
  173. room = connection.initJitsiConference(roomName.toLowerCase(), config);
  174. room.on(JitsiMeetJS.events.conference.STARTED_MUTED, onStartMuted);
  175. room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
  176. room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
  177. room.on(JitsiMeetJS.events.conference.USER_JOINED, id => {
  178. numParticipants++;
  179. setNumberOfParticipants();
  180. remoteTracks[id] = [];
  181. });
  182. room.on(JitsiMeetJS.events.conference.USER_LEFT, onUserLeft);
  183. const devices = [];
  184. if (localVideo) {
  185. devices.push('video');
  186. }
  187. if (autoCreateLocalAudio) {
  188. devices.push('audio');
  189. }
  190. if (devices.length > 0) {
  191. JitsiMeetJS.createLocalTracks({ devices })
  192. .then(onLocalTracks)
  193. .then(() => {
  194. room.join();
  195. })
  196. .catch(error => {
  197. throw error;
  198. });
  199. } else {
  200. room.join();
  201. }
  202. updateMaxFrameHeight();
  203. }
  204. /**
  205. * This function is called when the connection fail.
  206. */
  207. function onConnectionFailed() {
  208. console.error('Connection Failed!');
  209. }
  210. /**
  211. * This function is called when we disconnect.
  212. */
  213. function disconnect() {
  214. console.log('disconnect!');
  215. connection.removeEventListener(
  216. JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
  217. onConnectionSuccess);
  218. connection.removeEventListener(
  219. JitsiMeetJS.events.connection.CONNECTION_FAILED,
  220. onConnectionFailed);
  221. connection.removeEventListener(
  222. JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
  223. disconnect);
  224. }
  225. /**
  226. *
  227. */
  228. function unload() {
  229. for (let i = 0; i < localTracks.length; i++) {
  230. localTracks[i].dispose();
  231. }
  232. room.leave();
  233. connection.disconnect();
  234. }
  235. $(window).bind('beforeunload', unload);
  236. $(window).bind('unload', unload);
  237. JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
  238. JitsiMeetJS.init(config);
  239. config.serviceUrl = config.bosh = `${config.websocket || config.bosh}?room=${roomName.toLowerCase()}`;
  240. if (config.websocketKeepAliveUrl) {
  241. config.websocketKeepAliveUrl += `?room=${roomName.toLowerCase()}`;
  242. }
  243. connection = new JitsiMeetJS.JitsiConnection(null, null, config);
  244. connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED, onConnectionSuccess);
  245. connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_FAILED, onConnectionFailed);
  246. connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED, disconnect);
  247. connection.connect();