@3dsource/angular-unreal-module 0.0.113-dev.1 → 0.0.113-dev.2

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, ChangeDetectionStrategy, Component, Injectable, DestroyRef, effect, untracked, signal, computed, Pipe, input, ElementRef, viewChild, afterNextRender, HostListener, output, makeEnvironmentProviders, provideEnvironmentInitializer } from '@angular/core';
3
3
  import { SourceButtonComponent, SourceLoadingComponent } from '@3dsource/source-ui-native';
4
- import { merge, map, scan, concatMap, of, animationFrameScheduler, interval, Observable, skip, switchMap, concat, delay, debounceTime, timer, take, timeout, mergeMap, EMPTY, Subject, share, from, fromEvent, throwError, defer, retry, tap as tap$1, takeUntil as takeUntil$1, NEVER, startWith, throttleTime, asyncScheduler, filter as filter$1, withLatestFrom as withLatestFrom$1, pairwise, Subscription, bufferTime, combineLatestWith, distinctUntilChanged as distinctUntilChanged$1 } from 'rxjs';
4
+ import { merge, map, scan, concatMap, of, animationFrameScheduler, interval, Observable, skip, switchMap, concat, delay, debounceTime, timer, take, timeout, mergeMap, EMPTY, Subject, share, takeUntil as takeUntil$1, from, fromEvent, throwError, defer, retry, tap as tap$1, NEVER, startWith, throttleTime, asyncScheduler, filter as filter$1, withLatestFrom as withLatestFrom$1, pairwise, Subscription, bufferTime, combineLatestWith, distinctUntilChanged as distinctUntilChanged$1 } from 'rxjs';
5
5
  import { createAction, props, createReducer, on, createFeature, createSelector, Store, provideState } from '@ngrx/store';
6
6
  import { Actions, createEffect, ofType, provideEffects } from '@ngrx/effects';
7
7
  import { map as map$1, distinctUntilChanged, takeWhile, filter, tap, takeUntil, catchError, withLatestFrom, exhaustMap, switchMap as switchMap$1, timeout as timeout$1, debounceTime as debounceTime$1, take as take$1, startWith as startWith$1 } from 'rxjs/operators';
@@ -211,7 +211,7 @@ const WS_TIMEOUT = 2000;
211
211
  const POLLING_TIME = 4000;
212
212
  const WS_OPEN_STATE = 1;
213
213
  const DEFAULT_AFK_TIMEOUT_PERIOD = 15;
214
- const DEFAULT_AFK_TIMEOUT = 10;
214
+ const DEFAULT_AFK_TIMEOUT = 120;
215
215
  const DATA_CHANNEL_CONNECTION_TIMEOUT = 8000; //ms;
216
216
  const SIGNALLING_PERCENT_VALUE = 56;
217
217
  const SCREEN_LOCKER_CONTAINER_ID = '3dsource_start_screen';
@@ -232,7 +232,7 @@ const commandStarted = createAction(scoped$1 `command started`, props());
232
232
  const commandCompleted = createAction(scoped$1 `command completed`, props());
233
233
 
234
234
  const scoped = (templateString) => `[UNREAL] ${templateString[0]}`;
235
- const trackMixpanelEvent = createAction(scoped `track mixpanel event`, props());
235
+ const trackMixpanelEvent = createAction(scoped `track Mixpanel event`, props());
236
236
  const trackTelemetryData = createAction(scoped `track telemetry data`, props());
237
237
  const setMaxFps = createAction(scoped `change fps`, props());
238
238
  const destroyRemoteConnections = createAction(scoped `destroyRemoteConnections`, props());
@@ -278,9 +278,9 @@ const instanceReady = createAction(scoped `instance ready`);
278
278
  const regionPingFetchStart = createAction(scoped `region ping fetch start`);
279
279
  /**
280
280
  * Dispatched once `RegionsPingService.getProviders()` returns the region
281
- * list — i.e. the fetch step is done and the actual per-region ping
281
+ * list — i.e., the fetch step is done and the actual per-region ping
282
282
  * sweep is about to start. Splits the region-discovery waterfall into
283
- * two legs: config fetch vs ping sweep. Observability-only.
283
+ * two legs: config fetch vs. ping sweep. Observability-only.
284
284
  */
285
285
  const regionPingFetchEnd = createAction(scoped `region ping fetch end`);
286
286
  /**
@@ -292,9 +292,9 @@ const regionPingFetchEnd = createAction(scoped `region ping fetch end`);
292
292
  */
293
293
  const regionResolved = createAction(scoped `region resolved`, props());
294
294
  /**
295
- * Dispatched around the HTTP polling roundtrip inside `getAwsInstance`
295
+ * Dispatched around the HTTP polling roundup inside `getAwsInstance`
296
296
  * (old orchestration flow). Only fires when polling is actually used
297
- * (i.e. signaling URL is not a direct `ws://` / `wss://` endpoint).
297
+ * (i.e., signaling URL is not a direct `ws://` / `wss://` endpoint).
298
298
  * Observability-only — no state change.
299
299
  */
300
300
  const pollingStarted = createAction(scoped `polling started`);
@@ -1131,7 +1131,6 @@ const commandsFeature = createFeature({
1131
1131
  reducer: commandsReducer,
1132
1132
  });
1133
1133
 
1134
- const selectCommandsInProgress = createSelector(commandsFeature.selectCommandsInProgress, (commandsInProgress) => commandsInProgress?.length ?? 0);
1135
1134
  const selectCommandProgress = createSelector(commandsFeature.selectTotalCommandsStarted, commandsFeature.selectTotalCommandsCompleted, (totalCommandsStarted, totalCommandsCompleted) => totalCommandsStarted ? totalCommandsCompleted / totalCommandsStarted : 0);
1136
1135
 
1137
1136
  const selectFreezeFrameDataUrlFromVideo = createSelector(unrealFeature.selectFreezeFrameFromVideo, (freezeFrameFromVideo) => freezeFrameFromVideo?.dataUrl || null);
