@whereby.com/media 9.2.6 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -552,13 +552,6 @@ class Session {
552
552
  return;
553
553
  }
554
554
  const stream = this.streams[0];
555
- this._incrementAnalyticMetric("P2PSessionAddTrack");
556
- rtcStats.sendEvent("P2PSessionAddTrack", {
557
- trackId: track.id,
558
- kind: track.kind,
559
- hasSessionStream: !!stream,
560
- trackOfSameKindInStream: !!(stream === null || stream === void 0 ? void 0 : stream.getTracks().filter((t) => t.kind === track.kind && t.id !== track.id).length),
561
- });
562
555
  stream === null || stream === void 0 ? void 0 : stream.addTrack(track);
563
556
  this.pc.addTrack(track, stream);
564
557
  }
@@ -1449,6 +1442,8 @@ function captureVideoSsrcMetrics(ssrcMetrics, currentSsrcStats, prevSsrcStats, t
1449
1442
  const qpsumDiff = currentSsrcStats.qpSum - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.qpSum) || 0);
1450
1443
  ssrcMetrics.qpf = qpsumDiff / frameCountDiff;
1451
1444
  ssrcMetrics.fps = (frameCountDiff * 1000) / timeDiff;
1445
+ const freezeCountDiff = (currentSsrcStats.freezeCount || 0) - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.freezeCount) || 0);
1446
+ ssrcMetrics.freezeRate = (freezeCountDiff * 1000) / timeDiff;
1452
1447
  }
1453
1448
  else {
1454
1449
  const kfCountDiff = currentSsrcStats.keyFramesEncoded - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.keyFramesEncoded) || 0);
@@ -1594,15 +1589,17 @@ const getOrCreateSsrcMetricsContainer = (statsByView, time, pcIndex, clientId, t
1594
1589
  ssrcStats.updated = time;
1595
1590
  return ssrcStats;
1596
1591
  };
1597
- const removeNonUpdatedStats = (statsByView, time) => {
1592
+ const removeNonUpdatedStats = (statsByView, time, renderedDimensionsByTrack) => {
1598
1593
  Object.entries(statsByView).forEach(([viewId, viewStats]) => {
1599
1594
  if (viewStats.updated !== undefined && viewStats.updated < time) {
1595
+ Object.keys(viewStats.tracks).forEach((trackId) => delete renderedDimensionsByTrack[trackId]);
1600
1596
  delete statsByView[viewId];
1601
1597
  }
1602
1598
  else {
1603
1599
  Object.entries(viewStats.tracks).forEach(([trackId, trackStats]) => {
1604
1600
  if (trackStats.updated < time) {
1605
1601
  delete viewStats.tracks[trackId];
1602
+ delete renderedDimensionsByTrack[trackId];
1606
1603
  }
1607
1604
  else {
1608
1605
  Object.entries(trackStats.ssrcs).forEach(([ssrc, ssrcStats]) => {
@@ -1640,7 +1637,7 @@ function collectStats(state_1, _a, immediate_1) {
1640
1637
  if (timeSinceLastUpdate < 400) {
1641
1638
  if (immediate)
1642
1639
  return state.statsByView;
1643
- state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients); });
1640
+ state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients, state.renderedDimensionsByTrack); });
1644
1641
  state.nextTimeout = setTimeout(collectStatsBound, interval);
1645
1642
  return;
1646
1643
  }
@@ -1733,7 +1730,7 @@ function collectStats(state_1, _a, immediate_1) {
1733
1730
  }
1734
1731
  });
1735
1732
  });
1736
- removeNonUpdatedStats(state.statsByView, state.lastUpdateTime);
1733
+ removeNonUpdatedStats(state.statsByView, state.lastUpdateTime, state.renderedDimensionsByTrack);
1737
1734
  Object.entries((defaultViewStats === null || defaultViewStats === void 0 ? void 0 : defaultViewStats.candidatePairs) || {}).forEach(([cpKey, cp]) => {
1738
1735
  const active = cp.lastRtcStatsTime === state.lastUpdateTime;
1739
1736
  cp.active = active;
@@ -1752,7 +1749,7 @@ function collectStats(state_1, _a, immediate_1) {
1752
1749
  return state.statsByView;
1753
1750
  }
1754
1751
  else {
1755
- state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients); });
1752
+ state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients, state.renderedDimensionsByTrack); });
1756
1753
  }
1757
1754
  }
1758
1755
  catch (e) {
@@ -1791,6 +1788,7 @@ const STATE = {
1791
1788
  currentMonitor: null,
1792
1789
  getClients: () => [],
1793
1790
  lastUpdateTime: 0,
1791
+ renderedDimensionsByTrack: {},
1794
1792
  statsByView: {},
1795
1793
  subscriptions: [],
1796
1794
  numFailedStatsReports: 0,
@@ -1809,6 +1807,9 @@ const getNumMissingTrackSsrcLookups = () => numMissingTrackSsrcLookups;
1809
1807
  const getNumFailedTrackSsrcLookups = () => numFailedTrackSsrcLookups;
1810
1808
  const getUpdatedStats = () => { var _a; return (_a = STATE.currentMonitor) === null || _a === void 0 ? void 0 : _a.getUpdatedStats(); };
1811
1809
  const setClientProvider = (provider) => (STATE.getClients = provider);
1810
+ const updateRenderedDimensions = (trackId, data) => {
1811
+ STATE.renderedDimensionsByTrack[trackId] = data;
1812
+ };
1812
1813
  function startStatsMonitor(state, { interval, logger }) {
1813
1814
  const collectStatsBound = collectStats.bind(null, state, { interval, logger });
1814
1815
  let cpuObserver;
@@ -2529,6 +2530,7 @@ class P2pRtcManager {
2529
2530
  this._features = features || {};
2530
2531
  this._isAudioOnlyMode = false;
2531
2532
  this._closed = false;
2533
+ this._videoTrackIdByStreamId = {};
2532
2534
  this._fetchMediaServersTimer = null;
2533
2535
  this._stopCameraTimeout = null;
2534
2536
  this._icePublicIPGatheringTimeoutID = null;
@@ -2574,8 +2576,6 @@ class P2pRtcManager {
2574
2576
  P2PMicNotWorking: 0,
2575
2577
  P2PLocalNetworkFailed: 0,
2576
2578
  P2PRelayedIceCandidate: 0,
2577
- P2PSessionAddTrack: 0,
2578
- P2PAddTrackToPeerConnections: 0,
2579
2579
  P2PAddIceCandidateFailure: 0,
2580
2580
  };
2581
2581
  }
@@ -3011,6 +3011,8 @@ class P2pRtcManager {
3011
3011
  });
3012
3012
  return;
3013
3013
  }
3014
+ if (event.track.kind === "video")
3015
+ this._videoTrackIdByStreamId[stream.id] = event.track.id;
3014
3016
  if (session.streamIds.indexOf(stream.id) === -1) {
3015
3017
  session.streamIds.push(stream.id);
3016
3018
  this._emit(EVENTS.STREAM_ADDED, {
@@ -3159,12 +3161,6 @@ class P2pRtcManager {
3159
3161
  });
3160
3162
  }
3161
3163
  _addTrackToPeerConnections(track) {
3162
- this.analytics.P2PAddTrackToPeerConnections++;
3163
- rtcStats.sendEvent("P2PAddTrackToPeerConnections", {
3164
- trackId: track.id,
3165
- kind: track.kind,
3166
- readyState: track.readyState,
3167
- });
3168
3164
  this._forEachPeerConnection((session) => {
3169
3165
  this._withForcedRenegotiation(session, () => session.addTrack(track));
3170
3166
  });
@@ -3447,7 +3443,11 @@ class P2pRtcManager {
3447
3443
  }, 60 * 1000);
3448
3444
  }
3449
3445
  }
3450
- updateStreamResolution() { }
3446
+ updateStreamResolution(streamId, _ignored, { width, height, }) {
3447
+ const trackId = this._videoTrackIdByStreamId[streamId];
3448
+ if (trackId)
3449
+ updateRenderedDimensions(trackId, { width, height, time: Date.now() });
3450
+ }
3451
3451
  stopOrResumeAudio() {
3452
3452
  }
