Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

middleware.js 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // @flow
  2. import { jitsiLocalStorage } from '@jitsi/js-utils';
  3. import { getAmplitudeIdentity } from '../analytics';
  4. import { CONFERENCE_UNIQUE_ID_SET, E2E_RTT_CHANGED, CONFERENCE_TIMESTAMP_CHANGED, getConferenceOptions, getRoomName }
  5. from '../base/conference';
  6. import { LIB_WILL_INIT } from '../base/lib-jitsi-meet/actionTypes';
  7. import { DOMINANT_SPEAKER_CHANGED, getLocalParticipant } from '../base/participants';
  8. import { MiddlewareRegistry } from '../base/redux';
  9. import { TRACK_ADDED, TRACK_UPDATED } from '../base/tracks';
  10. import { ADD_FACE_EXPRESSION } from '../face-landmarks/actionTypes';
  11. import RTCStats from './RTCStats';
  12. import { canSendRtcstatsData, isRtcstatsEnabled } from './functions';
  13. import logger from './logger';
  14. /**
  15. * Middleware which intercepts lib-jitsi-meet initialization and conference join in order init the
  16. * rtcstats-client.
  17. *
  18. * @param {Store} store - The redux store.
  19. * @returns {Function}
  20. */
  21. MiddlewareRegistry.register(store => next => action => {
  22. const state = store.getState();
  23. const config = state['features/base/config'];
  24. const { analytics } = config;
  25. switch (action.type) {
  26. case LIB_WILL_INIT: {
  27. if (isRtcstatsEnabled(state)) {
  28. // RTCStats "proxies" WebRTC functions such as GUM and RTCPeerConnection by rewriting the global
  29. // window functions. Because lib-jitsi-meet uses references to those functions that are taken on
  30. // init, we need to add these proxies before it initializes, otherwise lib-jitsi-meet will use the
  31. // original non proxy versions of these functions.
  32. try {
  33. // Default poll interval is 1000ms and standard stats will be used, if not provided in the config.
  34. const pollInterval = analytics.rtcstatsPollInterval || 1000;
  35. const useLegacy = analytics.rtcstatsUseLegacy || false;
  36. // Initialize but don't connect to the rtcstats server wss, as it will start sending data for all
  37. // media calls made even before the conference started.
  38. RTCStats.init({
  39. endpoint: analytics.rtcstatsEndpoint,
  40. useLegacy,
  41. pollInterval
  42. });
  43. } catch (error) {
  44. logger.error('Failed to initialize RTCStats: ', error);
  45. }
  46. }
  47. break;
  48. }
  49. case TRACK_ADDED: {
  50. if (canSendRtcstatsData(state)) {
  51. const jitsiTrack = action?.track?.jitsiTrack;
  52. const { ssrc, videoType } = jitsiTrack || { };
  53. // Remote tracks store their ssrc in the jitsiTrack object. Local tracks don't. See getSsrcByTrack.
  54. if (videoType && ssrc && !jitsiTrack.isLocal()) {
  55. RTCStats.sendVideoTypeData({
  56. ssrc,
  57. videoType
  58. });
  59. }
  60. }
  61. break;
  62. }
  63. case TRACK_UPDATED: {
  64. if (canSendRtcstatsData(state)) {
  65. const { videoType, jitsiTrack } = action?.track || { };
  66. const { ssrc } = jitsiTrack || { };
  67. // if the videoType of the remote track has changed we expect to find it in track.videoType. grep for
  68. // trackVideoTypeChanged.
  69. if (videoType && ssrc && !jitsiTrack.isLocal()) {
  70. RTCStats.sendVideoTypeData({
  71. ssrc,
  72. videoType
  73. });
  74. }
  75. }
  76. break;
  77. }
  78. case CONFERENCE_UNIQUE_ID_SET: {
  79. if (canSendRtcstatsData(state)) {
  80. // Once the conference started connect to the rtcstats server and send data.
  81. try {
  82. RTCStats.connect();
  83. const localParticipant = getLocalParticipant(state);
  84. const options = getConferenceOptions(state);
  85. // Unique identifier for a conference session, not to be confused with meeting name
  86. // i.e. If all participants leave a meeting it will have a different value on the next join.
  87. const { conference } = action;
  88. const meetingUniqueId = conference && conference.getMeetingUniqueId();
  89. // The current implementation of rtcstats-server is configured to send data to amplitude, thus
  90. // we add identity specific information so we can correlate on the amplitude side. If amplitude is
  91. // not configured an empty object will be sent.
  92. // The current configuration of the conference is also sent as metadata to rtcstats server.
  93. // This is done in order to facilitate queries based on different conference configurations.
  94. // e.g. Find all RTCPeerConnections that connect to a specific shard or were created in a
  95. // conference with a specific version.
  96. // XXX(george): we also want to be able to correlate between rtcstats and callstats, so we're
  97. // appending the callstats user name (if it exists) to the display name.
  98. const displayName = options.statisticsId
  99. || options.statisticsDisplayName
  100. || jitsiLocalStorage.getItem('callStatsUserName');
  101. RTCStats.sendIdentityData({
  102. ...getAmplitudeIdentity(),
  103. ...options,
  104. endpointId: localParticipant?.id,
  105. confName: getRoomName(state),
  106. displayName,
  107. meetingUniqueId
  108. });
  109. } catch (error) {
  110. // If the connection failed do not impact jitsi-meet just silently fail.
  111. logger.error('RTCStats connect failed with: ', error);
  112. }
  113. }
  114. break;
  115. }
  116. case DOMINANT_SPEAKER_CHANGED: {
  117. if (canSendRtcstatsData(state)) {
  118. const { id, previousSpeakers } = action.participant;
  119. RTCStats.sendDominantSpeakerData({ dominantSpeakerEndpoint: id,
  120. previousSpeakers });
  121. }
  122. break;
  123. }
  124. case E2E_RTT_CHANGED: {
  125. if (canSendRtcstatsData(state)) {
  126. const { participant, rtt } = action.e2eRtt;
  127. RTCStats.sendE2eRttData({
  128. remoteEndpointId: participant.getId(),
  129. rtt,
  130. remoteRegion: participant.getProperty('region')
  131. });
  132. }
  133. break;
  134. }
  135. case ADD_FACE_EXPRESSION: {
  136. if (canSendRtcstatsData(state)) {
  137. const { duration, faceExpression, timestamp } = action;
  138. RTCStats.sendFaceExpressionData({
  139. duration,
  140. faceLandmarks: faceExpression,
  141. timestamp
  142. });
  143. }
  144. break;
  145. }
  146. case CONFERENCE_TIMESTAMP_CHANGED: {
  147. if (canSendRtcstatsData(state)) {
  148. const conferenceTimestamp = action.conferenceTimestamp;
  149. RTCStats.sendConferenceTimestamp(conferenceTimestamp);
  150. }
  151. break;
  152. }
  153. }
  154. return next(action);
  155. });