@@ -1147,7 +1146,6 @@ const selectIsExistMatchUrls = createSelector(unrealFeature.selectMatchUrls, (ur
1147
1146
  const selectIsAutostart = createSelector(selectStreamConfig, (config) => config?.autoStart);
1148
1147
  const selectShowReconnectPopup = createSelector(unrealFeature.selectCirrusConnected, unrealFeature.selectEstablishingConnection, (cirrusConnected, establishingConnection) => !cirrusConnected && !establishingConnection);
1149
1148
  const selectShowLoader = createSelector(selectShowReconnectPopup, unrealFeature.selectViewportReady, (showPopup, viewportReady) => !showPopup && !viewportReady);
1150
- const selectIsVideoPlayingAndDataChannelConnected = createSelector(unrealFeature.selectIsVideoPlaying, unrealFeature.selectDataChannelConnected, (isVideoPlaying, isDataChannelConnected) => isVideoPlaying && isDataChannelConnected);
1151
1149
  const selectSignalingParameters = createSelector(unrealFeature.selectSsData, unrealFeature.selectAwsInstance, (data, instance) => {
1152
1150
  const info = [];
1153
1151
  if (data) {
@@ -1243,34 +1241,12 @@ class UnrealEffects {
1243
1241
  onDataChannelClose: this.unrealInitialConfig?.reconnect?.onDataChannelClose ??
1244
1242
  DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE,
1245
1243
  };
1246
- this.disconnectReasonHandling$ = createEffect(() => {
1247
- return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => {
1248
- // Skip DataChannelClosed if peer reconnection will handle this case
1249
- if (reason === DisconnectReason.DataChannelClosed &&
1250
- this.canPeerReconnect()) {
1251
- Logger.info('[Reconnect] Skipping destroy for DataChannelClosed - peer reconnection will handle');
1252
- return false;
1253
- }
1254
- return DESTROY_DISCONNECT_REASONS.includes(reason);
1255
- }), tap(({ reason, message }) => {
1256
- Logger.log(`Disconnect Call=> reason:'${reason}', message:'${message}'`);
1257
- }), map(({ reason }) => destroyRemoteConnections({ reason })));
1258
- });
1259
1244
  this.destroyConnections$ = createEffect(() => {
1260
1245
  return this.actions$.pipe(ofType(destroyUnrealScene), tap(() => {
1261
1246
  this.commandsSender.destroy();
1262
1247
  this.videoService.setContainer(null);
1263
1248
  }), map(() => destroyRemoteConnections({ reason: DisconnectReason.Destroy })));
1264
1249
  });
1265
- this.destroyRemoteConnections$ = createEffect(() => {
1266
- return this.actions$.pipe(ofType(destroyRemoteConnections), tap(({ reason }) => {
1267
- this.signallingService.close({
1268
- code: WSCloseCode_FORCE_CIRRUS_CLOSE,
1269
- reason,
1270
- });
1271
- this.webRtcPlayerService.closePC();
1272
- }), filter(({ reason }) => reason === DisconnectReason.DropConnection), map(() => dropConnection()));
1273
- });
1274
1250
  this.changeStreamResolution$ = createEffect(() => {
1275
1251
  return this.actions$.pipe(ofType(changeStreamResolutionAction), filter((size) => !!(size?.width && size?.height)), concatLatestFrom(() => this.store.select(unrealFeature.selectStreamResolution)), filter(([newSizes, savedSizes]) => !(newSizes.width === savedSizes.width &&
1276
1252
  newSizes.height === savedSizes.height)), map(([sizes]) => changeStreamResolutionSuccessAction({
@@ -1282,7 +1258,7 @@ class UnrealEffects {
1282
1258
  return this.actions$.pipe(ofType(setConfig, setUserInactivityTimeout, resetWarnTimeout, resetConfig), map(() => resetAfk()));
1283
1259
  });
1284
1260
  this.abortEstablishingConnection$ = createEffect(() => {
1285
- return merge(this.store.select(unrealFeature.selectViewportReady).pipe(filter(Truthy)), this.actions$.pipe(ofType(setCirrusDisconnected, destroyUnrealScene, dropConnection))).pipe(map(() => abortEstablishingConnection()));
1261
+ return this.actions$.pipe(ofType(setCirrusDisconnected, dropConnection, destroyUnrealScene), map(() => abortEstablishingConnection()));
1286
1262
  });
1287
1263
  this.iframeMessaging$ = createEffect(() => {
1288
1264
  const cirrusConnected$ = this.store
@@ -1347,8 +1323,35 @@ class UnrealEffects {
1347
1323
  }));
1348
1324
  }));
1349
1325
  });
1326
+ /**
1327
+ * Effect: `forceViewportNotReady$`
1328
+ *
1329
+ * Ensures the viewport is explicitly marked as *not ready* to prevent
1330
+ * a temporary black screen flash when disconnecting.
1331
+ *
1332
+ * ### Why
1333
+ * - The video stream is disconnected immediately.
1334
+ * - The DataChannel closes slightly later.
1335
+ * - Closing the DataChannel resets the Unreal scene,
1336
+ * which also sets `viewPortReady` to `false`.
1337
+ *
1338
+ * Without this effect, the order of these events may cause
1339
+ * a visible flicker (video flashing to black).
1340
+ */
1341
+ this.forceViewportNotReady$ = createEffect(() => {
1342
+ return this.actions$.pipe(ofType(destroyRemoteConnections), concatLatestFrom(() => this.store.select(unrealFeature.selectViewportReady)), filter(([, viewportReady]) => viewportReady), map(() => setViewportNotReady()));
1343
+ });
1350
1344
  this.resetCirrusOnDestroy$ = createEffect(() => {
1351
- return this.actions$.pipe(ofType(destroyRemoteConnections), map(() => setCirrusDisconnected()));
1345
+ return this.actions$.pipe(ofType(destroyRemoteConnections), concatLatestFrom(() => this.store.select(unrealFeature.selectCirrusConnected)), filter(([, cirrusConnected]) => cirrusConnected), map(() => setCirrusDisconnected()));
1346
+ });
1347
+ this.destroyRemoteConnections$ = createEffect(() => {
1348
+ return this.actions$.pipe(ofType(destroyRemoteConnections), tap(({ reason }) => {
1349
+ this.signallingService.close({
1350
+ code: WSCloseCode_FORCE_CIRRUS_CLOSE,
1351
+ reason,
1352
+ });
1353
+ this.webRtcPlayerService.closePC();
1354
+ }), filter(({ reason }) => reason === DisconnectReason.DropConnection), map(() => dropConnection()));
1352
1355
  });
1353
1356
  this.destroyConnectionAndRestart$ = createEffect(() => {
1354
1357
  return this.actions$.pipe(ofType(setCirrusDisconnected), concatLatestFrom(() => this.store.select(unrealFeature.selectDisconnectReason)), filter(([, reason]) => reason === DisconnectReason.DataChannelTimeout), map(() => initSignalling()));
@@ -1390,24 +1393,6 @@ class UnrealEffects {
1390
1393
  this.resetAfkOnVideoStart$ = createEffect(() => {
1391
1394
  return this.actions$.pipe(ofType(videoStreamInitialized), filter(() => !!this.videoService.video?.paused), tap(() => Logger.info('Simulate Press Play')), map(() => resetAfk()));
1392
1395
  });
1393
- /**
1394
- * Effect: `forceViewportNotReady$`
1395
- *
1396
- * Ensures the viewport is explicitly marked as *not ready* to prevent
1397
- * a temporary black screen flash when disconnecting.
1398
- *
1399
- * ### Why
1400
- * - The video stream is disconnected immediately.
1401
- * - The DataChannel closes slightly later.
1402
- * - Closing the DataChannel resets the Unreal scene,
1403
- * which also sets `viewPortReady` to `false`.
1404
- *
1405
- * Without this effect, the order of these events may cause
1406
- * a visible flicker (video flashing to black).
1407
- */
1408
- this.forceViewportNotReady$ = createEffect(() => {
1409
- return this.actions$.pipe(ofType(destroyRemoteConnections), map(() => setViewportNotReady()));
1410
- });
1411
1396
  /**
1412
1397
  * Effect: `handleDataChannelClosed$`
1413
1398
  *
@@ -1415,6 +1400,19 @@ class UnrealEffects {
1415
1400
  * Only triggers if reconnection is enabled, onDataChannelClose is true,
1416
1401
  * and the signaling WebSocket is still connected.
1417
1402
  */
1403
+ this.disconnectReasonHandling$ = createEffect(() => {
1404
+ return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => {
1405
+ // Skip DataChannelClosed if peer reconnection will handle this case
1406
+ if (reason === DisconnectReason.DataChannelClosed &&
1407
+ this.canPeerReconnect()) {
1408
+ Logger.info('[Reconnect] Skipping destroy for DataChannelClosed - peer reconnection will handle');
1409
+ return false;
1410
+ }
1411
+ return DESTROY_DISCONNECT_REASONS.includes(reason);
1412
+ }), tap(({ reason, message }) => {
1413
+ Logger.log(`Disconnect Call=> reason:'${reason}', message:'${message}'`);
1414
+ }), map(({ reason }) => destroyRemoteConnections({ reason })));
1415
+ });
1418
1416
  this.handleDataChannelClosed$ = createEffect(() => {
1419
1417
  return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => reason === DisconnectReason.DataChannelClosed &&
1420
1418
  this.canPeerReconnect()), tap(() => {
@@ -1425,6 +1423,11 @@ class UnrealEffects {
1425
1423
  delay: 0,
1426
1424
  })));
1427
1425
  });
1426
+ this.webrtcErrorModalComponent$ = createEffect(() => {
1427
+ return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => reason === DisconnectReason.WebRTCError), debounceTime(400), switchMap(() => this.store
1428
+ .select(unrealFeature.selectDataChannelConnected)
1429
+ .pipe(take(1), filter(Falsy))), tap(() => this.dialog.open(WebrtcErrorModalComponent)));
1430
+ }, { dispatch: false });
1428
1431
  /**
1429
1432
  * Effect: `resetStateForPeerReconnect$`
1430
1433
  *
@@ -1496,11 +1499,6 @@ class UnrealEffects {
1496
1499
  });
1497
1500
  }));
1498
1501
  }, { dispatch: false });
1499
- this.webrtcErrorModalComponent$ = createEffect(() => {
1500
- return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => reason === DisconnectReason.WebRTCError), debounceTime(400), switchMap(() => this.store
1501
- .select(unrealFeature.selectDataChannelConnected)
1502
- .pipe(take(1), filter(Falsy))), tap(() => this.dialog.open(WebrtcErrorModalComponent)));
1503
- }, { dispatch: false });
1504
1502
  this.sendStatisticsToUnreal$ = createEffect(() => {
1505
1503
  return this.actions$.pipe(ofType(showUnrealErrorMessage), filter(({ code }) => code === 404), withLatestFrom(this.store.select(unrealFeature.selectAwsInstance), this.store.select(unrealFeature.selectStreamClientCompanyId), this.store.select(unrealFeature.selectStreamViewId)), switchMap(([action, instance, companyId, viewId]) => this.http
1506
1504
  .post(this.unrealInitialConfig?.customErrorsEndpoint || '', {
@@ -1590,14 +1588,12 @@ class AFKService extends SubService {
1590
1588
  this.active = false; // Whether the AFK system is currently looking for inactivity.
1591
1589
  this.countdown = 0;
1592
1590
  this.warnTimeout = this.store.selectSignal(selectWarnTimeout);
1591
+ this.isAfkTimerVisible = this.store.selectSignal(unrealFeature.selectIsAfkTimerVisible);
1593
1592
  this.isViewportReady = this.store.selectSignal(unrealFeature.selectViewportReady);
1594
1593
  this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
1595
1594
  /** Ticks every time warnTimeout changes or resetAfk action fires */
