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

load-test-participant.js 8.1KB

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