3453
3453
  _handleStopOrResumeVideo({ enable, track }) {
@@ -5588,7 +5588,7 @@ class VegaRtcManager {
5588
5588
  this._syncIncomingStreamsWithPWA(clientId);
5589
5589
  }
5590
5590
  updateStreamResolution(streamId, _ignored, { width, height, }) {
5591
- var _a, _b;
5591
+ var _a, _b, _c;
5592
5592
  logger$2.info("updateStreamResolution()", { streamId, width, height });
5593
5593
  const consumerId = this._streamIdToVideoConsumerId.get(streamId);
5594
5594
  const consumer = this._consumers.get(consumerId);
@@ -5596,17 +5596,18 @@ class VegaRtcManager {
5596
5596
  this._streamIdToVideoResolution.set(streamId, { width, height });
5597
5597
  return;
5598
5598
  }
5599
+ updateRenderedDimensions((_a = consumer.track) === null || _a === void 0 ? void 0 : _a.id, { width, height, time: Date.now() });
5599
5600
  const numberOfActiveVideos = getNumberOfActiveVideos(this._consumers);
5600
5601
  const numberOfTemporalLayers = getNumberOfTemporalLayers(consumer);
5601
5602
  const { spatialLayer, temporalLayer } = getLayers({ width, height }, {
5602
5603
  numberOfActiveVideos,
5603
5604
  numberOfTemporalLayers,
5604
- uncappedSingleRemoteVideoOn: (_a = this._features) === null || _a === void 0 ? void 0 : _a.uncappedSingleRemoteVideoOn,
5605
+ uncappedSingleRemoteVideoOn: (_b = this._features) === null || _b === void 0 ? void 0 : _b.uncappedSingleRemoteVideoOn,
5605
5606
  });
5606
5607
  if (consumer.appData.spatialLayer !== spatialLayer || consumer.appData.temporalLayer !== temporalLayer) {
5607
5608
  consumer.appData.spatialLayer = spatialLayer;
5608
5609
  consumer.appData.temporalLayer = temporalLayer;
5609
- (_b = this._vegaConnection) === null || _b === void 0 ? void 0 : _b.message("setConsumersPreferredLayers", {
5610
+ (_c = this._vegaConnection) === null || _c === void 0 ? void 0 : _c.message("setConsumersPreferredLayers", {
5610
5611
  consumerIds: [consumerId],
5611
5612
  spatialLayer,
5612
5613
  temporalLayer,
@@ -6021,6 +6022,92 @@ const getRoomMode = () => {
6021
6022
  return roomMode;
6022
6023
  };
6023
6024
 
6025
+ const createQualityDetector = (type) => {
6026
+ return {
6027
+ id: `quality-${type}`,
6028
+ enabled: ({ client }) => !client.isLocalClient && !client.isPresentation,
6029
+ check: ({ ssrc0, renderedDimensions, hasLiveTrack, kind }) => {
6030
+ if (!hasLiveTrack)
6031
+ return true;
6032
+ if (!ssrc0)
6033
+ return true;
6034
+ if (!ssrc0.bitrate)
6035
+ return true;
6036
+ if (kind === "video") {
6037
+ if (renderedDimensions && renderedDimensions.width && renderedDimensions.height) {
6038
+ const maxSideRendered = Math.max(renderedDimensions.width, renderedDimensions.height);
6039
+ const maxSideReceived = Math.max(ssrc0.width || 0, ssrc0.height || 0);
6040
+ const fpsReceived = ssrc0.fps || 0;
6041
+ const hadFreeze = !!ssrc0.freezeRate;
6042
+ const bitrate = ssrc0.bitrate || 0;
6043
+ if (maxSideRendered < 100) {
6044
+ if (type === "warning" && maxSideReceived < 160)
6045
+ return true;
6046
+ if (type === "critical" && maxSideReceived < 90)
6047
+ return true;
6048
+ if (type === "warning" && fpsReceived < 5)
6049
+ return true;
6050
+ if (type === "critical" && fpsReceived < 2)
6051
+ return true;
6052
+ if (type === "warning" && bitrate < 10000)
6053
+ return true;
6054
+ if (type === "critical" && bitrate < 5000)
6055
+ return true;
6056
+ }
6057
+ else if (maxSideRendered < 480) {
6058
+ if (type === "warning" && maxSideReceived < 240)
6059
+ return true;
6060
+ if (type === "critical" && maxSideReceived < 120)
6061
+ return true;
6062
+ if (type === "warning" && fpsReceived < 14)
6063
+ return true;
6064
+ if (type === "critical" && fpsReceived < 9)
6065
+ return true;
6066
+ if (hadFreeze)
6067
+ return true;
6068
+ if (type === "warning" && bitrate < 50000)
6069
+ return true;
6070
+ if (type === "critical" && bitrate < 20000)
6071
+ return true;
6072
+ }
6073
+ else {
6074
+ if (type === "warning" && maxSideReceived < 480)
6075
+ return true;
6076
+ if (type === "critical" && maxSideReceived < 240)
6077
+ return true;
6078
+ if (type === "warning" && fpsReceived < 14)
6079
+ return true;
6080
+ if (type === "critical" && fpsReceived < 9)
6081
+ return true;
6082
+ if (type === "warning" && bitrate < 200000)
6083
+ return true;
6084
+ if (type === "critical" && bitrate < 50000)
6085
+ return true;
6086
+ if (hadFreeze)
6087
+ return true;
6088
+ }
6089
+ }
6090
+ }
6091
+ else if (kind === "audio") {
6092
+ const audioLevel = ssrc0.audioLevel || 0;
6093
+ const concealment = ssrc0.audioConcealment || 0;
6094
+ const acceleration = ssrc0.audioAcceleration || 0;
6095
+ const deceleration = ssrc0.audioDeceleration || 0;
6096
+ const audioDistortion = concealment + acceleration + deceleration;
6097
+ if (audioLevel >= 0.01) {
6098
+ if (type === "warning" && audioDistortion > 0.1)
6099
+ return true;
6100
+ if (type === "critical" && audioDistortion > 0.2)
6101
+ return true;
6102
+ }
6103
+ }
6104
+ return false;
6105
+ },
6106
+ };
6107
+ };
6108
+ const qualityWarningDetector = createQualityDetector("warning");
6109
+ const qualityCriticalDetector = createQualityDetector("critical");
6110
+
6024
6111
  const badNetworkIssueDetector = {
6025
6112
  id: "bad-network",
6026
6113
  enabled: ({ hasLiveTrack, ssrcs }) => hasLiveTrack && ssrcs.length > 0,
@@ -6244,6 +6331,8 @@ const issueDetectors = [
6244
6331
  (ssrc0.audioLevel || 0) >= 0.001 &&
6245
6332
  (ssrc0.audioAcceleration || 0) >= 0.1,
6246
6333
  },
6334
+ qualityWarningDetector,
6335
+ qualityCriticalDetector,
6247
6336
  ];
6248
6337
 
6249
6338
  let subscriptions = [];
@@ -6398,7 +6487,7 @@ function issueDetectorOrMetricEnabled(issueDetectorOrMetric, checkData) {
6398
6487
  }
6399
6488
  return enabled && (issueDetectorOrMetric.enabled ? issueDetectorOrMetric.enabled(checkData) : true);
6400
6489
  }
6401
- function onUpdatedStats(statsByView, clients) {
6490
+ function onUpdatedStats(statsByView, clients, renderedDimensionsByTrack) {
6402
6491
  Object.values(aggregatedMetrics).forEach((metricData) => {
6403
6492
  metricData.curTicks = 0;
6404
6493
  metricData.curSum = 0;
@@ -6436,6 +6525,7 @@ function onUpdatedStats(statsByView, clients) {
6436
6525
  kind,
6437
6526
  track,
6438
6527
  trackStats,
6528
+ renderedDimensions: (track === null || track === void 0 ? void 0 : track.id) ? renderedDimensionsByTrack[track.id] : undefined,
6439
6529
  stats,
6440
6530
  hasLiveTrack,
6441
6531
  ssrc0,
@@ -7528,5 +7618,6 @@ exports.subscribeIssues = subscribeIssues;
7528
7618
  exports.subscribeStats = subscribeStats;
7529
7619
  exports.trackAnnotations = trackAnnotations;
7530
7620
  exports.turnServerOverride = turnServerOverride;
7621
+ exports.updateRenderedDimensions = updateRenderedDimensions;
7531
7622
  exports.variance = variance;
7532
7623
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -27,10 +27,16 @@ type PressureRecord = {
27
27
  state: string;
28
28
  time: number;
29
29
  };
30
+ type RenderedDimensionsReport = {
31
+ time: number;
32
+ width: number;
33
+ height: number;
34
+ };
30
35
  interface TrackStats {
31
36
  startTime: number;
32
37
  updated: number;
33
38
  ssrcs: Record<string, SsrcStats>;
39
+ renderedDimensions?: RenderedDimensionsReport;
34
40
  }
35
41
  interface ViewStats {
36
42
  startTime?: number;
@@ -93,6 +99,7 @@ interface SsrcStats {
93
99
  encodeTime?: number;
94
100
  sourceWidth?: number;
95
101
  sourceFps?: number;
102
+ freezeRate?: number;
96
103
  }
97
104
 
98
105
  interface IssueDetector {
@@ -106,6 +113,7 @@ interface IssueCheckData {
106
113
  clients: StatsClient[];
107
114
  kind: string;
108
115
  track: MediaStreamTrack | MediaStreamTrackWithDenoiserContext | undefined;
116
+ renderedDimensions?: RenderedDimensionsReport;
109
117
  trackStats?: TrackStats;
110
118
  stats?: ViewStats;
111
119
  hasLiveTrack: boolean;
@@ -236,7 +244,7 @@ interface StatsMonitor {
236
244
  stop: () => void;
237
245
  }
238
246
  interface StatsSubscription {
239
- onUpdatedStats: (statsByView: Record<string, ViewStats>, clients: StatsClient[]) => void;
247
+ onUpdatedStats: (statsByView: Record<string, ViewStats>, clients: StatsClient[], renderedDimensionsByTrack: Record<string, RenderedDimensionsReport>) => void;
240
248
  }
241
249
  interface StatsMonitorState {
242
250
  currentMonitor: StatsMonitor | null;
@@ -245,6 +253,7 @@ interface StatsMonitorState {
245
253
  lastUpdateTime: number;
246
254
  nextTimeout?: number;
247
255
  pressureObserver?: PressureObserver;
256
+ renderedDimensionsByTrack: Record<string, RenderedDimensionsReport>;
248
257
  statsByView: Record<string, ViewStats>;
249
258
  subscriptions: StatsSubscription[];
250
259
  numFailedStatsReports: number;
@@ -261,6 +270,7 @@ declare const getNumMissingTrackSsrcLookups: () => number;
261
270
  declare const getNumFailedTrackSsrcLookups: () => number;
262
271
  declare const getUpdatedStats: () => Promise<Record<string, ViewStats> | undefined> | undefined;
263
272
  declare const setClientProvider: (provider: () => StatsClient[]) => () => StatsClient[];
273
+ declare const updateRenderedDimensions: (trackId: string, data: RenderedDimensionsReport) => void;
264
274
  declare function subscribeStats(subscription: StatsSubscription, options?: StatsMonitorOptions, state?: StatsMonitorState): {
265
275
  stop(): void;
266
276
  };
@@ -1602,8 +1612,6 @@ type P2PAnalytics = {
1602
1612
  P2PMicNotWorking: number;
1603
1613
  P2PLocalNetworkFailed: number;
1604
1614
  P2PRelayedIceCandidate: number;
1605
- P2PSessionAddTrack: number;
1606
- P2PAddTrackToPeerConnections: number;
1607
1615
  P2PAddIceCandidateFailure: number;
1608
1616
  };
1609
1617
  type P2PAnalyticMetric = keyof P2PAnalytics;
@@ -1643,6 +1651,7 @@ declare class P2pRtcManager implements RtcManager {
1643
1651
  analytics: P2PAnalytics;
1644
1652
  _rtcStatsDisconnectTimeout?: ReturnType<typeof setTimeout>;
1645
1653
  _webcamPaused?: boolean;
1654
+ _videoTrackIdByStreamId: Record<string, string>;
1646
1655
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features }: RtcManagerOptions);
1647
1656
  numberOfPeerconnections(): number;
1648
1657
  isInitializedWith({ selfId, roomName, isSfu }: {
@@ -1695,7 +1704,10 @@ declare class P2pRtcManager implements RtcManager {
1695
1704
  clientId: string;
1696
1705
  }): Session;
1697
1706
  disconnect(clientId: string): void;
1698
- updateStreamResolution(): void;
1707
+ updateStreamResolution(streamId: string, _ignored: any, { width, height, }: {
1708
+ width: number;
1709
+ height: number;
1710
+ }): void;
1699
1711
  stopOrResumeAudio(): void;
1700
1712
  _handleStopOrResumeVideo({ enable, track }: {
1701
1713
  enable: boolean;
@@ -2091,5 +2103,5 @@ declare class VegaRtcManager implements RtcManager {
2091
2103
  hasClient(clientId: string): boolean;
2092
2104
  }
2093
2105
 
2094
- export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
2106
+ export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, updateRenderedDimensions, variance };
2095
2107
  export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatFileShare, ChatMessage, ChatMessageError, ChatMessageRemoved, ChatMessageRequest, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, FileShareErrorCode, FileUploadUrl, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, GetUserMediaAttempt, GetUserMediaAttemptOutcome, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveCaptionEvent, LiveCaptionsStartedEvent, LiveCaptionsStoppedEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
package/dist/index.d.mts CHANGED
@@ -27,10 +27,16 @@ type PressureRecord = {
27
27
  state: string;
28
28
  time: number;
29
29
  };
30
+ type RenderedDimensionsReport = {
31
+ time: number;
32
+ width: number;
33
+ height: number;
34
+ };
30
35
  interface TrackStats {
31
36
  startTime: number;
32
37
  updated: number;
33
38
  ssrcs: Record<string, SsrcStats>;
39
+ renderedDimensions?: RenderedDimensionsReport;
34
40
  }
35
41
  interface ViewStats {
36
42
  startTime?: number;
@@ -93,6 +99,7 @@ interface SsrcStats {
93
99
  encodeTime?: number;
94
100
  sourceWidth?: number;
95
101
  sourceFps?: number;
102
+ freezeRate?: number;
96
103
  }
97
104
 
98
105
  interface IssueDetector {
@@ -106,6 +113,7 @@ interface IssueCheckData {
106
113
  clients: StatsClient[];
107
114
  kind: string;
108
115
  track: MediaStreamTrack | MediaStreamTrackWithDenoiserContext | undefined;
116
+ renderedDimensions?: RenderedDimensionsReport;
109
117
  trackStats?: TrackStats;
110
118
  stats?: ViewStats;
111
119
  hasLiveTrack: boolean;
@@ -236,7 +244,7 @@ interface StatsMonitor {
236
244
  stop: () => void;
237
245
  }
238
246
  interface StatsSubscription {
239
- onUpdatedStats: (statsByView: Record<string, ViewStats>, clients: StatsClient[]) => void;
247
+ onUpdatedStats: (statsByView: Record<string, ViewStats>, clients: StatsClient[], renderedDimensionsByTrack: Record<string, RenderedDimensionsReport>) => void;
240
248
  }
241
249
  interface StatsMonitorState {
242
250
  currentMonitor: StatsMonitor | null;
@@ -245,6 +253,7 @@ interface StatsMonitorState {
245
253
  lastUpdateTime: number;
246
254
  nextTimeout?: number;
247
255
  pressureObserver?: PressureObserver;
256
+ renderedDimensionsByTrack: Record<string, RenderedDimensionsReport>;
248
257
  statsByView: Record<string, ViewStats>;
249
258
  subscriptions: StatsSubscription[];
250
259
  numFailedStatsReports: number;
@@ -261,6 +270,7 @@ declare const getNumMissingTrackSsrcLookups: () => number;
261
270
  declare const getNumFailedTrackSsrcLookups: () => number;
262
271
  declare const getUpdatedStats: () => Promise<Record<string, ViewStats> | undefined> | undefined;
263
272
  declare const setClientProvider: (provider: () => StatsClient[]) => () => StatsClient[];
273
+ declare const updateRenderedDimensions: (trackId: string, data: RenderedDimensionsReport) => void;
264
274
  declare function subscribeStats(subscription: StatsSubscription, options?: StatsMonitorOptions, state?: StatsMonitorState): {
265
275
  stop(): void;
266
276
  };
@@ -1602,8 +1612,6 @@ type P2PAnalytics = {
1602
1612
  P2PMicNotWorking: number;
1603
1613
  P2PLocalNetworkFailed: number;
1604
1614
  P2PRelayedIceCandidate: number;
1605
- P2PSessionAddTrack: number;
1606
- P2PAddTrackToPeerConnections: number;
1607
1615
  P2PAddIceCandidateFailure: number;
1608
1616
  };
1609
1617
  type P2PAnalyticMetric = keyof P2PAnalytics;
@@ -1643,6 +1651,7 @@ declare class P2pRtcManager implements RtcManager {
1643
1651
  analytics: P2PAnalytics;
1644
1652
  _rtcStatsDisconnectTimeout?: ReturnType<typeof setTimeout>;
1645
1653
  _webcamPaused?: boolean;
1654
+ _videoTrackIdByStreamId: Record<string, string>;
1646
1655
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features }: RtcManagerOptions);
1647
1656
  numberOfPeerconnections(): number;
1648
1657
  isInitializedWith({ selfId, roomName, isSfu }: {
@@ -1695,7 +1704,10 @@ declare class P2pRtcManager implements RtcManager {
1695
1704
  clientId: string;
1696
1705
  }): Session;
1697
1706
  disconnect(clientId: string): void;
1698
- updateStreamResolution(): void;
1707
+ updateStreamResolution(streamId: string, _ignored: any, { width, height, }: {
1708
+ width: number;
1709
+ height: number;
1710
+ }): void;
1699
1711
  stopOrResumeAudio(): void;
1700
1712
  _handleStopOrResumeVideo({ enable, track }: {
1701
1713
  enable: boolean;
@@ -2091,5 +2103,5 @@ declare class VegaRtcManager implements RtcManager {
2091
2103
  hasClient(clientId: string): boolean;
2092
2104
  }
2093
2105
 
2094
- export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
2106
+ export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, updateRenderedDimensions, variance };
2095
2107
  export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatFileShare, ChatMessage, ChatMessageError, ChatMessageRemoved, ChatMessageRequest, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, FileShareErrorCode, FileUploadUrl, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, GetUserMediaAttempt, GetUserMediaAttemptOutcome, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveCaptionEvent, LiveCaptionsStartedEvent, LiveCaptionsStoppedEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
package/dist/index.d.ts CHANGED
@@ -27,10 +27,16 @@ type PressureRecord = {
27
27
  state: string;
28
28
  time: number;
29
29
  };
30
+ type RenderedDimensionsReport = {
31
+ time: number;
32
+ width: number;
33
+ height: number;
34
+ };
30
35
  interface TrackStats {
31
36
  startTime: number;
32
37
  updated: number;
33
38
  ssrcs: Record<string, SsrcStats>;
39
+ renderedDimensions?: RenderedDimensionsReport;
34
40
  }
35
41
  interface ViewStats {
36
42
  startTime?: number;
@@ -93,6 +99,7 @@ interface SsrcStats {
93
99
  encodeTime?: number;
94
100
  sourceWidth?: number;
95
101
  sourceFps?: number;
102
+ freezeRate?: number;
96
103
  }
97
104
 
98
105
  interface IssueDetector {
@@ -106,6 +113,7 @@ interface IssueCheckData {
106
113
  clients: StatsClient[];
107
114
  kind: string;
108
115
  track: MediaStreamTrack | MediaStreamTrackWithDenoiserContext | undefined;
116
+ renderedDimensions?: RenderedDimensionsReport;
109
117
  trackStats?: TrackStats;
110
118
  stats?: ViewStats;
111
119
  hasLiveTrack: boolean;
@@ -236,7 +244,7 @@ interface StatsMonitor {
236
244
  stop: () => void;
237
245
  }
238
246
  interface StatsSubscription {
239
- onUpdatedStats: (statsByView: Record<string, ViewStats>, clients: StatsClient[]) => void;
247
+ onUpdatedStats: (statsByView: Record<string, ViewStats>, clients: StatsClient[], renderedDimensionsByTrack: Record<string, RenderedDimensionsReport>) => void;
240
248
  }
241
249
  interface StatsMonitorState {
242
250
  currentMonitor: StatsMonitor | null;
@@ -245,6 +253,7 @@ interface StatsMonitorState {
245
253
  lastUpdateTime: number;
246
254
  nextTimeout?: number;
247
255
  pressureObserver?: PressureObserver;
256
+ renderedDimensionsByTrack: Record<string, RenderedDimensionsReport>;
248
257
  statsByView: Record<string, ViewStats>;
249
258
  subscriptions: StatsSubscription[];
250
259
  numFailedStatsReports: number;
@@ -261,6 +270,7 @@ declare const getNumMissingTrackSsrcLookups: () => number;
261
270
  declare const getNumFailedTrackSsrcLookups: () => number;
262
271
  declare const getUpdatedStats: () => Promise<Record<string, ViewStats> | undefined> | undefined;
263
272
  declare const setClientProvider: (provider: () => StatsClient[]) => () => StatsClient[];
273
+ declare const updateRenderedDimensions: (trackId: string, data: RenderedDimensionsReport) => void;
264
274
  declare function subscribeStats(subscription: StatsSubscription, options?: StatsMonitorOptions, state?: StatsMonitorState): {
265
275
  stop(): void;
266
276
  };
@@ -1602,8 +1612,6 @@ type P2PAnalytics = {
1602
1612
  P2PMicNotWorking: number;
1603
1613
  P2PLocalNetworkFailed: number;
1604
1614
  P2PRelayedIceCandidate: number;
1605
- P2PSessionAddTrack: number;
1606
- P2PAddTrackToPeerConnections: number;
1607
1615
  P2PAddIceCandidateFailure: number;
1608
1616
  };
1609
1617
  type P2PAnalyticMetric = keyof P2PAnalytics;
@@ -1643,6 +1651,7 @@ declare class P2pRtcManager implements RtcManager {
1643
1651
  analytics: P2PAnalytics;
1644
1652
  _rtcStatsDisconnectTimeout?: ReturnType<typeof setTimeout>;
1645
1653
  _webcamPaused?: boolean;
1654
+ _videoTrackIdByStreamId: Record<string, string>;
1646
1655
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features }: RtcManagerOptions);
1647
1656
  numberOfPeerconnections(): number;
1648
1657
  isInitializedWith({ selfId, roomName, isSfu }: {
@@ -1695,7 +1704,10 @@ declare class P2pRtcManager implements RtcManager {
1695
1704
  clientId: string;
1696
1705
  }): Session;
1697
1706
  disconnect(clientId: string): void;
1698
- updateStreamResolution(): void;
1707
+ updateStreamResolution(streamId: string, _ignored: any, { width, height, }: {
1708
+ width: number;
1709
+ height: number;
1710
+ }): void;
1699
1711
  stopOrResumeAudio(): void;
1700
1712
  _handleStopOrResumeVideo({ enable, track }: {
1701
1713
  enable: boolean;
@@ -2091,5 +2103,5 @@ declare class VegaRtcManager implements RtcManager {
2091
2103
  hasClient(clientId: string): boolean;
2092
2104
  }
2093
2105
 
2094
- export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
2106
+ export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, updateRenderedDimensions, variance };
2095
2107
  export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatFileShare, ChatMessage, ChatMessageError, ChatMessageRemoved, ChatMessageRequest, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, FileShareErrorCode, FileUploadUrl, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, GetUserMediaAttempt, GetUserMediaAttemptOutcome, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveCaptionEvent, LiveCaptionsStartedEvent, LiveCaptionsStoppedEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
package/dist/index.mjs CHANGED
@@ -532,13 +532,6 @@ class Session {
532
532
  return;
533
533
  }
534
534
  const stream = this.streams[0];
535
- this._incrementAnalyticMetric("P2PSessionAddTrack");
536
- rtcStats.sendEvent("P2PSessionAddTrack", {
537
- trackId: track.id,
538
- kind: track.kind,
539
- hasSessionStream: !!stream,
540
- trackOfSameKindInStream: !!(stream === null || stream === void 0 ? void 0 : stream.getTracks().filter((t) => t.kind === track.kind && t.id !== track.id).length),
541
- });
542
535
  stream === null || stream === void 0 ? void 0 : stream.addTrack(track);
543
536
  this.pc.addTrack(track, stream);
544
537
  }
@@ -1429,6 +1422,8 @@ function captureVideoSsrcMetrics(ssrcMetrics, currentSsrcStats, prevSsrcStats, t
1429
1422
  const qpsumDiff = currentSsrcStats.qpSum - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.qpSum) || 0);
1430
1423
  ssrcMetrics.qpf = qpsumDiff / frameCountDiff;
1431
1424
  ssrcMetrics.fps = (frameCountDiff * 1000) / timeDiff;
1425
+ const freezeCountDiff = (currentSsrcStats.freezeCount || 0) - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.freezeCount) || 0);
1426
+ ssrcMetrics.freezeRate = (freezeCountDiff * 1000) / timeDiff;
1432
1427
  }
1433
1428
  else {
1434
1429
  const kfCountDiff = currentSsrcStats.keyFramesEncoded - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.keyFramesEncoded) || 0);
@@ -1574,15 +1569,17 @@ const getOrCreateSsrcMetricsContainer = (statsByView, time, pcIndex, clientId, t
1574
1569
  ssrcStats.updated = time;
1575
1570
  return ssrcStats;
1576
1571
  };
1577
- const removeNonUpdatedStats = (statsByView, time) => {
1572
+ const removeNonUpdatedStats = (statsByView, time, renderedDimensionsByTrack) => {
1578
1573
  Object.entries(statsByView).forEach(([viewId, viewStats]) => {
1579
1574
  if (viewStats.updated !== undefined && viewStats.updated < time) {
1575
+ Object.keys(viewStats.tracks).forEach((trackId) => delete renderedDimensionsByTrack[trackId]);
1580
1576
  delete statsByView[viewId];
1581
1577
  }
1582
1578
  else {
1583
1579
  Object.entries(viewStats.tracks).forEach(([trackId, trackStats]) => {
1584
1580
  if (trackStats.updated < time) {
1585
1581
  delete viewStats.tracks[trackId];
1582
+ delete renderedDimensionsByTrack[trackId];
1586
1583
  }
1587
1584
  else {
1588
1585
  Object.entries(trackStats.ssrcs).forEach(([ssrc, ssrcStats]) => {
@@ -1620,7 +1617,7 @@ function collectStats(state_1, _a, immediate_1) {
1620
1617
  if (timeSinceLastUpdate < 400) {
1621
1618
  if (immediate)
1622
1619
  return state.statsByView;
1623
- state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients); });
1620
+ state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients, state.renderedDimensionsByTrack); });
1624
1621
  state.nextTimeout = setTimeout(collectStatsBound, interval);
1625
1622
  return;
1626
1623
  }
@@ -1713,7 +1710,7 @@ function collectStats(state_1, _a, immediate_1) {
1713
1710
  }
1714
1711
  });
1715
1712
  });
1716
- removeNonUpdatedStats(state.statsByView, state.lastUpdateTime);
1713
+ removeNonUpdatedStats(state.statsByView, state.lastUpdateTime, state.renderedDimensionsByTrack);
1717
1714
  Object.entries((defaultViewStats === null || defaultViewStats === void 0 ? void 0 : defaultViewStats.candidatePairs) || {}).forEach(([cpKey, cp]) => {
1718
1715
  const active = cp.lastRtcStatsTime === state.lastUpdateTime;
1719
1716
  cp.active = active;
@@ -1732,7 +1729,7 @@ function collectStats(state_1, _a, immediate_1) {
1732
1729
  return state.statsByView;
1733
1730
  }
1734
1731
  else {
1735
- state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients); });
1732
+ state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients, state.renderedDimensionsByTrack); });
1736
1733
  }
1737
1734
  }
1738
1735
  catch (e) {
@@ -1771,6 +1768,7 @@ const STATE = {
1771
1768
  currentMonitor: null,
1772
1769
  getClients: () => [],
1773
1770
  lastUpdateTime: 0,
1771
+ renderedDimensionsByTrack: {},
1774
1772
  statsByView: {},
1775
1773
  subscriptions: [],
1776
1774
  numFailedStatsReports: 0,
@@ -1789,6 +1787,9 @@ const getNumMissingTrackSsrcLookups = () => numMissingTrackSsrcLookups;
1789
1787
  const getNumFailedTrackSsrcLookups = () => numFailedTrackSsrcLookups;
1790
1788
  const getUpdatedStats = () => { var _a; return (_a = STATE.currentMonitor) === null || _a === void 0 ? void 0 : _a.getUpdatedStats(); };
1791
1789
  const setClientProvider = (provider) => (STATE.getClients = provider);
1790
+ const updateRenderedDimensions = (trackId, data) => {
1791
+ STATE.renderedDimensionsByTrack[trackId] = data;
1792
+ };
1792
1793
  function startStatsMonitor(state, { interval, logger }) {
1793
1794
  const collectStatsBound = collectStats.bind(null, state, { interval, logger });
1794
1795
  let cpuObserver;
@@ -2509,6 +2510,7 @@ class P2pRtcManager {
2509
2510
  this._features = features || {};
2510
2511
  this._isAudioOnlyMode = false;
2511
2512
  this._closed = false;
2513
+ this._videoTrackIdByStreamId = {};
2512
2514
  this._fetchMediaServersTimer = null;
2513
2515
  this._stopCameraTimeout = null;
2514
2516
  this._icePublicIPGatheringTimeoutID = null;
@@ -2554,8 +2556,6 @@ class P2pRtcManager {
2554
2556
  P2PMicNotWorking: 0,
2555
2557
  P2PLocalNetworkFailed: 0,
2556
2558
  P2PRelayedIceCandidate: 0,
2557
- P2PSessionAddTrack: 0,
2558
- P2PAddTrackToPeerConnections: 0,
2559
2559
  P2PAddIceCandidateFailure: 0,
2560
2560
  };
2561
2561
  }
@@ -2991,6 +2991,8 @@ class P2pRtcManager {
2991
2991
  });
2992
2992
  return;
2993
2993
  }
2994
+ if (event.track.kind === "video")
2995
+ this._videoTrackIdByStreamId[stream.id] = event.track.id;
2994
2996
  if (session.streamIds.indexOf(stream.id) === -1) {
2995
2997
  session.streamIds.push(stream.id);
2996
2998
  this._emit(EVENTS.STREAM_ADDED, {
@@ -3139,12 +3141,6 @@ class P2pRtcManager {
3139
3141
  });
3140
3142
  }
3141
3143
  _addTrackToPeerConnections(track) {
3142
- this.analytics.P2PAddTrackToPeerConnections++;
3143
- rtcStats.sendEvent("P2PAddTrackToPeerConnections", {
3144
- trackId: track.id,
3145
- kind: track.kind,
3146
- readyState: track.readyState,
3147
- });
3148
3144
  this._forEachPeerConnection((session) => {
3149
3145
  this._withForcedRenegotiation(session, () => session.addTrack(track));
3150
3146
  });
@@ -3427,7 +3423,11 @@ class P2pRtcManager {
3427
3423
  }, 60 * 1000);
3428
3424
  }
3429
3425
  }
3430
- updateStreamResolution() { }
3426
+ updateStreamResolution(streamId, _ignored, { width, height, }) {
3427
+ const trackId = this._videoTrackIdByStreamId[streamId];
3428
+ if (trackId)
3429
+ updateRenderedDimensions(trackId, { width, height, time: Date.now() });
3430
+ }
3431
3431
  stopOrResumeAudio() {
3432
3432
  }
3433
3433
  _handleStopOrResumeVideo({ enable, track }) {
@@ -5568,7 +5568,7 @@ class VegaRtcManager {
5568
5568
  this._syncIncomingStreamsWithPWA(clientId);
5569
5569
  }
5570
5570
  updateStreamResolution(streamId, _ignored, { width, height, }) {
5571
- var _a, _b;
5571
+ var _a, _b, _c;
5572
5572
  logger$2.info("updateStreamResolution()", { streamId, width, height });
5573
5573
  const consumerId = this._streamIdToVideoConsumerId.get(streamId);
5574
5574
  const consumer = this._consumers.get(consumerId);
@@ -5576,17 +5576,18 @@ class VegaRtcManager {
5576
5576
  this._streamIdToVideoResolution.set(streamId, { width, height });
5577
5577
  return;
5578
5578
  }
5579
+ updateRenderedDimensions((_a = consumer.track) === null || _a === void 0 ? void 0 : _a.id, { width, height, time: Date.now() });
5579
5580
  const numberOfActiveVideos = getNumberOfActiveVideos(this._consumers);
5580
5581
  const numberOfTemporalLayers = getNumberOfTemporalLayers(consumer);
5581
5582
  const { spatialLayer, temporalLayer } = getLayers({ width, height }, {
5582
5583
  numberOfActiveVideos,
5583
5584
  numberOfTemporalLayers,
5584
- uncappedSingleRemoteVideoOn: (_a = this._features) === null || _a === void 0 ? void 0 : _a.uncappedSingleRemoteVideoOn,
5585
+ uncappedSingleRemoteVideoOn: (_b = this._features) === null || _b === void 0 ? void 0 : _b.uncappedSingleRemoteVideoOn,
5585
5586
  });
5586
5587
  if (consumer.appData.spatialLayer !== spatialLayer || consumer.appData.temporalLayer !== temporalLayer) {
5587
5588
  consumer.appData.spatialLayer = spatialLayer;
5588
5589
  consumer.appData.temporalLayer = temporalLayer;
5589
- (_b = this._vegaConnection) === null || _b === void 0 ? void 0 : _b.message("setConsumersPreferredLayers", {
5590
+ (_c = this._vegaConnection) === null || _c === void 0 ? void 0 : _c.message("setConsumersPreferredLayers", {
5590
5591
  consumerIds: [consumerId],
5591
5592
  spatialLayer,
5592
5593
  temporalLayer,
@@ -6001,6 +6002,92 @@ const getRoomMode = () => {
6001
6002
  return roomMode;
6002
6003
  };
6003
6004
 
6005
+ const createQualityDetector = (type) => {
6006
+ return {
6007
+ id: `quality-${type}`,
6008
+ enabled: ({ client }) => !client.isLocalClient && !client.isPresentation,
6009
+ check: ({ ssrc0, renderedDimensions, hasLiveTrack, kind }) => {
6010
+ if (!hasLiveTrack)
6011
+ return true;
6012
+ if (!ssrc0)
6013
+ return true;
6014
+ if (!ssrc0.bitrate)
6015
+ return true;
6016
+ if (kind === "video") {
6017
+ if (renderedDimensions && renderedDimensions.width && renderedDimensions.height) {
6018
+ const maxSideRendered = Math.max(renderedDimensions.width, renderedDimensions.height);
6019
+ const maxSideReceived = Math.max(ssrc0.width || 0, ssrc0.height || 0);
6020
+ const fpsReceived = ssrc0.fps || 0;
6021
+ const hadFreeze = !!ssrc0.freezeRate;
6022
+ const bitrate = ssrc0.bitrate || 0;
6023
+ if (maxSideRendered < 100) {
6024
+ if (type === "warning" && maxSideReceived < 160)
6025
+ return true;
6026
+ if (type === "critical" && maxSideReceived < 90)
6027
+ return true;
6028
+ if (type === "warning" && fpsReceived < 5)
6029
+ return true;
6030
+ if (type === "critical" && fpsReceived < 2)
6031
+ return true;
6032
+ if (type === "warning" && bitrate < 10000)
6033
+ return true;
6034
+ if (type === "critical" && bitrate < 5000)
6035
+ return true;
6036
+ }
6037
+ else if (maxSideRendered < 480) {
6038
+ if (type === "warning" && maxSideReceived < 240)
6039
+ return true;
6040
+ if (type === "critical" && maxSideReceived < 120)
6041
+ return true;
6042
+ if (type === "warning" && fpsReceived < 14)
6043
+ return true;
6044
+ if (type === "critical" && fpsReceived < 9)
6045
+ return true;
6046
+ if (hadFreeze)
6047
+ return true;
6048
+ if (type === "warning" && bitrate < 50000)
6049
+ return true;
6050
+ if (type === "critical" && bitrate < 20000)
6051
+ return true;
6052
+ }
6053
+ else {
6054
+ if (type === "warning" && maxSideReceived < 480)
6055
+ return true;
6056
+ if (type === "critical" && maxSideReceived < 240)
6057
+ return true;
6058
+ if (type === "warning" && fpsReceived < 14)
6059
+ return true;
6060
+ if (type === "critical" && fpsReceived < 9)
6061
+ return true;
6062
+ if (type === "warning" && bitrate < 200000)
6063
+ return true;
6064
+ if (type === "critical" && bitrate < 50000)
6065
+ return true;
6066
+ if (hadFreeze)
6067
+ return true;
6068
+ }
6069
+ }
6070
+ }
6071
+ else if (kind === "audio") {
6072
+ const audioLevel = ssrc0.audioLevel || 0;
6073
+ const concealment = ssrc0.audioConcealment || 0;
6074
+ const acceleration = ssrc0.audioAcceleration || 0;
6075
+ const deceleration = ssrc0.audioDeceleration || 0;
6076
+ const audioDistortion = concealment + acceleration + deceleration;
6077
+ if (audioLevel >= 0.01) {
6078
+ if (type === "warning" && audioDistortion > 0.1)
6079
+ return true;
6080
+ if (type === "critical" && audioDistortion > 0.2)
6081
+ return true;
6082
+ }
6083
+ }
6084
+ return false;
6085
+ },
6086
+ };
6087
+ };
6088
+ const qualityWarningDetector = createQualityDetector("warning");
6089
+ const qualityCriticalDetector = createQualityDetector("critical");
6090
+
6004
6091
  const badNetworkIssueDetector = {
6005
6092
  id: "bad-network",
6006
6093
  enabled: ({ hasLiveTrack, ssrcs }) => hasLiveTrack && ssrcs.length > 0,
@@ -6224,6 +6311,8 @@ const issueDetectors = [
6224
6311
  (ssrc0.audioLevel || 0) >= 0.001 &&
6225
6312
  (ssrc0.audioAcceleration || 0) >= 0.1,
6226
6313
  },
6314
+ qualityWarningDetector,
6315
+ qualityCriticalDetector,
6227
6316
  ];
6228
6317
 
6229
6318
  let subscriptions = [];
@@ -6378,7 +6467,7 @@ function issueDetectorOrMetricEnabled(issueDetectorOrMetric, checkData) {
6378
6467
  }
6379
6468
  return enabled && (issueDetectorOrMetric.enabled ? issueDetectorOrMetric.enabled(checkData) : true);
6380
6469
  }
6381
- function onUpdatedStats(statsByView, clients) {
6470
+ function onUpdatedStats(statsByView, clients, renderedDimensionsByTrack) {
6382
6471
  Object.values(aggregatedMetrics).forEach((metricData) => {
6383
6472
  metricData.curTicks = 0;
6384
6473
  metricData.curSum = 0;
@@ -6416,6 +6505,7 @@ function onUpdatedStats(statsByView, clients) {
6416
6505
  kind,
6417
6506
  track,
6418
6507
  trackStats,
6508
+ renderedDimensions: (track === null || track === void 0 ? void 0 : track.id) ? renderedDimensionsByTrack[track.id] : undefined,
6419
6509
  stats,
6420
6510
  hasLiveTrack,
6421
6511
  ssrc0,
@@ -7408,4 +7498,4 @@ var RtcEventNames;
7408
7498
  RtcEventNames["stream_added"] = "stream_added";
7409
7499
  })(RtcEventNames || (RtcEventNames = {}));
7410
7500
 
7411
- export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
7501
+ export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, updateRenderedDimensions, variance };
@@ -532,13 +532,6 @@ class Session {
532
532
  return;
533
533
  }
534
534
  const stream = this.streams[0];
535
- this._incrementAnalyticMetric("P2PSessionAddTrack");
536
- rtcStats.sendEvent("P2PSessionAddTrack", {
537
- trackId: track.id,
538
- kind: track.kind,
539
- hasSessionStream: !!stream,
540
- trackOfSameKindInStream: !!(stream === null || stream === void 0 ? void 0 : stream.getTracks().filter((t) => t.kind === track.kind && t.id !== track.id).length),
541
- });
542
535
  stream === null || stream === void 0 ? void 0 : stream.addTrack(track);
543
536
  this.pc.addTrack(track, stream);
544
537
  }
@@ -1429,6 +1422,8 @@ function captureVideoSsrcMetrics(ssrcMetrics, currentSsrcStats, prevSsrcStats, t
1429
1422
  const qpsumDiff = currentSsrcStats.qpSum - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.qpSum) || 0);
1430
1423
  ssrcMetrics.qpf = qpsumDiff / frameCountDiff;
1431
1424
  ssrcMetrics.fps = (frameCountDiff * 1000) / timeDiff;
1425
+ const freezeCountDiff = (currentSsrcStats.freezeCount || 0) - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.freezeCount) || 0);
1426
+ ssrcMetrics.freezeRate = (freezeCountDiff * 1000) / timeDiff;
1432
1427
  }
1433
1428
  else {
1434
1429
  const kfCountDiff = currentSsrcStats.keyFramesEncoded - ((prevSsrcStats === null || prevSsrcStats === void 0 ? void 0 : prevSsrcStats.keyFramesEncoded) || 0);
@@ -1574,15 +1569,17 @@ const getOrCreateSsrcMetricsContainer = (statsByView, time, pcIndex, clientId, t
1574
1569
  ssrcStats.updated = time;
1575
1570
  return ssrcStats;
1576
1571
  };
1577
- const removeNonUpdatedStats = (statsByView, time) => {
1572
+ const removeNonUpdatedStats = (statsByView, time, renderedDimensionsByTrack) => {
1578
1573
  Object.entries(statsByView).forEach(([viewId, viewStats]) => {
1579
1574
  if (viewStats.updated !== undefined && viewStats.updated < time) {
1575
+ Object.keys(viewStats.tracks).forEach((trackId) => delete renderedDimensionsByTrack[trackId]);
1580
1576
  delete statsByView[viewId];
1581
1577
  }
1582
1578
  else {
1583
1579
  Object.entries(viewStats.tracks).forEach(([trackId, trackStats]) => {
1584
1580
  if (trackStats.updated < time) {
1585
1581
  delete viewStats.tracks[trackId];
1582
+ delete renderedDimensionsByTrack[trackId];
1586
1583
  }
1587
1584
  else {
1588
1585
  Object.entries(trackStats.ssrcs).forEach(([ssrc, ssrcStats]) => {
@@ -1620,7 +1617,7 @@ function collectStats(state_1, _a, immediate_1) {
1620
1617
  if (timeSinceLastUpdate < 400) {
1621
1618
  if (immediate)
1622
1619
  return state.statsByView;
1623
- state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients); });
1620
+ state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients, state.renderedDimensionsByTrack); });
1624
1621
  state.nextTimeout = setTimeout(collectStatsBound, interval);
1625
1622
  return;
1626
1623
  }
@@ -1713,7 +1710,7 @@ function collectStats(state_1, _a, immediate_1) {
1713
1710
  }
1714
1711
  });
1715
1712
  });
1716
- removeNonUpdatedStats(state.statsByView, state.lastUpdateTime);
1713
+ removeNonUpdatedStats(state.statsByView, state.lastUpdateTime, state.renderedDimensionsByTrack);
1717
1714
  Object.entries((defaultViewStats === null || defaultViewStats === void 0 ? void 0 : defaultViewStats.candidatePairs) || {}).forEach(([cpKey, cp]) => {
1718
1715
  const active = cp.lastRtcStatsTime === state.lastUpdateTime;
1719
1716
  cp.active = active;
@@ -1732,7 +1729,7 @@ function collectStats(state_1, _a, immediate_1) {
1732
1729
  return state.statsByView;
1733
1730
  }
1734
1731
  else {
1735
- state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients); });
1732
+ state.subscriptions.forEach((subscription) => { var _a; return (_a = subscription.onUpdatedStats) === null || _a === void 0 ? void 0 : _a.call(subscription, state.statsByView, clients, state.renderedDimensionsByTrack); });
1736
1733
  }
1737
1734
  }
1738
1735
  catch (e) {
@@ -1771,6 +1768,7 @@ const STATE = {
1771
1768
  currentMonitor: null,
1772
1769
  getClients: () => [],
1773
1770
  lastUpdateTime: 0,
1771
+ renderedDimensionsByTrack: {},
1774
1772
  statsByView: {},
1775
1773
  subscriptions: [],
1776
1774
  numFailedStatsReports: 0,
@@ -1789,6 +1787,9 @@ const getNumMissingTrackSsrcLookups = () => numMissingTrackSsrcLookups;
1789
1787
  const getNumFailedTrackSsrcLookups = () => numFailedTrackSsrcLookups;
1790
1788
  const getUpdatedStats = () => { var _a; return (_a = STATE.currentMonitor) === null || _a === void 0 ? void 0 : _a.getUpdatedStats(); };
1791
1789
  const setClientProvider = (provider) => (STATE.getClients = provider);
1790
+ const updateRenderedDimensions = (trackId, data) => {
1791
+ STATE.renderedDimensionsByTrack[trackId] = data;
1792
+ };
1792
1793
  function startStatsMonitor(state, { interval, logger }) {
1793
1794
  const collectStatsBound = collectStats.bind(null, state, { interval, logger });
1794
1795
  let cpuObserver;
@@ -2509,6 +2510,7 @@ class P2pRtcManager {
2509
2510
  this._features = features || {};
2510
2511
  this._isAudioOnlyMode = false;
2511
2512
  this._closed = false;
2513
+ this._videoTrackIdByStreamId = {};
2512
2514
  this._fetchMediaServersTimer = null;
2513
2515
  this._stopCameraTimeout = null;
2514
2516
  this._icePublicIPGatheringTimeoutID = null;
@@ -2554,8 +2556,6 @@ class P2pRtcManager {
2554
2556
  P2PMicNotWorking: 0,
2555
2557
  P2PLocalNetworkFailed: 0,
2556
2558
  P2PRelayedIceCandidate: 0,
2557
- P2PSessionAddTrack: 0,
2558
- P2PAddTrackToPeerConnections: 0,
2559
2559
  P2PAddIceCandidateFailure: 0,
2560
2560
  };
2561
2561
  }
@@ -2991,6 +2991,8 @@ class P2pRtcManager {
2991
2991
  });
2992
2992
  return;
2993
2993
  }
2994
+ if (event.track.kind === "video")
2995
+ this._videoTrackIdByStreamId[stream.id] = event.track.id;
2994
2996
  if (session.streamIds.indexOf(stream.id) === -1) {
2995
2997
  session.streamIds.push(stream.id);
2996
2998
  this._emit(EVENTS.STREAM_ADDED, {
@@ -3139,12 +3141,6 @@ class P2pRtcManager {
3139
3141
  });
3140
3142
  }
3141
3143
  _addTrackToPeerConnections(track) {
3142
- this.analytics.P2PAddTrackToPeerConnections++;
3143
- rtcStats.sendEvent("P2PAddTrackToPeerConnections", {
3144
- trackId: track.id,
3145
- kind: track.kind,
3146
- readyState: track.readyState,
3147
- });
3148
3144
  this._forEachPeerConnection((session) => {
3149
3145
  this._withForcedRenegotiation(session, () => session.addTrack(track));
3150
3146
  });
@@ -3427,7 +3423,11 @@ class P2pRtcManager {
3427
3423
  }, 60 * 1000);
3428
3424
  }
3429
3425
  }
3430
- updateStreamResolution() { }
3426
+ updateStreamResolution(streamId, _ignored, { width, height, }) {
3427
+ const trackId = this._videoTrackIdByStreamId[streamId];
3428
+ if (trackId)
3429
+ updateRenderedDimensions(trackId, { width, height, time: Date.now() });
3430
+ }
3431
3431
  stopOrResumeAudio() {
3432
3432
  }
3433
3433
  _handleStopOrResumeVideo({ enable, track }) {
@@ -5568,7 +5568,7 @@ class VegaRtcManager {
5568
5568
  this._syncIncomingStreamsWithPWA(clientId);
5569
5569
  }
5570
5570
  updateStreamResolution(streamId, _ignored, { width, height, }) {
5571
- var _a, _b;
5571
+ var _a, _b, _c;
5572
5572
  logger$2.info("updateStreamResolution()", { streamId, width, height });
5573
5573
  const consumerId = this._streamIdToVideoConsumerId.get(streamId);
5574
5574
  const consumer = this._consumers.get(consumerId);
@@ -5576,17 +5576,18 @@ class VegaRtcManager {
5576
5576
  this._streamIdToVideoResolution.set(streamId, { width, height });
5577
5577
  return;
5578
5578
  }
5579
+ updateRenderedDimensions((_a = consumer.track) === null || _a === void 0 ? void 0 : _a.id, { width, height, time: Date.now() });
5579
5580
  const numberOfActiveVideos = getNumberOfActiveVideos(this._consumers);
5580
5581
  const numberOfTemporalLayers = getNumberOfTemporalLayers(consumer);
5581
5582
  const { spatialLayer, temporalLayer } = getLayers({ width, height }, {
5582
5583
  numberOfActiveVideos,
5583
5584
  numberOfTemporalLayers,
5584
- uncappedSingleRemoteVideoOn: (_a = this._features) === null || _a === void 0 ? void 0 : _a.uncappedSingleRemoteVideoOn,
5585
+ uncappedSingleRemoteVideoOn: (_b = this._features) === null || _b === void 0 ? void 0 : _b.uncappedSingleRemoteVideoOn,
5585
5586
  });
5586
5587
  if (consumer.appData.spatialLayer !== spatialLayer || consumer.appData.temporalLayer !== temporalLayer) {
5587
5588
  consumer.appData.spatialLayer = spatialLayer;
5588
5589
  consumer.appData.temporalLayer = temporalLayer;
5589
- (_b = this._vegaConnection) === null || _b === void 0 ? void 0 : _b.message("setConsumersPreferredLayers", {
5590
+ (_c = this._vegaConnection) === null || _c === void 0 ? void 0 : _c.message("setConsumersPreferredLayers", {
5590
5591
  consumerIds: [consumerId],
5591
5592
  spatialLayer,
5592
5593
  temporalLayer,
@@ -6001,6 +6002,92 @@ const getRoomMode = () => {
6001
6002
  return roomMode;
6002
6003
  };
6003
6004
 
6005
+ const createQualityDetector = (type) => {
6006
+ return {
6007
+ id: `quality-${type}`,
6008
+ enabled: ({ client }) => !client.isLocalClient && !client.isPresentation,
6009
+ check: ({ ssrc0, renderedDimensions, hasLiveTrack, kind }) => {
6010
+ if (!hasLiveTrack)
6011
+ return true;
6012
+ if (!ssrc0)
6013
+ return true;
6014
+ if (!ssrc0.bitrate)
6015
+ return true;
6016
+ if (kind === "video") {
6017
+ if (renderedDimensions && renderedDimensions.width && renderedDimensions.height) {
6018
+ const maxSideRendered = Math.max(renderedDimensions.width, renderedDimensions.height);
6019
+ const maxSideReceived = Math.max(ssrc0.width || 0, ssrc0.height || 0);
6020
+ const fpsReceived = ssrc0.fps || 0;
6021
+ const hadFreeze = !!ssrc0.freezeRate;
6022
+ const bitrate = ssrc0.bitrate || 0;
6023
+ if (maxSideRendered < 100) {
6024
+ if (type === "warning" && maxSideReceived < 160)
6025
+ return true;
6026
+ if (type === "critical" && maxSideReceived < 90)
6027
+ return true;
6028
+ if (type === "warning" && fpsReceived < 5)
6029
+ return true;
6030
+ if (type === "critical" && fpsReceived < 2)
6031
+ return true;
6032
+ if (type === "warning" && bitrate < 10000)
6033
+ return true;
6034
+ if (type === "critical" && bitrate < 5000)
6035
+ return true;
6036
+ }
6037
+ else if (maxSideRendered < 480) {
6038
+ if (type === "warning" && maxSideReceived < 240)
6039
+ return true;
6040
+ if (type === "critical" && maxSideReceived < 120)
6041
+ return true;
6042
+ if (type === "warning" && fpsReceived < 14)
6043
+ return true;
6044
+ if (type === "critical" && fpsReceived < 9)
6045
+ return true;
6046
+ if (hadFreeze)
6047
+ return true;
6048
+ if (type === "warning" && bitrate < 50000)
6049
+ return true;
6050
+ if (type === "critical" && bitrate < 20000)
6051
+ return true;
6052
+ }
6053
+ else {
6054
+ if (type === "warning" && maxSideReceived < 480)
6055
+ return true;
6056
+ if (type === "critical" && maxSideReceived < 240)
6057
+ return true;
6058
+ if (type === "warning" && fpsReceived < 14)
6059
+ return true;
6060
+ if (type === "critical" && fpsReceived < 9)
6061
+ return true;
6062
+ if (type === "warning" && bitrate < 200000)
6063
+ return true;
6064
+ if (type === "critical" && bitrate < 50000)
6065
+ return true;
6066
+ if (hadFreeze)
6067
+ return true;
6068
+ }
6069
+ }
6070
+ }
6071
+ else if (kind === "audio") {
6072
+ const audioLevel = ssrc0.audioLevel || 0;
6073
+ const concealment = ssrc0.audioConcealment || 0;
6074
+ const acceleration = ssrc0.audioAcceleration || 0;
6075
+ const deceleration = ssrc0.audioDeceleration || 0;
6076
+ const audioDistortion = concealment + acceleration + deceleration;
6077
+ if (audioLevel >= 0.01) {
6078
+ if (type === "warning" && audioDistortion > 0.1)
6079
+ return true;
6080
+ if (type === "critical" && audioDistortion > 0.2)
6081
+ return true;
6082
+ }
6083
+ }
6084
+ return false;
6085
+ },
6086
+ };
6087
+ };
6088
+ const qualityWarningDetector = createQualityDetector("warning");
6089
+ const qualityCriticalDetector = createQualityDetector("critical");
6090
+
6004
6091
  const badNetworkIssueDetector = {
6005
6092
  id: "bad-network",
6006
6093
  enabled: ({ hasLiveTrack, ssrcs }) => hasLiveTrack && ssrcs.length > 0,
@@ -6224,6 +6311,8 @@ const issueDetectors = [
6224
6311
  (ssrc0.audioLevel || 0) >= 0.001 &&
6225
6312
  (ssrc0.audioAcceleration || 0) >= 0.1,
6226
6313
  },
6314
+ qualityWarningDetector,
6315
+ qualityCriticalDetector,
6227
6316
  ];
6228
6317
 
6229
6318
  let subscriptions = [];
@@ -6378,7 +6467,7 @@ function issueDetectorOrMetricEnabled(issueDetectorOrMetric, checkData) {
6378
6467
  }
6379
6468
  return enabled && (issueDetectorOrMetric.enabled ? issueDetectorOrMetric.enabled(checkData) : true);
6380
6469
  }
6381
- function onUpdatedStats(statsByView, clients) {
6470
+ function onUpdatedStats(statsByView, clients, renderedDimensionsByTrack) {
6382
6471
  Object.values(aggregatedMetrics).forEach((metricData) => {
6383
6472
  metricData.curTicks = 0;
6384
6473
  metricData.curSum = 0;
@@ -6416,6 +6505,7 @@ function onUpdatedStats(statsByView, clients) {
6416
6505
  kind,
6417
6506
  track,
6418
6507
  trackStats,
6508
+ renderedDimensions: (track === null || track === void 0 ? void 0 : track.id) ? renderedDimensionsByTrack[track.id] : undefined,
6419
6509
  stats,
6420
6510
  hasLiveTrack,
6421
6511
  ssrc0,
@@ -7408,5 +7498,5 @@ var RtcEventNames;
7408
7498
  RtcEventNames["stream_added"] = "stream_added";
7409
7499
  })(RtcEventNames || (RtcEventNames = {}));
7410
7500
 
7411
- export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
7501
+ export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, FILE_SHARE_ERROR_CODES, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isFileShareError, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, updateRenderedDimensions, variance };
7412
7502
  //# sourceMappingURL=legacy-esm.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@whereby.com/media",
3
3
  "description": "Media library for Whereby",
4
- "version": "9.2.6",
4
+ "version": "9.3.0",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/whereby/sdk",
7
7
  "repository": {