1596
1595
  this.afkResetTrigger = toSignal(merge(this.store.select(selectWarnTimeout), this.actions$.pipe(ofType(resetAfk))));
1597
- /** Ticks when cirrus disconnects */
1598
1596
  this.disconnected = toSignal(this.disconnect$);
1599
- /** Ticks when resetUserInactivityTimeout action fires */
1600
- this.resetUserInactivityTrigger = toSignal(this.actions$.pipe(ofType(resetUserInactivityTimeout)));
1601
1597
  this.destroyRef.onDestroy(() => this.clearTimers());
1602
1598
  if (this.unrealConfig?.playwright) {
1603
1599
  return;
@@ -1618,20 +1614,20 @@ class AFKService extends SubService {
1618
1614
  untracked(() => this.startAfkWarningTimer());
1619
1615
  }
1620
1616
  });
1621
- // Stop on disconnect
1622
1617
  effect(() => {
1623
1618
  const disconnected = this.disconnected();
1624
1619
  if (disconnected !== undefined) {
1625
1620
  untracked(() => this.stop());
1626
1621
  }
1627
1622
  });
1628
- // Full reset (hide overlay + restart warning timer) on external request
1629
- effect(() => {
1630
- this.resetUserInactivityTrigger();
1631
- untracked(() => this.reset());
1632
- });
1623
+ this.actions$
1624
+ .pipe(ofType(resetUserInactivityTimeout), takeUntil$1(this.destroy$))
1625
+ .subscribe(() => this.reset());
1633
1626
  }
