@3dsource/angular-unreal-module 0.0.146-dev.8 → 0.0.148-dev.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/LICENSE +14 -14
- package/README.md +370 -361
- package/fesm2022/3dsource-angular-unreal-module.mjs +253 -632
- package/fesm2022/3dsource-angular-unreal-module.mjs.map +1 -1
- package/package.json +1 -1
- package/types/3dsource-angular-unreal-module.d.ts +69 -273
- package/js/stream-prefetch.js +0 -4
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ import { Store } from '@ngrx/store';
|
|
|
11
11
|
import { Actions } from '@ngrx/effects';
|
|
12
12
|
import { IKeyCode, ImageOutputValues, Area } from '@3dsource/utils';
|
|
13
13
|
import { SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser';
|
|
14
|
-
import { MetaBoxCommandPacket, MetaBoxCommandList,
|
|
14
|
+
import { MetaBoxCommandPacket, MetaBoxCommandList, MetaBoxCallbackList, FOnSceneStateCallback, FOnFocusObjectCallback, FCameraChangedCallback, FOnObjectTransformChangedCallback, FOnChangeSequenceChangedCallback, FOnFinishSequenceChangedCallback } from '@3dsource/types-unreal';
|
|
15
15
|
import * as node_modules__ngrx_effects_types_ngrx_effects from 'node_modules/@ngrx/effects/types/ngrx-effects';
|
|
16
16
|
|
|
17
17
|
declare class AfkTimeoutModalComponent {
|
|
@@ -231,6 +231,18 @@ interface FreezeFrameMessage {
|
|
|
231
231
|
progress: number | null;
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
interface ReconnectConfig {
|
|
235
|
+
/** Enable auto-reconnection when WebRTC or DataChannel connection is lost. Default: true */
|
|
236
|
+
enabled?: boolean;
|
|
237
|
+
/** Maximum number of reconnection attempts before giving up. Default: 3 */
|
|
238
|
+
maxAttempts?: number;
|
|
239
|
+
/** Delay in milliseconds between reconnection attempts. Default: 1000 */
|
|
240
|
+
delayMs?: number;
|
|
241
|
+
/** Reconnect on ICE connection failure (disconnected/failed state). Default: true */
|
|
242
|
+
onIceFailure?: boolean;
|
|
243
|
+
/** Reconnect on DataChannel close. Default: true */
|
|
244
|
+
onDataChannelClose?: boolean;
|
|
245
|
+
}
|
|
234
246
|
interface UnrealInitialConfig {
|
|
235
247
|
playwright?: boolean;
|
|
236
248
|
customErrorsEndpoint?: string;
|
|
@@ -241,57 +253,8 @@ interface UnrealInitialConfig {
|
|
|
241
253
|
streamTelemetryV2Url?: string;
|
|
242
254
|
fpsMonitor?: boolean;
|
|
243
255
|
autoHighResolution?: boolean;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
interface SignalingData {
|
|
247
|
-
instanceType: string;
|
|
248
|
-
branchInfo: string;
|
|
249
|
-
cirrusVersion: string;
|
|
250
|
-
streamerVersion: string;
|
|
251
|
-
streamPath: string;
|
|
252
|
-
streamApp: string;
|
|
253
|
-
connectionId: string;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Live WebRTC connection parked on `window.__stream` by the `stream-prefetch.js`
|
|
258
|
-
* head-script, ready for the Angular services to ADOPT instead of building a
|
|
259
|
-
* connection from scratch. The shape is the handoff contract between that
|
|
260
|
-
* framework-free script and {@link StreamAdoptionService} — keep the two in sync.
|
|
261
|
-
*/
|
|
262
|
-
interface ParkedStream {
|
|
263
|
-
state: 'connecting' | 'ready' | 'failed' | 'adopted';
|
|
264
|
-
pc?: RTCPeerConnection;
|
|
265
|
-
dc?: RTCDataChannel;
|
|
266
|
-
/** video(+audio) MediaStream from the `track` event */
|
|
267
|
-
stream?: MediaStream;
|
|
268
|
-
/** live signalling socket (handshake already done, `requestStream` sent) */
|
|
269
|
-
ws?: WebSocket;
|
|
270
|
-
/** `data` from the streamer's `ssInfo` message — received before adoption */
|
|
271
|
-
ssData?: SignalingData;
|
|
272
|
-
/** = resolved wsUrl of the winning machine */
|
|
273
|
-
machineId?: string;
|
|
274
|
-
/** `peerConnectionOptions` the machine sent in its `config` message */
|
|
275
|
-
config?: RTCConfiguration;
|
|
276
|
-
/** ids the script generated; Angular reuses them (no regeneration) */
|
|
277
|
-
ids: {
|
|
278
|
-
clientId: string;
|
|
279
|
-
viewId: string;
|
|
280
|
-
correlationId: string;
|
|
281
|
-
};
|
|
282
|
-
/** DataChannel messages received before adoption, replayed on adopt */
|
|
283
|
-
dcBuffer: ArrayBuffer[];
|
|
284
|
-
/** `performance.now()` marks for the prefetch waterfall (telemetry) */
|
|
285
|
-
timings: Record<string, number>;
|
|
286
|
-
failReason?: string;
|
|
287
|
-
failError?: string;
|
|
288
|
-
/** Stops the script's watchdog and flips state to `adopted`. */
|
|
289
|
-
adopt: () => ParkedStream;
|
|
290
|
-
}
|
|
291
|
-
declare global {
|
|
292
|
-
interface Window {
|
|
293
|
-
__stream?: ParkedStream;
|
|
294
|
-
}
|
|
256
|
+
/** Configuration for auto-reconnection behavior */
|
|
257
|
+
reconnect?: ReconnectConfig;
|
|
295
258
|
}
|
|
296
259
|
|
|
297
260
|
declare const SpecialKeyCodes: {
|
|
@@ -383,9 +346,6 @@ declare const MIN_CONTAINER_SIZE = 2;
|
|
|
383
346
|
declare const MINIMAL_FPS = 6;
|
|
384
347
|
declare const STREAMING_VIDEO_ID = "streamingVideo";
|
|
385
348
|
declare const STREAMING_AUDIO_ID = "streamingAudio";
|
|
386
|
-
declare const CONSOLE_COMMAND_ENABLE_MESSAGES = "EnableAllScreenMessages";
|
|
387
|
-
declare const CONSOLE_COMMAND_DISABLE_MESSAGES = "DisableAllScreenMessages";
|
|
388
|
-
declare const CONSOLE_COMMAND_PIXEL_QUALITY = "PixelStreaming.FreezeFrameQuality 95";
|
|
389
349
|
declare const FULL_HD_WIDTH = 1920;
|
|
390
350
|
declare const FULL_HD_HEIGHT = 1080;
|
|
391
351
|
declare const WS_TIMEOUT = 6000;
|
|
@@ -404,29 +364,16 @@ declare const REGION_PING_CACHE_TTL_MS: number;
|
|
|
404
364
|
declare const REGION_PING_ACCURATE_SAMPLES = 3;
|
|
405
365
|
declare const REGION_PING_WARMUP_DEADLINE_MS = 1500;
|
|
406
366
|
declare const REGION_PING_BACKGROUND_REFRESH_DELAY_MS = 5000;
|
|
407
|
-
declare const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
367
|
+
declare const DEFAULT_RECONNECT_ENABLED = true;
|
|
368
|
+
declare const DEFAULT_RECONNECT_MAX_ATTEMPTS = 3;
|
|
369
|
+
declare const DEFAULT_RECONNECT_DELAY_MS = 1000;
|
|
370
|
+
declare const DEFAULT_RECONNECT_ON_ICE_FAILURE = true;
|
|
371
|
+
declare const DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE = true;
|
|
412
372
|
declare const UnrealStatusMessage: {
|
|
413
373
|
readonly CONNECTING_TO_SESSION: "Connecting to session.";
|
|
414
374
|
readonly STARTING_YOUR_SESSION: "Starting your session";
|
|
415
375
|
};
|
|
416
376
|
|
|
417
|
-
interface NormalizeAndQuantizeUnsignedValue {
|
|
418
|
-
inRange: boolean;
|
|
419
|
-
x: number;
|
|
420
|
-
y: number;
|
|
421
|
-
}
|
|
422
|
-
interface UnquantizeAndDenormalizeUnsignedValue {
|
|
423
|
-
x: number;
|
|
424
|
-
y: number;
|
|
425
|
-
}
|
|
426
|
-
interface NormalizeAndQuantizeSignedValue {
|
|
427
|
-
x: number;
|
|
428
|
-
y: number;
|
|
429
|
-
}
|
|
430
377
|
interface InputProps {
|
|
431
378
|
controlScheme: ControlSchemeValues;
|
|
432
379
|
suppressBrowserKeys: boolean;
|
|
@@ -434,6 +381,16 @@ interface InputProps {
|
|
|
434
381
|
|
|
435
382
|
type Quality = 'lime' | 'red' | 'orange';
|
|
436
383
|
|
|
384
|
+
interface SignalingData {
|
|
385
|
+
instanceType: string;
|
|
386
|
+
branchInfo: string;
|
|
387
|
+
cirrusVersion: string;
|
|
388
|
+
streamerVersion: string;
|
|
389
|
+
streamPath: string;
|
|
390
|
+
streamApp: string;
|
|
391
|
+
connectionId: string;
|
|
392
|
+
}
|
|
393
|
+
|
|
437
394
|
declare const OrchestrationMessageTypes: {
|
|
438
395
|
readonly ping: "ping";
|
|
439
396
|
readonly error: "error";
|
|
@@ -898,7 +855,6 @@ declare class InputService extends SubService {
|
|
|
898
855
|
private isKeyCodeBrowserKey;
|
|
899
856
|
private getKeyCode;
|
|
900
857
|
private registerKeyboardEvents;
|
|
901
|
-
private isIgnoredViewportKey;
|
|
902
858
|
private startListenKeys;
|
|
903
859
|
static ɵfac: i0.ɵɵFactoryDeclaration<InputService, never>;
|
|
904
860
|
static ɵprov: i0.ɵɵInjectableDeclaration<InputService>;
|
|
@@ -923,15 +879,8 @@ declare class RegionsPingService {
|
|
|
923
879
|
* entry is well-formed and still within {@link REGION_PING_CACHE_TTL_MS}.
|
|
924
880
|
* All access is guarded — `localStorage` can throw (private mode, disabled
|
|
925
881
|
* storage) or be absent (non-browser).
|
|
926
|
-
*
|
|
927
|
-
* Public so adopted connections (which skip `getFastest`) can replay the
|
|
928
|
-
* region-resolving telemetry phase from the same cached winner — see
|
|
929
|
-
* `UnrealEffects.regionTelemetryOnAdopt$`.
|
|
930
882
|
*/
|
|
931
|
-
readCachedWinner
|
|
932
|
-
region_code: string;
|
|
933
|
-
result: number[];
|
|
934
|
-
} | null;
|
|
883
|
+
private readCachedWinner;
|
|
935
884
|
private writeCachedWinner;
|
|
936
885
|
/**
|
|
937
886
|
* Accurate, OFF-critical-path refresh of the region cache. Mirrors the
|
|
@@ -1053,15 +1002,6 @@ declare class SignallingService extends SubService {
|
|
|
1053
1002
|
private pollLoop;
|
|
1054
1003
|
private connectToCirrus;
|
|
1055
1004
|
private addWsHandlers;
|
|
1056
|
-
/**
|
|
1057
|
-
* Adopt a live signalling socket opened by the `stream-prefetch.js`
|
|
1058
|
-
* head-script. The socket is already OPEN and `requestStream` was already
|
|
1059
|
-
* sent, so — unlike {@link addWsHandlers} — we attach message/close/error
|
|
1060
|
-
* handlers but deliberately skip {@link OnOpenHandler} (which would
|
|
1061
|
-
* `setCirrusConnected` + re-`sendRequestStream`). Reuses the head-script's
|
|
1062
|
-
* `correlationId` so subsequent correlated messages line up.
|
|
1063
|
-
*/
|
|
1064
|
-
adoptSocket(ws: WebSocket, correlationId: string): void;
|
|
1065
1005
|
private showStatusMessage;
|
|
1066
1006
|
/**
|
|
1067
1007
|
* Close the connection with the signaling server
|
|
@@ -1081,52 +1021,6 @@ declare class SignallingService extends SubService {
|
|
|
1081
1021
|
static ɵprov: i0.ɵɵInjectableDeclaration<SignallingService>;
|
|
1082
1022
|
}
|
|
1083
1023
|
|
|
1084
|
-
/**
|
|
1085
|
-
* Adopts a WebRTC connection prefetched by the `stream-prefetch.js` head-script
|
|
1086
|
-
* and parked on `window.__stream`, instead of running `connectToSignaling` from
|
|
1087
|
-
* scratch. Called from the same seam where signalling normally starts
|
|
1088
|
-
* (`connectToSignaling$` effect); if there is nothing ready to adopt it returns
|
|
1089
|
-
* `false` and the caller falls back to the normal connect — strictly additive.
|
|
1090
|
-
*/
|
|
1091
|
-
declare class StreamAdoptionService {
|
|
1092
|
-
private readonly store;
|
|
1093
|
-
private readonly signalling;
|
|
1094
|
-
private readonly webRtc;
|
|
1095
|
-
/**
|
|
1096
|
-
* Decide adoption, WAITING for an in-flight prefetch instead of racing it.
|
|
1097
|
-
*
|
|
1098
|
-
* - nothing parked → emit `false` at once (caller connects normally).
|
|
1099
|
-
* - already settled (`ready`/`failed`/`adopted`) → adopt-if-ready at once.
|
|
1100
|
-
* - still `connecting` → poll until the script settles it, then adopt-if-ready.
|
|
1101
|
-
*
|
|
1102
|
-
* Deliberately NO time budget: for DIRECT orchestration the prefetch holds
|
|
1103
|
-
* the socket open while the orchestrator provisions a machine, which can take
|
|
1104
|
-
* minutes (150–200s+). A fixed deadline would make Angular give up and open a
|
|
1105
|
-
* second connection mid-provisioning — exactly the race/orphan this avoids.
|
|
1106
|
-
* The wait is bounded by liveness instead: the script flips the parked state
|
|
1107
|
-
* to `failed` on a dead socket (`ws.onclose`/`onerror`), and the caller wraps
|
|
1108
|
-
* this in `takeUntil(abortEstablishingConnection)`, so a route change / teardown
|
|
1109
|
-
* cancels it. Emits exactly once. Cancelling runs no adoption — which is what
|
|
1110
|
-
* stops a fast route-switch from starting overlapping connections.
|
|
1111
|
-
*
|
|
1112
|
-
* Wrapped in `defer` so the `tryAdopt()` side effect (which dispatches
|
|
1113
|
-
* `streamAdopted`) runs at SUBSCRIPTION time, not when the observable is
|
|
1114
|
-
* built. The effect prepends `startWith(setEstablishingConnection(true))`,
|
|
1115
|
-
* which starts the telemetry session and subscribes its phase catalog; that
|
|
1116
|
-
* must happen BEFORE `streamAdopted` → `regionTelemetryOnAdopt$` replays
|
|
1117
|
-
* `regionResolved`, or the region phase fires into a session that doesn't
|
|
1118
|
-
* exist yet and is lost. `defer` guarantees that ordering.
|
|
1119
|
-
*/
|
|
1120
|
-
awaitAndAdopt$(): Observable<boolean>;
|
|
1121
|
-
/**
|
|
1122
|
-
* @returns `true` if a ready parked stream was adopted (caller must NOT
|
|
1123
|
-
* start a fresh connection), `false` otherwise.
|
|
1124
|
-
*/
|
|
1125
|
-
tryAdopt(): boolean;
|
|
1126
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<StreamAdoptionService, never>;
|
|
1127
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<StreamAdoptionService>;
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
1024
|
declare class StreamStatusTelemetryService extends SubService {
|
|
1131
1025
|
private readonly videoService;
|
|
1132
1026
|
private readonly unrealConfig;
|
|
@@ -1214,17 +1108,6 @@ declare class StreamStatusTelemetryService2 {
|
|
|
1214
1108
|
private readonly disconnectReason$;
|
|
1215
1109
|
private readonly errorMessage$;
|
|
1216
1110
|
private readonly viewPortReady$;
|
|
1217
|
-
/**
|
|
1218
|
-
* Synchronous adoption flag. The `streamAdopted` reducer sets it BEFORE any
|
|
1219
|
-
* action subscriber runs, so the connection-phase closers (which fire inside
|
|
1220
|
-
* the same dispatch, e.g. `ssinfo-received` off the `ssData` state change)
|
|
1221
|
-
* can read it and defer to the prefetch-timed attribution emitted by
|
|
1222
|
-
* {@link emitAdoptedConnection} instead of recording the live wall-clock.
|
|
1223
|
-
*/
|
|
1224
|
-
private readonly adopted$;
|
|
1225
|
-
/** Streamer identity for the adopted signaling phase params. */
|
|
1226
|
-
private readonly ssData$;
|
|
1227
|
-
private readonly awsInstance$;
|
|
1228
1111
|
private session;
|
|
1229
1112
|
/**
|
|
1230
1113
|
* Whether a session has already started during the current page lifetime.
|
|
@@ -1288,36 +1171,6 @@ declare class StreamStatusTelemetryService2 {
|
|
|
1288
1171
|
* are derived from neighbor phases.
|
|
1289
1172
|
*/
|
|
1290
1173
|
private emitPhaseEnded;
|
|
1291
|
-
/**
|
|
1292
|
-
* Emit the region / signaling / webrtc phases for an ADOPTED connection.
|
|
1293
|
-
*
|
|
1294
|
-
* The prefetch script established the connection in PARALLEL with page load,
|
|
1295
|
-
* so the phases are positioned at their real (anchor-relative) spans — shifted
|
|
1296
|
-
* LEFT to overlap the HTML-loading / route-idle rows — rather than sequentially
|
|
1297
|
-
* after them. That's the whole point of the prefetch: the handshake already
|
|
1298
|
-
* happened while the page was loading. Each phase ships:
|
|
1299
|
-
* - `duration` — the real sub-step time the prefetch spent.
|
|
1300
|
-
* - `spanStartMs` — anchor-relative start, so the viewer left-shifts the bar.
|
|
1301
|
-
* - `adoptionAtMs` — where Angular took over (the next phase, Unreal
|
|
1302
|
-
* communication, resumes here on the sequential timeline).
|
|
1303
|
-
* - savings params: `prefetchConnectMs` (full handshake), `prefetchSavedMs`
|
|
1304
|
-
* (done before Angular was ready), `adoptionWaitMs` (real connect→adopted
|
|
1305
|
-
* wait), `adoptionOverheadMs` (prefetch-ready → adopted gap).
|
|
1306
|
-
*/
|
|
1307
|
-
private emitAdoptedConnection;
|
|
1308
|
-
/**
|
|
1309
|
-
* Emit one adopted phase positioned at its real `spanStartMs` (left-shifted
|
|
1310
|
-
* to overlap page load) with its real prefetch `duration`. `prefetched`,
|
|
1311
|
-
* `spanStartMs` and `adoptionAtMs` ride as top-level wire fields the viewer
|
|
1312
|
-
* uses to lay the bar out; the rest become display params.
|
|
1313
|
-
*/
|
|
1314
|
-
private emitAdoptedPhase;
|
|
1315
|
-
/** Streamer identity params for the adopted signaling phase — mirrors the
|
|
1316
|
-
* `ssinfo-received` closer's shape (client / instanceName / …ssData). */
|
|
1317
|
-
private adoptedSignalingParams;
|
|
1318
|
-
/** Read the region-ping cache the prefetch reused (localStorage), so the
|
|
1319
|
-
* adopted region phase can still report the winning region + samples. */
|
|
1320
|
-
private readRegionCache;
|
|
1321
1174
|
private handleWindow;
|
|
1322
1175
|
private evaluateAnomalies;
|
|
1323
1176
|
private updateMaxFpsTarget;
|
|
@@ -1546,16 +1399,6 @@ declare class WebRtcPlayerService extends SubService {
|
|
|
1546
1399
|
* @returns true if reconnection was initiated, false if signaling is not connected
|
|
1547
1400
|
*/
|
|
1548
1401
|
reconnectPeer(): boolean;
|
|
1549
|
-
/**
|
|
1550
|
-
* Adopt a fully-negotiated connection prefetched by `stream-prefetch.js`:
|
|
1551
|
-
* take ownership of its PeerConnection, DataChannel and media stream instead
|
|
1552
|
-
* of running the handshake. The head-script attached property-based handlers
|
|
1553
|
-
* (`pc.onicecandidate`, `dc.onmessage`, …) and buffered inbound DC messages;
|
|
1554
|
-
* here we detach those, wire our own (addEventListener-based) handlers, replay
|
|
1555
|
-
* the buffer in order, then drive `onDataChannelConnected` manually because the
|
|
1556
|
-
* DataChannel is already open (its `open` event won't fire again).
|
|
1557
|
-
*/
|
|
1558
|
-
adopt(pc: RTCPeerConnection, dc: RTCDataChannel, stream: MediaStream, config: RTCConfiguration, dcBuffer: ArrayBuffer[]): void;
|
|
1559
1402
|
private setConfig;
|
|
1560
1403
|
private handlePeerConnectionEvents;
|
|
1561
1404
|
private setupTransceiversAsync;
|
|
@@ -1821,44 +1664,45 @@ declare class FpsMonitorService extends SubService {
|
|
|
1821
1664
|
static ɵprov: i0.ɵɵInjectableDeclaration<FpsMonitorService>;
|
|
1822
1665
|
}
|
|
1823
1666
|
|
|
1667
|
+
/**
|
|
1668
|
+
* `MetaBoxCommandList` / `MetaBoxCallbackList` are keyed by string-**enum**
|
|
1669
|
+
* members, which are nominal: a plain string literal like
|
|
1670
|
+
* `'loadProductCommandCallback'` is NOT assignable to the enum key
|
|
1671
|
+
* `MetaBoxCallback.FLoadProductCommandCallback`. So template-literal lookups
|
|
1672
|
+
* against `keyof MetaBoxCallbackList` always miss. We first re-key the callback
|
|
1673
|
+
* list by its plain string values, then bridge command→callback by string.
|
|
1674
|
+
*/
|
|
1675
|
+
type CallbackByString = {
|
|
1676
|
+
[C in keyof MetaBoxCallbackList as `${C & string}`]: MetaBoxCallbackList[C];
|
|
1677
|
+
};
|
|
1678
|
+
/**
|
|
1679
|
+
* Resolves a command key to its matching callback type via the
|
|
1680
|
+
* `F*Command` → `F*CommandCallback` naming convention
|
|
1681
|
+
* (e.g. command `'loadProduct'` → callback `'loadProductCommandCallback'`).
|
|
1682
|
+
*/
|
|
1683
|
+
type CommandCallbackFor<K extends keyof MetaBoxCommandList> = `${K & string}CommandCallback` extends keyof CallbackByString ? CallbackByString[`${K & string}CommandCallback`] : never;
|
|
1684
|
+
/** Every command keyed to its real callback type. */
|
|
1685
|
+
type UnrealCommandCallbackMap = {
|
|
1686
|
+
[K in keyof MetaBoxCommandList]: CommandCallbackFor<K>;
|
|
1687
|
+
};
|
|
1824
1688
|
/**
|
|
1825
1689
|
* Custom Unreal callback events that are not part of MetaBoxCommandList.
|
|
1826
1690
|
* These events are pushed from Unreal to the frontend via the data channel.
|
|
1691
|
+
* Keys are the runtime `command` values used for filtering.
|
|
1827
1692
|
*/
|
|
1828
1693
|
interface UnrealCallbackEventMap {
|
|
1829
|
-
onSceneState:
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
payload: FProductPayload;
|
|
1836
|
-
};
|
|
1837
|
-
cameraChanged: {
|
|
1838
|
-
command: 'cameraChanged';
|
|
1839
|
-
payload: FCameraChangedPayload;
|
|
1840
|
-
};
|
|
1841
|
-
onObjectTransformChanged: {
|
|
1842
|
-
command: 'onObjectTransformChanged';
|
|
1843
|
-
payload: {
|
|
1844
|
-
objectName: string;
|
|
1845
|
-
transform: FTransformJson;
|
|
1846
|
-
};
|
|
1847
|
-
};
|
|
1848
|
-
onChangeSequence: {
|
|
1849
|
-
command: 'onChangeSequence';
|
|
1850
|
-
payload: unknown;
|
|
1851
|
-
};
|
|
1852
|
-
onFinishedSequence: {
|
|
1853
|
-
command: 'onFinishedSequence';
|
|
1854
|
-
payload: unknown;
|
|
1855
|
-
};
|
|
1694
|
+
onSceneState: FOnSceneStateCallback;
|
|
1695
|
+
onFocusObject: FOnFocusObjectCallback;
|
|
1696
|
+
cameraChanged: FCameraChangedCallback;
|
|
1697
|
+
onObjectTransformChanged: FOnObjectTransformChangedCallback;
|
|
1698
|
+
onChangeSequence: FOnChangeSequenceChangedCallback;
|
|
1699
|
+
onFinishedSequence: FOnFinishSequenceChangedCallback;
|
|
1856
1700
|
}
|
|
1857
1701
|
/**
|
|
1858
|
-
* Combined map of all known callback
|
|
1859
|
-
*
|
|
1702
|
+
* Combined map of all known callback types: every command mapped to its real
|
|
1703
|
+
* callback (`MetaBoxCallbackList`) + the custom event callbacks.
|
|
1860
1704
|
*/
|
|
1861
|
-
type UnrealCallbackDescriptor =
|
|
1705
|
+
type UnrealCallbackDescriptor = UnrealCommandCallbackMap & UnrealCallbackEventMap;
|
|
1862
1706
|
declare class UnrealCallbackService {
|
|
1863
1707
|
private readonly actions$;
|
|
1864
1708
|
/**
|
|
@@ -1903,7 +1747,7 @@ declare class UnrealCallbackService {
|
|
|
1903
1747
|
* .subscribe();
|
|
1904
1748
|
* ```
|
|
1905
1749
|
*/
|
|
1906
|
-
observeCommandResponse<K extends keyof MetaBoxCommandList, T extends MetaBoxCommandList[K] = MetaBoxCommandList[K]>(data: T, sender: (data: T) => void, timeOut?: number, dispatchOnTimeout?: boolean): node_modules_rxjs_dist_types.Observable<
|
|
1750
|
+
observeCommandResponse<K extends keyof MetaBoxCommandList, T extends MetaBoxCommandList[K] = MetaBoxCommandList[K]>(data: T, sender: (data: T) => void, timeOut?: number, dispatchOnTimeout?: boolean): node_modules_rxjs_dist_types.Observable<CommandCallbackFor<K>>;
|
|
1907
1751
|
static ɵfac: i0.ɵɵFactoryDeclaration<UnrealCallbackService, never>;
|
|
1908
1752
|
static ɵprov: i0.ɵɵInjectableDeclaration<UnrealCallbackService>;
|
|
1909
1753
|
}
|
|
@@ -2616,44 +2460,6 @@ declare const showUnrealErrorMessage: node_modules__ngrx_store_types_ngrx_store.
|
|
|
2616
2460
|
error?: string;
|
|
2617
2461
|
} & node_modules__ngrx_store_types_ngrx_store.Action<string>>;
|
|
2618
2462
|
declare const initSignalling: node_modules__ngrx_store_types_ngrx_store.ActionCreator<string, () => node_modules__ngrx_store_types_ngrx_store.Action<string>>;
|
|
2619
|
-
/**
|
|
2620
|
-
* Dispatched when a prefetched connection parked on `window.__stream` by the
|
|
2621
|
-
* `stream-prefetch.js` head-script is adopted instead of opening a fresh
|
|
2622
|
-
* `connectToSignaling`. Marks cirrus connected and records the adopted machine
|
|
2623
|
-
* in one transaction; the data channel / app-init chain then proceeds via
|
|
2624
|
-
* `dataChannelConnected` dispatched from `WebRtcPlayerService`.
|
|
2625
|
-
*
|
|
2626
|
-
* Deliberately does NOT touch `streamClientCompanyId` / `streamViewId`: the host
|
|
2627
|
-
* app (e.g. metabox) sets those authoritatively from its own data before
|
|
2628
|
-
* `initSignalling`, and the prefetch script's ids are connection-internal only.
|
|
2629
|
-
*/
|
|
2630
|
-
declare const streamAdopted: node_modules__ngrx_store_types_ngrx_store.ActionCreator<string, (props: {
|
|
2631
|
-
machineId: string | null;
|
|
2632
|
-
ssData: SignalingData | null;
|
|
2633
|
-
/**
|
|
2634
|
-
* `performance.now()` marks the prefetch script recorded while it
|
|
2635
|
-
* established the connection (`prefetch_start` / `ws_open` / `dc_open` /
|
|
2636
|
-
* `ready`), on the page navigation timeline. The telemetry service uses
|
|
2637
|
-
* them to attribute the signaling / webrtc phase durations to the time the
|
|
2638
|
-
* prefetch actually spent — instead of dumping the whole pre-adoption wait
|
|
2639
|
-
* onto whichever phase closer happens to fire first. `null` when adopting a
|
|
2640
|
-
* stream that carried no timings.
|
|
2641
|
-
*/
|
|
2642
|
-
timings: Record<string, number> | null;
|
|
2643
|
-
}) => {
|
|
2644
|
-
machineId: string | null;
|
|
2645
|
-
ssData: SignalingData | null;
|
|
2646
|
-
/**
|
|
2647
|
-
* `performance.now()` marks the prefetch script recorded while it
|
|
2648
|
-
* established the connection (`prefetch_start` / `ws_open` / `dc_open` /
|
|
2649
|
-
* `ready`), on the page navigation timeline. The telemetry service uses
|
|
2650
|
-
* them to attribute the signaling / webrtc phase durations to the time the
|
|
2651
|
-
* prefetch actually spent — instead of dumping the whole pre-adoption wait
|
|
2652
|
-
* onto whichever phase closer happens to fire first. `null` when adopting a
|
|
2653
|
-
* stream that carried no timings.
|
|
2654
|
-
*/
|
|
2655
|
-
timings: Record<string, number> | null;
|
|
2656
|
-
} & node_modules__ngrx_store_types_ngrx_store.Action<string>>;
|
|
2657
2463
|
declare const startStream: node_modules__ngrx_store_types_ngrx_store.ActionCreator<string, (props: {
|
|
2658
2464
|
config: Partial<StreamConfig>;
|
|
2659
2465
|
}) => {
|
|
@@ -2750,11 +2556,11 @@ declare class UnrealEffects {
|
|
|
2750
2556
|
private readonly commandTelemetryService;
|
|
2751
2557
|
private readonly regionsPingService;
|
|
2752
2558
|
private readonly signallingService;
|
|
2753
|
-
private readonly streamAdoptionService;
|
|
2754
2559
|
private readonly videoService;
|
|
2755
2560
|
private readonly unrealCallbackService;
|
|
2756
2561
|
private dataChannelConnectionTimeout;
|
|
2757
2562
|
private connectionCompleted$;
|
|
2563
|
+
private reconnectConfig;
|
|
2758
2564
|
destroyConnections$: node_modules_rxjs_dist_types.Observable<{
|
|
2759
2565
|
reason: _3dsource_angular_unreal_module.DisconnectReasonType;
|
|
2760
2566
|
} & node_modules__ngrx_store_types_ngrx_store.Action<string>> & node_modules__ngrx_effects_types_ngrx_effects.CreateEffectMetadata;
|
|
@@ -2822,8 +2628,8 @@ declare class UnrealEffects {
|
|
|
2822
2628
|
* Effect: `handleDataChannelClosed$`
|
|
2823
2629
|
*
|
|
2824
2630
|
* Triggers peer reconnection when DataChannel closes unexpectedly.
|
|
2825
|
-
* Only triggers if reconnection is enabled
|
|
2826
|
-
* is still connected.
|
|
2631
|
+
* Only triggers if reconnection is enabled, onDataChannelClose is true,
|
|
2632
|
+
* and the signaling WebSocket is still connected.
|
|
2827
2633
|
*/
|
|
2828
2634
|
handleDataChannelClosed$: node_modules_rxjs_dist_types.Observable<{
|
|
2829
2635
|
attempt: number;
|
|
@@ -2868,9 +2674,7 @@ declare class UnrealEffects {
|
|
|
2868
2674
|
id: string;
|
|
2869
2675
|
now: number;
|
|
2870
2676
|
} & node_modules__ngrx_store_types_ngrx_store.Action<string>> & node_modules__ngrx_effects_types_ngrx_effects.CreateEffectMetadata;
|
|
2871
|
-
connectToSignaling$: node_modules_rxjs_dist_types.Observable<
|
|
2872
|
-
value: boolean;
|
|
2873
|
-
} & node_modules__ngrx_store_types_ngrx_store.Action<string>> & node_modules__ngrx_effects_types_ngrx_effects.CreateEffectMetadata;
|
|
2677
|
+
connectToSignaling$: node_modules_rxjs_dist_types.Observable<WebSocket> & node_modules__ngrx_effects_types_ngrx_effects.CreateEffectMetadata;
|
|
2874
2678
|
private canPeerReconnect;
|
|
2875
2679
|
/**
|
|
2876
2680
|
* Either schedules the next peer-reconnect attempt or gives up with the
|
|
@@ -2887,7 +2691,6 @@ declare const unrealFeature: {
|
|
|
2887
2691
|
name: "unrealFeature";
|
|
2888
2692
|
reducer: node_modules__ngrx_store_types_ngrx_store.ActionReducer<_3dsource_angular_unreal_module.UnrealState, node_modules__ngrx_store_types_ngrx_store.Action<string>>;
|
|
2889
2693
|
selectUnrealFeatureState: node_modules__ngrx_store_types_ngrx_store.MemoizedSelector<Record<string, any>, _3dsource_angular_unreal_module.UnrealState, (featureState: _3dsource_angular_unreal_module.UnrealState) => _3dsource_angular_unreal_module.UnrealState>;
|
|
2890
|
-
selectAdopted: node_modules__ngrx_store_types_ngrx_store.MemoizedSelector<Record<string, any>, boolean, (featureState: _3dsource_angular_unreal_module.UnrealState) => boolean>;
|
|
2891
2694
|
selectFreezeFrame: node_modules__ngrx_store_types_ngrx_store.MemoizedSelector<Record<string, any>, _3dsource_angular_unreal_module.FreezeFrameMessage, (featureState: _3dsource_angular_unreal_module.UnrealState) => _3dsource_angular_unreal_module.FreezeFrameMessage>;
|
|
2892
2695
|
selectIsVideoPlaying: node_modules__ngrx_store_types_ngrx_store.MemoizedSelector<Record<string, any>, boolean, (featureState: _3dsource_angular_unreal_module.UnrealState) => boolean>;
|
|
2893
2696
|
selectStatusMessage: node_modules__ngrx_store_types_ngrx_store.MemoizedSelector<Record<string, any>, string | null, (featureState: _3dsource_angular_unreal_module.UnrealState) => string | null>;
|
|
@@ -2944,13 +2747,6 @@ interface UnrealState {
|
|
|
2944
2747
|
isAfkTimerVisible: boolean;
|
|
2945
2748
|
afkCountdown: number;
|
|
2946
2749
|
cirrusConnected: boolean;
|
|
2947
|
-
/**
|
|
2948
|
-
* True once a prefetched connection has been adopted (`streamAdopted`).
|
|
2949
|
-
* Read synchronously by the telemetry service so the connection-phase
|
|
2950
|
-
* closers know to defer to the prefetch-timed attribution instead of the
|
|
2951
|
-
* live-event one. Reset on every fresh attempt / disconnect.
|
|
2952
|
-
*/
|
|
2953
|
-
adopted: boolean;
|
|
2954
2750
|
viewportReady: boolean;
|
|
2955
2751
|
freezeFrameFromVideo: FreezeFrameMessage;
|
|
2956
2752
|
freezeFrame: FreezeFrameMessage;
|
|
@@ -3036,5 +2832,5 @@ declare const selectUserInactivityDetected: node_modules__ngrx_store_types_ngrx_
|
|
|
3036
2832
|
/** Used by external consumers (e.g., metabox). Do not remove. */
|
|
3037
2833
|
declare const selectIsVideoPlayingAndDataChannelConnected: node_modules__ngrx_store_types_ngrx_store.MemoizedSelector<Record<string, any>, boolean, (s1: boolean, s2: boolean) => boolean>;
|
|
3038
2834
|
|
|
3039
|
-
export { AFKService, AUTO_HIGH_RESOLUTION_IDLE_MS, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler,
|
|
3040
|
-
export type { AggregatedStat, AnySignalingMessage, AwsInstance, CandidateMessage, CloseReason, CommandInProgress, ConfigMessage, ConnectionError, ControlSchemeValues, DataFlowCheckResult, DisconnectReasonType, EmittedMilestone, EventId, ForceClientDisconnect, FreezeFrameMessage, InboundVideoStats, InputProps, InstanceReady, InstanceReserved, InterruptClientStream, ListStreamersMessage, MessageBase, MessageTypeValues,
|
|
2835
|
+
export { AFKService, AUTO_HIGH_RESOLUTION_IDLE_MS, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, CommandTelemetryService, 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, INNER_RETRY_LIMIT, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LoadingProgressService, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MIN_CONTAINER_SIZE, MessageType, MouseButton, MouseButtonsMask, OUTER_RETRY_DELAY, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, REGION_PING_ACCURATE_SAMPLES, REGION_PING_BACKGROUND_REFRESH_DELAY_MS, REGION_PING_CACHE_KEY, REGION_PING_CACHE_TTL_MS, REGION_PING_WARMUP_DEADLINE_MS, 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_RETRY_PER_INSTANCE, WS_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, answerSent, changeStatusMainVideoOnScene, changeStreamResolutionAction, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, dropDC, dropPC, floatToPercents, floatToSmoothPercents, forceResizeViewport, fromResizeObserver, getActiveUrl, getImageFromVideoStream, getResizeStudioValues, getResizeValuesUniversal, getRtcErrorMessage, iceConnectionFailed, initSignalling, instanceReady, keepMaxUntilReset, makeEven, pollingEnded, pollingStarted, provideUnrealModule, provideUnrealState, 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, selectIsVideoPlayingAndDataChannelConnected, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectUserInactivityDetected, 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, signalingRetryAttempted, smoothTransition, startStream, trackMixpanelEvent, trackTelemetryData, uint8ToBase64, unrealCommandCallback, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
|
|
2836
|
+
export type { AggregatedStat, AnySignalingMessage, AwsInstance, CandidateMessage, CloseReason, CommandInProgress, ConfigMessage, ConnectionError, ControlSchemeValues, DataFlowCheckResult, DisconnectReasonType, EmittedMilestone, EventId, ForceClientDisconnect, FreezeFrameMessage, InboundVideoStats, InputProps, InstanceReady, InstanceReserved, InterruptClientStream, ListStreamersMessage, MessageBase, MessageTypeValues, OrchestrationErrorMessage, OrchestrationMessageType, P2PEstablishedMessage, PhaseOverlay, PhaseParam, PingMessage, PlayerCountMessage, PollingOrchestrationMessage, Quality, ReceivedFile, ReconnectConfig, RequestStream, SSInfo, SelectedIceCandidatePair, SignalingData, SignalingMessageHandler, SignalingMessageMap, StreamConfig, StreamRequestContext, StreamResolutionProps, StreamerListMessage, TelemetryType, UnknownFields, UnrealCallbackDescriptor, UnrealCallbackEventMap, UnrealCallbackJson, UnrealCallbackJsonWrapped, UnrealInitialConfig, UnrealState, WSCloseCodesValues, streamPreparedForUserInteractionMessage };
|
package/js/stream-prefetch.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
"use strict";(()=>{"use strict";const f="metabox-configurator",m=/metabox-configurator\/(modular|basic)\/([^/?#]+)/i,g="3dsource:region-ping",k="assets/config.json",w="42e01f";function l(){return typeof crypto!="undefined"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,o=>{const t=Math.random()*16|0;return(o==="x"?t:t&3|8).toString(16)})}function I(o){return o.replace("http://","ws://").replace("https://","wss://")}const h="[stream-prefetch]",s=(...o)=>console.log(h,...o),c=(...o)=>console.warn(h,...o),u=(...o)=>console.error(h,...o);class y{constructor(){const t=document.currentScript||(()=>{const n=document.getElementsByTagName("script");return n[n.length-1]})(),e=t&&t.dataset||{};this.configUrl=e.configUrl||k,this.fallbackPollingUrl=e.fallbackUrl||"",this.skipRouteCheck=this.boolOr(e.skipRouteCheck,!1),this.config={ws_timeout:this.numberOr(e.wsTimeout,6e3),poll_timeout:this.numberOr(e.pollTimeout,4e3)};const i=new URLSearchParams(window.location.search);this.forceTURN=i.has("ForceTURN"),this.forceMaxBundle=i.has("ForceMaxBundle"),this.forceMonoAudio=i.has("forceMono"),this.ids={clientId:l(),viewId:l(),correlationId:l()},this.context=null,this.environmentId=void 0,this.orchestrationType="",this.region="",this.requireEnvironmentId=!0,this.pc=null,this.dc=null,this.stream=null,this.ws=null,this.remoteDescriptionSet=!1,this.iceBuffer=[],this.wsTimeoutId=null,this.settled=!1}run(){if(typeof window=="undefined"||!("WebSocket"in window)||!("RTCPeerConnection"in window))return;if(this.skipRouteCheck){this.context={},this.requireEnvironmentId=!1,c("skipRouteCheck=true \u2014 ignoring URL gate, route, context and environmentId; using fallback polling"),this.publishParked("connecting"),this.connect().catch(e=>this.fail("exception",e));return}if(window.location.href.indexOf(f)===-1){s("skip \u2014 URL does not contain gate",`"${f}"`);return}const t=this.parseConfiguratorUrl();t?(this.context={id:t.contextId,data:{configuratorId:t.configuratorId}},this.requireEnvironmentId=!0,s("start",{contextId:t.contextId,configuratorId:t.configuratorId,ids:this.ids})):(this.context={},this.requireEnvironmentId=!1,c("URL is not a configurator route \u2014 prefetching with empty context {} and no required environmentId",window.location.pathname)),this.publishParked("connecting"),this.connect().catch(e=>this.fail("exception",e))}parseConfiguratorUrl(){const t=window.location.pathname.match(m);return t?{contextId:t[1].toLowerCase()==="modular"?"metaboxModularConfigurator":"metaboxBasicConfigurator",configuratorId:decodeURIComponent(t[2])}:null}connect(){return this.mark("prefetch_start"),this.region=this.readRegion()||"",s("region from cache:",this.region||"(none)"),(this.skipRouteCheck?Promise.resolve(null):this.fetchConfig()).then(e=>{let i;if(e)i=this.chooseEndpoint(e);else if(this.fallbackPollingUrl)c("no app config \u2014 falling back to polling",this.fallbackPollingUrl),i={type:"polling",url:this.fallbackPollingUrl,environmentId:""},this.requireEnvironmentId=!1;else{this.fail("no-config");return}if(!i){this.fail("no-endpoint");return}if(s("endpoint chosen",{type:i.type,url:i.url,environmentId:i.environmentId}),this.requireEnvironmentId&&!i.environmentId){this.fail("no-environment-id");return}this.orchestrationType=i.type,this.environmentId=i.environmentId||void 0;const n=this.adaptUrlToRegion(i.url);return(i.type==="polling"?this.pollOrchestration(n):Promise.resolve(n)).then(a=>{if(!a){this.fail("no-ws-url");return}return this.parked.machineId=a,s("opening socket",a),this.openSocket(a)})})}fetchConfig(){const t=new URL(this.configUrl,window.location.origin).href;return this.fetchWithTimeout(t,{credentials:"omit"},this.config.poll_timeout).then(e=>e.ok?e.json().catch(()=>null):null).catch(()=>null)}chooseEndpoint(t){const e=t.newSignalling,i=this.firstVersionUrl(e&&e.versions);if(i&&/^wss?:\/\//i.test(i))return{type:"direct",url:i,environmentId:e&&e.environmentId||""};const n=t.signalling,r=this.firstVersionUrl(n&&n.versions);return r?(this.requireEnvironmentId=!1,{type:"polling",url:r,environmentId:n&&n.environmentId||""}):null}firstVersionUrl(t){if(!t||typeof t!="object")return"";for(const e of Object.keys(t))if(t[e])return t[e];return""}pollOrchestration(t){const e=`${t}${this.ids.clientId}/${this.ids.viewId}`;return this.fetchWithTimeout(e,{credentials:"omit"},this.config.poll_timeout).then(i=>i.ok?i.json().catch(()=>({})):null).then(i=>i&&i.signallingServer?I(`${window.location.protocol}//${i.signallingServer}`):null).catch(()=>null)}adaptUrlToRegion(t){return this.region&&t.indexOf(":region")===-1?t.replace(/signallingserver/gi,`signallingserver/region:${this.region}`):t}openSocket(t){const e=new WebSocket(t);e.binaryType="arraybuffer",this.ws=e,this.parked.ws=e,this.wsTimeoutId=setTimeout(()=>{e.readyState!==WebSocket.OPEN&&this.fail("ws-timeout")},this.config.ws_timeout),e.onopen=()=>{clearTimeout(this.wsTimeoutId),this.mark("ws_open"),s("WS open \u2192 sending requestStream",{environmentId:this.environmentId,region:this.region,context:this.context}),this.sendRequestStream()},e.onmessage=i=>this.onWsMessage(i),e.onerror=i=>{u("WS error",i),this.fail("ws-error")},e.onclose=i=>{!this.settled&&this.parked.state!=="ready"&&(c("WS closed before ready",{code:i&&i.code}),this.fail("ws-closed"))}}sendRequestStream(){this.send({type:"requestStream",correlationId:this.ids.correlationId,payload:{region:this.region,environmentId:this.environmentId,context:this.context}})}onWsMessage(t){let e;try{const i=typeof t.data=="string"?t.data:null;if(i===null)return;e=JSON.parse(i)}catch{return}switch(s("WS \u2190",e.type),e.type){case"ssInfo":this.parked.ssData=e.data;break;case"config":this.onConfig(e);break;case"offer":this.onOffer(e);break;case"answer":this.onAnswer(e);break;case"iceCandidate":this.onIceCandidate(e.candidate);break;case"ping":this.send({type:"pong",source:"front"});break;case"streamerDisconnected":case"playerDisconnected":this.fail("streamer-disconnected");break;case"error":this.fail("orchestration-error");break;default:break}}onConfig(t){if(this.pc)return;const e=Object.assign({},t.peerConnectionOptions);this.forceTURN&&(e.iceTransportPolicy="relay"),e.bundlePolicy=this.forceMaxBundle?"max-bundle":"balanced",e.iceCandidatePoolSize=1,this.parked.config=e;const i=new RTCPeerConnection(e);this.pc=i,this.parked.pc=i,s("PeerConnection created from config"),i.onicecandidate=n=>{n.candidate&&this.send({type:"iceCandidate",candidate:n.candidate})},i.ondatachannel=n=>this.wireDataChannel(n.channel),i.ontrack=n=>{n.track&&n.track.kind==="video"&&n.streams[0]&&(s("video track received"),this.stream=n.streams[0],this.parked.stream=this.stream,this.maybeReady())}}onOffer(t){return this.pc?(this.remoteDescriptionSet=!1,this.iceBuffer.length=0,this.pc.setRemoteDescription(t).then(()=>(this.remoteDescriptionSet=!0,this.flushIce(),this.pc.createAnswer())).then(e=>(e.sdp=this.mungeSDP(e.sdp||""),this.pc.setLocalDescription(e).then(()=>{s("WS \u2192 answer sent"),this.send(e)}))).catch(e=>this.fail("offer-failed",e))):Promise.resolve()}onAnswer(t){return this.pc?this.pc.setRemoteDescription(t).then(()=>{this.remoteDescriptionSet=!0,this.flushIce()}).catch(e=>this.fail("answer-failed",e)):Promise.resolve()}onIceCandidate(t){t&&(this.forceTURN&&String(t.candidate).indexOf("relay")<0||(this.remoteDescriptionSet&&this.pc?this.pc.addIceCandidate(t).catch(()=>{}):this.iceBuffer.push(t)))}flushIce(){for(const t of this.iceBuffer)this.pc.addIceCandidate(t).catch(()=>{});this.iceBuffer.length=0}wireDataChannel(t){t.binaryType="arraybuffer",this.dc=t,this.parked.dc=t,t.onmessage=e=>{this.parked.dcBuffer.push(e.data)},t.onopen=()=>{s("DataChannel open"),this.mark("dc_open"),this.maybeReady()},t.onclose=()=>{!this.settled&&this.parked.state!=="ready"&&(c("DataChannel closed before ready"),this.fail("dc-closed"))},t.readyState==="open"&&this.maybeReady()}maybeReady(){this.settled||!this.dc||this.dc.readyState!=="open"||this.stream&&(this.settled=!0,this.mark("ready"),this.parked.state="ready",s("READY \u2014 parked on window.__stream",this.parked.timings))}publishParked(t){const e=this;this.parked={state:t,pc:null,dc:null,stream:null,ws:null,ssData:void 0,machineId:void 0,config:void 0,ids:this.ids,dcBuffer:[],timings:{},adopt(){return e.clearTimers(),this.state="adopted",this}},window.__stream=this.parked}clearTimers(){this.wsTimeoutId&&(clearTimeout(this.wsTimeoutId),this.wsTimeoutId=null)}fail(t,e){if(!(this.parked&&(this.parked.state==="adopted"||this.parked.state==="failed"))){u("FAILED:",t,e||""),this.settled=!0,this.clearTimers();try{this.dc&&this.dc.close()}catch{}try{this.pc&&this.pc.close()}catch{}try{this.ws&&this.ws.close()}catch{}this.parked&&(this.parked.state="failed",this.parked.failReason=t,e&&(this.parked.failError=String(e&&e.message||e)))}}mungeSDP(t){let e=this.prioritizeH264Profile(t,w);e=e.replace(/(a=fmtp:\d+ .*level-asymmetry-allowed=.*)\r\n/gm,`$1;x-google-start-bitrate=10000;x-google-max-bitrate=100000\r
|
|
2
|
-
`);let i="maxaveragebitrate=510000;";return i+=this.forceMonoAudio?"stereo=0;":"stereo=1;",i+="useinbandfec=1",e=e.replace("useinbandfec=1",i),e}prioritizeH264Profile(t,e){const i=t.split(`\r
|
|
3
|
-
`),n=[];for(const r of i)if(r.startsWith("a=fmtp:")&&r.toLowerCase().includes(`profile-level-id=${e}`)){const a=r.split(":")[1]&&r.split(":")[1].split(" ")[0];a&&n.push(a)}return n.length===0?t:i.map(r=>{if(!r.startsWith("m=video"))return r;const a=r.split(" "),x=a.slice(0,3),p=a.slice(3),b=[...n.filter(d=>p.includes(d)),...p.filter(d=>!n.includes(d))];return[...x,...b].join(" ")}).join(`\r
|
|
4
|
-
`)}send(t){const e=typeof t=="string"?t:JSON.stringify(t);if(this.ws&&this.ws.readyState===WebSocket.OPEN)try{this.ws.send(e)}catch{}}mark(t){this.parked&&(this.parked.timings[t]=performance.now())}readRegion(){try{const t=localStorage.getItem(g);if(!t)return null;const e=JSON.parse(t);return!e||typeof e.region_code!="string"||typeof e.ts!="number"||Date.now()-e.ts>=2592e6?null:e.region_code}catch{return null}}fetchWithTimeout(t,e,i){const n=new AbortController;e.signal=n.signal;const r=setTimeout(()=>n.abort(),i);return fetch(t,e).finally(()=>clearTimeout(r))}numberOr(t,e){const i=Number(t);return t!=null&&t!==""&&!Number.isNaN(i)?i:e}boolOr(t,e){return t==="true"||t===""?!0:t==="false"?!1:e}}new y().run()})();
|