1634
1627
  hideOverlay() {
1628
+ if (!this.isAfkTimerVisible()) {
1629
+ return;
1630
+ }
1635
1631
  this.store.dispatch(setAfkTimerHide());
1636
1632
  }
1637
1633
  /**
@@ -1842,6 +1838,7 @@ const BITRATE_MONITOR = new DataFlowMonitor(FilterModel.yellowFlag, FilterModel.
1842
1838
  class VideoService extends SubService {
1843
1839
  constructor() {
1844
1840
  super(...arguments);
1841
+ this.isVideoPlaying = this.store.selectSignal(unrealFeature.selectIsVideoPlaying);
1845
1842
  this.video = null;
1846
1843
  this.audio = null;
1847
1844
  this.container = null;
@@ -2065,6 +2062,7 @@ class VideoService extends SubService {
2065
2062
  if (!this.video) {
2066
2063
  return;
2067
2064
  }
2065
+ this.changeStatusMainVideoOnScene(false);
2068
2066
  this.video = null;
2069
2067
  this.audio = null;
2070
2068
  this.videoTrack$.next(null);
@@ -2076,7 +2074,12 @@ class VideoService extends SubService {
2076
2074
  while (this.container?.firstChild) {
2077
2075
  this.container.removeChild(this.container.firstChild);
2078
2076
  }
2079
- this.store.dispatch(changeStatusMainVideoOnScene({ isVideoPlaying: false }));
2077
+ }
2078
+ changeStatusMainVideoOnScene(isVideoPlaying) {
2079
+ if (this.isVideoPlaying() === isVideoPlaying) {
2080
+ return;
2081
+ }
2082
+ this.store.dispatch(changeStatusMainVideoOnScene({ isVideoPlaying }));
2080
2083
  }
2081
2084
  createWebRtcVideo() {
2082
2085
  dispatchResize();
@@ -2089,14 +2092,10 @@ class VideoService extends SubService {
2089
2092
  video.disablePictureInPicture = true;
2090
2093
  this.video = video;
2091
2094
  this.container?.appendChild(this.video);
2092
- this.video.addEventListener('play', () => this.store.dispatch(changeStatusMainVideoOnScene({ isVideoPlaying: true })));
2095
+ this.video.addEventListener('play', () => this.changeStatusMainVideoOnScene(true));
2093
2096
  fromEvent(this.video, 'loadedmetadata')
2094
- .pipe(take(1), filter((data) => this.video === data.target), tapLog('VideoService loadedmetadata:'))
2095
- .subscribe(() => {
2096
- if (this.video) {
2097
- this.store.dispatch(videoStreamInitialized());
2098
- }
2099
- });
2097
+ .pipe(take(1), filter((data) => this.video === data.target), tapLog('VideoService loadedmetadata:'), filter(() => !!this.video))
2098
+ .subscribe(() => this.store.dispatch(videoStreamInitialized()));
2100
2099
  }
2101
2100
  createWebRtcAudio() {
2102
2101
  const audio = new Audio();
@@ -3898,6 +3897,10 @@ class DevModeService {
3898
3897
  get isDevMode() {
3899
3898
  return Truthy(localStorage.getItem('devMode'));
3900
3899
  }
3900
+ /**
3901
+ * Called from the browser console to toggle dev mode at runtime.
3902
+ * @preserve
3903
+ */
3901
3904
  setDevMode(value) {
3902
3905
  if (value) {
3903
3906
  localStorage.setItem('devMode', value.toString());
@@ -4727,7 +4730,7 @@ class StreamStatusTelemetryService2 {
4727
4730
  /**
4728
4731
  * Whether a session has already started during the current page lifetime.
4729
4732
  * Used to distinguish a fresh page load (bootstrap measurement is
4730
- * meaningful) from a Resume/restart (the document is already loaded,
4733
+ * meaningful) from a Résumé/restart (the document is already loaded,
4731
4734
  * so "bootstrap" is a no-op). Only the first session gets the bootstrap
4732
4735
  * phase anchored at navigation start (perf.now() === 0).
4733
4736
  */
@@ -4736,7 +4739,7 @@ class StreamStatusTelemetryService2 {
4736
4739
  * Rolling snapshot of the currently selected WebRTC ICE candidate pair
4737
4740
  * (local/remote type + url). Scanned over `videoStats$` so the stream
4738
4741
  * *keeps* the first non-null pair even if later stats emit null — WebRTC
4739
- * doesn't un-select a pair mid-session, but the source is nullable. The
4742
+ * doesn't unselect a pair mid-session, but the source is nullable. The
4740
4743
  * `startWith(null)` seed makes `withLatestFrom` on this stream safe even
4741
4744
  * before the first video stat arrives (common at data-channel-open).
4742
4745
  */
@@ -4745,7 +4748,7 @@ class StreamStatusTelemetryService2 {
4745
4748
  * Correlation-matched Observable: emits once when the first `loopBack`
4746
4749
  * command's corresponding `command completed` action fires. Built from
4747
4750
  * the two related actions — the command-started captures the correlation
4748
- * id, the command-completed with that id emits.
4751
+ * id; the command-completed with that id emits.
4749
4752
  */
4750
4753
  this.loopbackReceived$ = this.actions$.pipe(ofType(commandStarted), filter$1(({ command }) => command === 'loopBack'), take(1), switchMap(({ id }) => this.actions$.pipe(ofType(commandCompleted), filter$1((b) => b.id === id), take(1))));
4751
4754
  // Overlay-referenced milestones — hoisted as fields so both
@@ -4776,7 +4779,7 @@ class StreamStatusTelemetryService2 {
4776
4779
  /**
4777
4780
  * Unified phase catalog — the single source of truth for everything
4778
4781
  * this service tracks after `session_started`. Each entry is a phase;
4779
- * its `milestones` array is ordered chronologically and the *last*
4782
+ * its `milestones` array is ordered chronologically, and the *last*
4780
4783
  * entry is the phase closer. When that closer's observable fires, the
4781
4784
  * service emits one generic `stream.phase_ended` wire event with every
4782
4785
  * display field the viewer needs.
@@ -4882,7 +4885,7 @@ class StreamStatusTelemetryService2 {
4882
4885
  // time) into phase-3 params:
4883
4886
  // - `iceCandidateCount` (total ICE candidates from server — too
4884
4887
  // few hints at a restrictive network)
4885
- // - `handshakeFlow` (server-offer vs client-offer; we only use
4888
+ // - `handshakeFlow` (server-offer vs. client-offer; we only use
4886
4889
  // server-offer today, but the detector stays in place)
4887
4890
  // - `instanceType` / `branchInfo` / version / path / app /
4888
4891
  // `connectionId` (streamer identity, from `ssInfo` message)
@@ -4918,7 +4921,7 @@ class StreamStatusTelemetryService2 {
4918
4921
  this.loopbackReceivedEntry,
4919
4922
  // CLOSER — flattens the selected ICE candidate pair into two
4920
4923
  // string params (local / remote), and snapshots the running
4921
- // command counter so phase 5 shows how many commands the client
4924
+ // command counter, so phase 5 shows how many commands the client
4922
4925
  // fired at Unreal before the viewport was ready.
4923
4926
  {
4924
4927
  label: 'Viewport ready',
@@ -4962,7 +4965,7 @@ class StreamStatusTelemetryService2 {
4962
4965
  .select(unrealFeature.selectCirrusConnected)
4963
4966
  .pipe(pairwise(), filter$1(([prev, curr]) => prev && !curr))
4964
4967
  .subscribe(() => this.endSession('disconnected'));
4965
- // Close the session when the tab is hidden / being evicted from bfcache.
4968
+ // Close the session when the tab is hidden / being evicted from cache.
4966
4969
  // `pagehide` fires in more cases than `beforeunload` (covers iOS Safari, bfcache).
4967
4970
  fromEvent(window, 'pagehide').subscribe(() => this.endSession('pagehide'));
4968
4971
  }
@@ -4977,7 +4980,7 @@ class StreamStatusTelemetryService2 {
4977
4980
  // - First session on this page → anchor at navigation start (0).
4978
4981
  // `performance.now()` is already "ms since navigation start", so
4979
4982
  // `session_started.duration` becomes the full page-load + idle-time
4980
- // leading up to the first stream start (i.e. the real bootstrap).
4983
+ // leading up to the first stream start (i.e., the real bootstrap).
4981
4984
  // - Resume/restart sessions → anchor at the session's own start.
4982
4985
  // The document is already loaded — a "bootstrap" phase would either
4983
4986
  // balloon (to include all prior idle time) or be misleading, so we
@@ -5027,7 +5030,7 @@ class StreamStatusTelemetryService2 {
5027
5030
  this.session.handshakeFlow = 'client-offer';
5028
5031
  }));
5029
5032
  // Unreal-command counter — increments on every `commandStarted`
5030
- // action. Snapshotted into the `viewport_ready` closer payload as
5033
+ // action. Snapshot ted into the `viewport_ready` closer payload as
5031
5034
  // phase-5's `commandCount`.
5032
5035
  sub.add(this.actions$.pipe(ofType(commandStarted)).subscribe(() => {
5033
5036
  if (this.session)
@@ -5128,7 +5131,7 @@ class StreamStatusTelemetryService2 {
5128
5131
  * Emit the unified `stream.phase_ended` wire event for a closer. Packs
5129
5132
  * every display field the viewer consumes — phaseNo (derived from the
5130
5133
  * catalog index), label, color, milestones, params, overlays. Boundary
5131
- * labels aren't on the wire — the viewer derives them from neighbour
5134
+ * labels aren't on the wire — the viewer derives them from neighbor
5132
5135
  * phases' `label` fields.
5133
5136
  */
5134
5137
  emitPhaseEnded(bucket, bucketIdx, extrasValue) {
@@ -5199,7 +5202,7 @@ class StreamStatusTelemetryService2 {
5199
5202
  qpP95: qp.p95,
5200
5203
  });
5201
5204
  }
5202
- // FPS low vs current target.
5205
+ // FPS low vs. current target.
5203
5206
  const ref = s.maxFpsTarget > 0 ? s.maxFpsTarget : UNLIMITED_REFERENCE_FPS;
5204
5207
  const fpsLowNow = fps.p50 < ref * FPS_LOW_RATIO;
5205
5208
  if (fpsLowNow && !s.fpsLow) {
@@ -5329,7 +5332,7 @@ class StreamStatusTelemetryService2 {
5329
5332
  // Nearest-rank method: p-th percentile ≡ sorted[ceil(p/100 * n) - 1].
5330
5333
  // Using `floor` would make p95 collapse to `max` for n=20
5331
5334
  // (floor(0.95*20) = 19 = max index), hiding the max line behind p95
5332
- // in charts. `ceil - 1` keeps them distinct: p95 = sorted[18], max = sorted[19].
5335
+ // in charts. `ceil - 1` keeps them distinct: p. 95 = sorted[18], max = sorted[19].
5333
5336
  const pick = (p) => {
5334
5337
  const idx = Math.ceil((p / 100) * sorted.length) - 1;
5335
5338
  return sorted[Math.max(0, Math.min(sorted.length - 1, idx))];
@@ -5342,7 +5345,7 @@ class StreamStatusTelemetryService2 {
5342
5345
  };
5343
5346
  }
5344
5347
  track(event, data) {
5345
- // `userId` is attached to every event so the server can bucket files
5348
+ // `userId` is attached to every event, so the server can bucket files
5346
5349
  // under `data/<userId>/<sessionId>.jsonl` without maintaining a
5347
5350
  // session→user index.
5348
5351
  this.store.dispatch(trackTelemetryData({
@@ -5362,8 +5365,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
5362
5365
  /** Compact one side of an ICE candidate pair to `"type (url)"` or just
5363
5366
  * `type` (host candidates have no URL). */
5364
5367
  function fmtCandidate(c) {
5365
- if (!c)
5368
+ if (!c) {
5366
5369
  return null;
5370
+ }
5367
5371
  return c.url ? `${c.type} (${c.url})` : c.type;
5368
5372
  }
5369
5373
  /**
@@ -5540,7 +5544,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
5540
5544
  * ## How it works
5541
5545
  *
5542
5546
  * The service subscribes to `VideoService.videoStats$` (emitted every 250 ms)
5543
- * and collects samples of FPS, bitrate, and QP (Quantisation Parameter).
5547
+ * and collects samples of FPS, bitrate, and QP (Quantization Parameter).
5544
5548
  * Every {@link SAMPLE_WINDOW} ticks (~2 s) it averages the collected samples
5545
5549
  * and feeds them into a set of **fuzzy-logic membership functions** that
5546
5550
  * classify each metric into overlapping quality bands.
@@ -5549,28 +5553,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
5549
5553
  *
5550
5554
  * **1. FPS ratio** = `actualFPS / currentTargetFPS` (0..1+)
5551
5555
  *
5552
- * | Band | Range | Meaning |
5556
+ * | Band | Range | Meaning |
5553
5557
  * |--------|---------------------|-----------------------------------------------|
5554
- * | low | ratio < 0.7 → 1.0, linear ramp 0.7..0.9 → 0 | Stream cannot keep up with the target |
5555
- * | ok | triangle 0.8..1.0, peak at 0.95 | Stream roughly matches the target |
5556
- * | high | ratio 0.9..1.0 → ramp, >1.0 → 1.0 | Stream meets or exceeds the target |
5558
+ * | low | ratio < 0.7 → 1.0, linear ramp 0.7..0.9 → 0 | Stream cannot keep up with the target |
5559
+ * | okays | triangle 0.8..1.0, peak at 0.95 | Stream roughly matches the target |
5560
+ * | high | ratio 0.9..1.0 → ramp, >1.0 → 1.0 | Stream meets or exceeds the target |
5557
5561
  *
5558
5562
  * **2. Bitrate load** = `currentBitrate / MAX_BITRATE` (0..1+)
5559
5563
  *
5560
5564
  * `MAX_BITRATE` = 20 Mbit/s — the reference ceiling for the encoder.
5561
5565
  *
5562
- * | Band | Range | Meaning |
5566
+ * | Band | Range | Meaning |
5563
5567
  * |--------|-------------------------------------------------|-----------------------------------------------|
5564
- * | high | load 0.5..0.8 → ramp, >0.8 → 1.0 | Encoder is using most of the available bandwidth |
5565
- * | not high | load < 0.5 → 0.0 | Bandwidth headroom is available |
5568
+ * | high | load 0.5..0.8 → ramp, >0.8 → 1.0 | Encoder is using most of the available bandwidth |
5569
+ * | not high | load < 0.5 → 0.0 | Bandwidth headroom is available |
5566
5570
  *
5567
5571
  * **3. Quality** — mapped from QP via `mapQpToQuality()` (see {@link Quality}):
5568
5572
  *
5569
- * | Quality | QP range | Meaning |
5573
+ * | Quality | QP range | Meaning |
5570
5574
  * |----------|-----------|-------------------------------------------------|
5571
- * | `lime` | QP <= 26 | Good — encoder has enough headroom |
5572
- * | `orange` | QP 27..35 | Fair — encoder is under moderate pressure |
5573
- * | `red` | QP > 35 | Poor — heavy compression, visible artefacts |
5575
+ * | `lime` | QP <= 26 | Good — encoder has enough headroom |
5576
+ * | `orange` | QP 27..35 | Fair — encoder is under moderate pressure |
5577
+ * | `red` | QP > 35 | Poor — heavy compression, visible artifacts |
5574
5578
  *
5575
5579
  * ### Decision rules (evaluated in priority order, first match wins)
5576
5580
  *
@@ -5584,17 +5588,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
5584
5588
  *
5585
5589
  * ## Cooldown-based throttling
5586
5590
  *
5587
- * The service continuously evaluates fuzzy rules every sample window.
5591
+ * The service continuously evaluates fuzzy rules in every sample window.
5588
5592
  * After each FPS step change it enforces a cooldown before the next
5589
5593
  * change can be applied. The cooldown duration depends on the
5590
5594
  * (previous decision → next decision) pair:
5591
5595
  *
5592
- * | Previous | Next | Cooldown |
5596
+ * | Previous | Next | Cooldown |
5593
5597
  * |-----------|-----------|-----------------------------------------------------|
5594
- * | decrease | decrease | {@link COOLDOWN_DECREASE_AFTER_DECREASE_MS} (2 s) |
5595
- * | decrease | increase | {@link COOLDOWN_INCREASE_AFTER_DECREASE_MS} (10 s) |
5596
- * | increase | decrease | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
5597
- * | increase | increase | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
5598
+ * | decrease | decrease | {@link COOLDOWN_DECREASE_AFTER_DECREASE_MS} (2 s) |
5599
+ * | decrease | increase | {@link COOLDOWN_INCREASE_AFTER_DECREASE_MS} (10 s) |
5600
+ * | increase | decrease | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
5601
+ * | increase | increase | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
5598
5602
  *
5599
5603
  * This means the system reacts quickly after an increase (2 s in any
5600
5604
  * direction) but is cautious about stepping back up after a decrease
@@ -5611,7 +5615,7 @@ class FpsMonitorService {
5611
5615
  this.videoService = inject(VideoService);
5612
5616
  this.store = inject(Store);
5613
5617
  this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
5614
- /** Discrete FPS targets the controller can switch between (ascending order). Last 0 is unlimited framerate indicator*/
5618
+ /** Discrete FPS targets the controller can switch between (ascending order). Last 0 is an unlimited framerate indicator*/
5615
5619
  this.FPS_STEPS = [30, 40, 50, 0];
5616
5620
  /**
5617
5621
  * Reference FPS used to compute the FPS ratio when `currentFpsTarget` is 0
@@ -5632,7 +5636,7 @@ class FpsMonitorService {
5632
5636
  this.COOLDOWN_DECREASE_AFTER_DECREASE_MS = 2_000;
5633
5637
  /**
5634
5638
  * Cooldown (ms) for an increase following a previous decrease.
5635
- * The stream needs more time to stabilise before stepping back up.
5639
+ * The stream needs more time to stabilize before stepping back up.
5636
5640
  */
5637
5641
  this.COOLDOWN_INCREASE_AFTER_DECREASE_MS = 10_000;
5638
5642
  /**
@@ -5711,9 +5715,9 @@ class FpsMonitorService {
5711
5715
  * Rules are evaluated in priority order — first match wins.
5712
5716
  *
5713
5717
  * Inputs:
5714
- * - `fpsRatio` = avgFPS / currentTargetFPS (e.g. 45/60 = 0.75)
5715
- * - `bitrateLoad` = avgBitrate / 20 Mbit/s (e.g. 12M/20M = 0.6)
5716
- * - `quality` = mapQpToQuality(avgQP) → 'lime' | 'orange' | 'red'
5718
+ * - `fpsRatio` = avgFPS / currentTargetFPS (e.g., 45/60 = 0.75)
5719
+ * - `bitrateLoad` = avgBitrate / 20 Mbit/s (e.g., 12M/20M = 0.6)
5720
+ * - `quality` = mapQpToQuality(avgQP) → 'lime' | 'orange' | 'red'
5717
5721
  */
5718
5722
  evaluateDecision(avg, currentTarget) {
5719
5723
  const referenceTarget = currentTarget > 0 ? currentTarget : this.UNLIMITED_REFERENCE_FPS;
@@ -5730,17 +5734,17 @@ class FpsMonitorService {
5730
5734
  return 'decrease';
5731
5735
  }
5732
5736
  // Rule 2: FPS looks acceptable numerically, but encoder quality is 'red'
5733
- // (QP > 35 — heavy compression artefacts). Reducing target FPS frees
5737
+ // (QP > 35 — heavy compression artifacts). Reducing target FPS frees
5734
5738
  // encoder headroom and improves visual quality.
5735
5739
  if (fpsOk > 0.4 && quality === 'red') {
5736
5740
  return 'decrease';
5737
5741
  }
5738
- // Rule 3: FPS is ok, but bitrate is above ~50-80% of 20 Mbit/s ceiling
5742
+ // Rule 3: FPS is ok, but the bitrate is above ~50-80% of 20 Mbit/s ceiling
5739
5743
  // and quality is 'orange' (QP 27..35). Near capacity — don't push higher.
5740
5744
  if (fpsOk > 0.4 && bitrateHigh > 0.5 && quality === 'orange') {
5741
5745
  return 'hold';
5742
5746
  }
5743
- // Rule 4: FPS meets/exceeds target (ratio >= ~0.95), quality is 'lime'
5747
+ // Rule 4: FPS meets/exceeds the target (ratio >= ~0.95), quality is 'lime'
5744
5748
  // (QP <= 26), and bitrate is below 50% of ceiling — safe to step up.
5745
5749
  // Note: the last FPS_STEPS value (0) means "no limit", so compare by
5746
5750
  // position in FPS_STEPS rather than numerically.
@@ -5763,11 +5767,11 @@ class FpsMonitorService {
5763
5767
  // ---------------------------------------------------------------------------
5764
5768
  /**
5765
5769
  * FPS ratio membership "low".
5766
- * Input: ratio = actualFPS / targetFPS (e.g. 42/60 = 0.70).
5770
+ * Input: a ratio = actualFPS / targetFPS (e.g., 42/60 = 0.70).
5767
5771
  *
5768
- * ratio < 0.7 → 1.0 (clearly failing, e.g. 40/60)
5769
- * ratio 0.7..0.9 → linear ramp down (e.g. 0.8 → 0.5)
5770
- * ratio > 0.9 → 0.0 (keeping up)
5772
+ * ratio < 0.7 → 1.0 (clearly failing, e.g., 40/60)
5773
+ * ratio 0.7..0.9 → linear ramp down (e.g., 0.8 → 0.5)
5774
+ * a ratio > 0.9 → 0.0 (keeping up)
5771
5775
  */
5772
5776
  membershipFpsLow(ratio) {
5773
5777
  if (ratio < 0.7)
@@ -5780,10 +5784,10 @@ class FpsMonitorService {
5780
5784
  * FPS ratio membership "ok" — triangle shape.
5781
5785
  * Input: ratio = actualFPS / targetFPS.
5782
5786
  *
5783
- * ratio < 0.8 → 0.0
5784
- * ratio 0.8..0.95 → ramp up, peak at 0.95 (e.g. 57/60)
5787
+ * ratio < 0.8 → 0.0
5788
+ * ratio 0.8..0.95 → ramp up, peak at 0.95 (e.g., 57/60)
5785
5789
  * ratio 0.95..1.0 → ramp down
5786
- * ratio > 1.0 → 0.0
5790
+ * a ratio > 1.0 → 0.0
5787
5791
  */
5788
5792
  membershipFpsOk(ratio) {
5789
5793
  if (ratio < 0.8)
@@ -5798,9 +5802,9 @@ class FpsMonitorService {
5798
5802
  * FPS ratio membership "high".
5799
5803
  * Input: ratio = actualFPS / targetFPS.
5800
5804
  *
5801
- * ratio < 0.9 → 0.0
5802
- * ratio 0.9..1.0 → linear ramp up (e.g. 0.95 → 0.5)
5803
- * ratio >= 1.0 → 1.0 (meeting or exceeding target, e.g. 60/60)
5805
+ * ratio < 0.9 → 0.0
5806
+ * ratio 0.9..1.0 → linear ramp up (e.g., 0.95 → 0.5)
5807
+ * a ratio >= 1.0 → 1.0 (meeting or exceeding target, e.g., 60/60)
5804
5808
  */
5805
5809
  membershipFpsHigh(ratio) {
5806
5810
  if (ratio < 0.9)
@@ -5811,11 +5815,11 @@ class FpsMonitorService {
5811
5815
  }
5812
5816
  /**
5813
5817
  * Bitrate load membership "high".
5814
- * Input: load = currentBitrate / MAX_BITRATE (20 Mbit/s).
5818
+ * Input: a load = currentBitrate / MAX_BITRATE (20 Mbit/s).
5815
5819
  *
5816
- * load < 0.5 → 0.0 (below 10 Mbit/s — plenty of headroom)
5817
- * load 0.5..0.8 → linear ramp (e.g. 13M/20M = 0.65 → 0.5)
5818
- * load > 0.8 → 1.0 (above 16 Mbit/s — near capacity)
5820
+ * load < 0.5 → 0.0 (below 10 Mbit/s — plenty of headroom)
5821
+ * load 0.5..0.8 → linear ramp (e.g., 13M/20M = 0.65 → 0.5)
5822
+ * load > 0.8 → 1.0 (above 16 Mbit/s — near capacity)
5819
5823
  */
5820
5824
  membershipBitrateHigh(load) {
5821
5825
  if (load < 0.5)
@@ -5847,14 +5851,14 @@ class FpsMonitorService {
5847
5851
  Logger.info(`[FpsMonitor] Decision: ${decision} → FPS: ${newTarget}, Quality: ${quality}`);
5848
5852
  if (newTarget !== this.currentFpsTarget) {
5849
5853
  this.currentFpsTarget = newTarget;
5850
- this.store.dispatch(setMaxFps({ maxFps: newTarget }));
5854
+ // this.store.dispatch(setMaxFps({ maxFps: newTarget }));
5851
5855
  }
5852
5856
  this.lastDecisionTime = now;
5853
5857
  this.samples = [];
5854
5858
  }
5855
5859
  /**
5856
- * Get the next FPS target based on current target and decision.
5857
- * Clamps to valid FPS_STEPS range.
5860
+ * Get the next FPS target based on the current target and decision.
5861
+ * Clamps to the valid FPS_STEPS range.
5858
5862
  */
5859
5863
  getNextFpsTarget(currentTarget, decision) {
5860
5864
  const currentIndex = this.FPS_STEPS.indexOf(currentTarget);
@@ -6779,5 +6783,5 @@ function provideUnrealModule() {
6779
6783
  * Generated bundle index. Do not edit.
6780
6784
  */
6781
6785
 
6782
- export { AFKService, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, CommandTelemetryService, CommandsEffects, ConfigHandler, ConsoleExtensionsService, ControlScheme, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DEFAULT_RECONNECT_DELAY_MS, DEFAULT_RECONNECT_ENABLED, DEFAULT_RECONNECT_MAX_ATTEMPTS, DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE, DEFAULT_RECONNECT_ON_ICE_FAILURE, DESTROY_DISCONNECT_REASONS, DataFlowMonitor, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverService, FilterSettingsComponent, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LoadingProgressService, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MIN_CONTAINER_SIZE, MessageType, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, RegionsPingService, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_AUDIO_ID, STREAMING_VIDEO_ID, SafePipe, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage, UNREAL_CONFIG, UnrealCallbackService, UnrealCommunicatorService, UnrealEffects, UnrealSceneComponent, UnrealStatusMessage, VideoService, VideoStatsComponent, WSCloseCode_CIRRUS_ABNORMAL_CLOSURE, WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR, WSCloseCode_CIRRUS_PLAYER_DISCONNECTED, WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER, WSCloseCode_FORCE_CIRRUS_CLOSE, WSCloseCode_NORMAL_AFK_TIMEOUT, WSCloseCode_NORMAL_CLOSURE, WSCloseCode_NORMAL_MANUAL_DISCONNECT, WSCloseCode_UNKNOWN, WSCloseCodes, WS_OPEN_STATE, WS_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, answerSent, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, commandCompleted, commandStarted, commandsFeature, commandsReducer, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, dropDC, dropPC, floatToSmoothPercents, forceResizeViewport, fromResizeObserver, getActiveUrl, getImageFromVideoStream, getResizeStudioValues, getResizeValuesUniversal, getRtcErrorMessage, iceConnectionFailed, initSignalling, instanceReady, keepMaxUntilReset, makeEven, pollingEnded, pollingStarted, provideUnrealModule, qpToQuality, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, regionPingFetchEnd, regionPingFetchStart, regionResolved, resetAfk, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetUserInactivityTimeout, resetWarnTimeout, saveAnalyticsEvent, selectCirrusConnectionId, selectClientAndViewIds, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsFullyConnected, selectIsLoaderScreenVisible, selectIsVideoPlayingAndDataChannelConnected, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, setAfkTimerCountdown, setAfkTimerHide, setAfkTimerVisible, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMaxFps, setOrchestrationContext, setOrchestrationMessage, setOrchestrationParameters, setOrchestrationProgress, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setUnrealPlaywrightConfig, setUserInactivityTimeout, setViewportNotReady, setViewportReady, showLoadingProgress, showResumeStreamPopup, showUnrealErrorMessage, showUserInactivityTimeoutPopup, smoothTransition, startStream, trackMixpanelEvent, trackTelemetryData, unrealCommandCallback, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
6786
+ export { AFKService, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, CommandTelemetryService, CommandsEffects, ConfigHandler, ConsoleExtensionsService, ControlScheme, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DEFAULT_RECONNECT_DELAY_MS, DEFAULT_RECONNECT_ENABLED, DEFAULT_RECONNECT_MAX_ATTEMPTS, DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE, DEFAULT_RECONNECT_ON_ICE_FAILURE, DESTROY_DISCONNECT_REASONS, DataFlowMonitor, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverService, FilterSettingsComponent, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LoadingProgressService, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MIN_CONTAINER_SIZE, MessageType, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, RegionsPingService, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_AUDIO_ID, STREAMING_VIDEO_ID, SafePipe, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage, UNREAL_CONFIG, UnrealCallbackService, UnrealCommunicatorService, UnrealEffects, UnrealSceneComponent, UnrealStatusMessage, VideoService, VideoStatsComponent, WSCloseCode_CIRRUS_ABNORMAL_CLOSURE, WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR, WSCloseCode_CIRRUS_PLAYER_DISCONNECTED, WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER, WSCloseCode_FORCE_CIRRUS_CLOSE, WSCloseCode_NORMAL_AFK_TIMEOUT, WSCloseCode_NORMAL_CLOSURE, WSCloseCode_NORMAL_MANUAL_DISCONNECT, WSCloseCode_UNKNOWN, WSCloseCodes, WS_OPEN_STATE, WS_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, answerSent, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, commandCompleted, commandStarted, commandsFeature, commandsReducer, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, dropDC, dropPC, floatToSmoothPercents, forceResizeViewport, fromResizeObserver, getActiveUrl, getImageFromVideoStream, getResizeStudioValues, getResizeValuesUniversal, getRtcErrorMessage, iceConnectionFailed, initSignalling, instanceReady, keepMaxUntilReset, makeEven, pollingEnded, pollingStarted, provideUnrealModule, qpToQuality, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, regionPingFetchEnd, regionPingFetchStart, regionResolved, resetAfk, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetUserInactivityTimeout, resetWarnTimeout, saveAnalyticsEvent, selectCirrusConnectionId, selectClientAndViewIds, selectCommandProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsFullyConnected, selectIsLoaderScreenVisible, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, setAfkTimerCountdown, setAfkTimerHide, setAfkTimerVisible, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMaxFps, setOrchestrationContext, setOrchestrationMessage, setOrchestrationParameters, setOrchestrationProgress, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setUnrealPlaywrightConfig, setUserInactivityTimeout, setViewportNotReady, setViewportReady, showLoadingProgress, showResumeStreamPopup, showUnrealErrorMessage, showUserInactivityTimeoutPopup, smoothTransition, startStream, trackMixpanelEvent, trackTelemetryData, unrealCommandCallback, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
6783
6787
  //# sourceMappingURL=3dsource-angular-unreal-module.mjs.map