@3dsource/angular-unreal-module 0.0.199 → 0.0.200-dev.1
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
CHANGED
|
File without changes
|
|
@@ -3,7 +3,7 @@ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef,
|
|
|
3
3
|
import { JsonPipe, NgOptimizedImage, NgTemplateOutlet } from "@angular/common";
|
|
4
4
|
import { Store, createAction, createFeature, createReducer, createSelector, on, props, provideState } from "@ngrx/store";
|
|
5
5
|
import { Actions, createEffect, ofType, provideEffects } from "@ngrx/effects";
|
|
6
|
-
import { BehaviorSubject, EMPTY, NEVER, Observable, Subject, Subscription, animationFrameScheduler, asyncScheduler, bufferTime, combineLatestWith, concat, concatMap, debounceTime, defer, delay, filter, firstValueFrom, from, fromEvent, ignoreElements, interval, map, merge, mergeMap, of, pairwise, repeat, retry, scan, share, shareReplay, skip, startWith, switchMap, take, takeUntil, takeWhile, tap, throttleTime, throwError, timeout, timer, timestamp, withLatestFrom } from "rxjs";
|
|
6
|
+
import { BehaviorSubject, EMPTY, NEVER, Observable, Subject, Subscription, TimeoutError, animationFrameScheduler, asyncScheduler, bufferTime, combineLatestWith, concat, concatMap, debounceTime, defer, delay, filter, firstValueFrom, from, fromEvent, ignoreElements, interval, map, merge, mergeMap, of, pairwise, repeat, retry, scan, share, shareReplay, skip, startWith, switchMap, take, takeUntil, takeWhile, tap, throttleTime, throwError, timeout, timer, timestamp, withLatestFrom } from "rxjs";
|
|
7
7
|
import { UNREAL_CONFIG } from "@3dsource/angular-unreal-module/config";
|
|
8
8
|
import { catchError, debounceTime as debounceTime$1, distinctUntilChanged, exhaustMap, filter as filter$1, finalize, first, map as map$1, startWith as startWith$1, switchMap as switchMap$1, take as take$1, takeUntil as takeUntil$1, takeWhile as takeWhile$1, tap as tap$1, timeout as timeout$1, withLatestFrom as withLatestFrom$1 } from "rxjs/operators";
|
|
9
9
|
import { v4 } from "uuid";
|
|
@@ -567,6 +567,8 @@ const RECONNECT_CONFIG = {
|
|
|
567
567
|
maxAttempts: 3,
|
|
568
568
|
delayMs: 1e3
|
|
569
569
|
};
|
|
570
|
+
const DC_WATCH_INTERVAL_MS = 1e3;
|
|
571
|
+
const DC_CLOSING_GRACE_MS = 2e3;
|
|
570
572
|
const DATA_CHANNEL_TIMEOUT_RESTARTS = {
|
|
571
573
|
hidden: 3,
|
|
572
574
|
visible: 10
|
|
@@ -1804,6 +1806,7 @@ const ORCHESTRATION_ERROR_CODES = {
|
|
|
1804
1806
|
};
|
|
1805
1807
|
const RETRY_CODES = /* @__PURE__ */ new Set([ORCHESTRATION_ERROR_CODES.NO_AVAILABLE_INSTANCES.code, ORCHESTRATION_ERROR_CODES.LIMIT_REACHED.code]);
|
|
1806
1808
|
function OrchestrationErrorHandler(msg) {
|
|
1809
|
+
this.onOrchestrationError$.next(msg.payload);
|
|
1807
1810
|
if (RETRY_CODES.has(msg.payload.code)) {
|
|
1808
1811
|
const errorInfo = Object.values(ORCHESTRATION_ERROR_CODES).find(({ code }) => code === msg.payload.code);
|
|
1809
1812
|
this.store.dispatch(setOrchestrationMessage({ message: errorInfo?.description }));
|
|
@@ -1831,6 +1834,10 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
1831
1834
|
this.onWebRtcIce$ = new Subject();
|
|
1832
1835
|
this.onWebRtcAnswer$ = new Subject();
|
|
1833
1836
|
this.onInstanceReady$ = new Subject();
|
|
1837
|
+
this.onRequestStreamSent$ = new Subject();
|
|
1838
|
+
this.onOrchestrationError$ = new Subject();
|
|
1839
|
+
this.onCirrusClose$ = new Subject();
|
|
1840
|
+
this.onPollResponse$ = new Subject();
|
|
1834
1841
|
this.abort$ = this.actions$.pipe(ofType(abortEstablishingConnection));
|
|
1835
1842
|
this.ws = null;
|
|
1836
1843
|
this.controlWs = null;
|
|
@@ -1978,8 +1985,13 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
1978
1985
|
}));
|
|
1979
1986
|
}
|
|
1980
1987
|
pollLoop(url) {
|
|
1981
|
-
|
|
1988
|
+
let sentAt = 0;
|
|
1989
|
+
return defer(() => {
|
|
1990
|
+
sentAt = performance.now();
|
|
1991
|
+
return this.httpClient.get(url);
|
|
1992
|
+
}).pipe(timeout(POLLING_TIME), tap$1((data) => this.onPollResponse$.next(pollResponse(200, data, sentAt))), catchError((err) => {
|
|
1982
1993
|
const status = err?.status;
|
|
1994
|
+
this.onPollResponse$.next(pollResponse(typeof status === "number" && status > 0 ? status : err instanceof TimeoutError ? "timeout" : "network", null, sentAt));
|
|
1983
1995
|
if (typeof status === "number" && status >= 400 && status < 500 && status !== 429) {
|
|
1984
1996
|
Logger.warn(`Polling HARD error on ${url} (HTTP ${status}); rotating URL`);
|
|
1985
1997
|
return throwError(() => err);
|
|
@@ -2122,6 +2134,7 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
2122
2134
|
context
|
|
2123
2135
|
}
|
|
2124
2136
|
});
|
|
2137
|
+
this.onRequestStreamSent$.next(this.correlationId);
|
|
2125
2138
|
}
|
|
2126
2139
|
isConnected() {
|
|
2127
2140
|
return !!(this.ws && this.ws.readyState === 1);
|
|
@@ -2161,6 +2174,15 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2161
2174
|
}],
|
|
2162
2175
|
ctorParameters: () => []
|
|
2163
2176
|
});
|
|
2177
|
+
function pollResponse(status, data, sentAt) {
|
|
2178
|
+
return {
|
|
2179
|
+
status,
|
|
2180
|
+
ms: Math.round(performance.now() - sentAt),
|
|
2181
|
+
ready: !!data?.signallingServer,
|
|
2182
|
+
percent: data?.info?.percent ?? null,
|
|
2183
|
+
message: data?.mm_message || data?.error || null
|
|
2184
|
+
};
|
|
2185
|
+
}
|
|
2164
2186
|
function finite(value) {
|
|
2165
2187
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2166
2188
|
}
|
|
@@ -2838,14 +2860,22 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2838
2860
|
});
|
|
2839
2861
|
fromEvent(datachannel, "message").pipe(map$1((e) => e.data), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe((data) => this.onDataChannelMessage$.next(data));
|
|
2840
2862
|
for (const buffered of replay) this.onDataChannelMessage$.next(buffered);
|
|
2841
|
-
|
|
2863
|
+
const open$ = datachannel.readyState === "open" ? of(null) : fromEvent(datachannel, "open").pipe(take(1));
|
|
2864
|
+
open$.pipe(tap(() => {
|
|
2842
2865
|
Logger.info(`[DATACHANNEL] Data channel "${datachannel.label}" connected. id:${datachannel.id}`);
|
|
2843
2866
|
}), switchMap$1(() => this.videoService.video$.pipe(filter$1(Truthy), take(1))), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe(() => this.onDataChannelConnected());
|
|
2867
|
+
this.watchForStuckClose(datachannel, open$);
|
|
2844
2868
|
} catch (e) {
|
|
2845
2869
|
Logger.warn("[DATACHANNEL] Datachannel setup caused an exception: ", e);
|
|
2846
2870
|
this.dcClient = null;
|
|
2847
2871
|
}
|
|
2848
2872
|
}
|
|
2873
|
+
watchForStuckClose(datachannel, open$) {
|
|
2874
|
+
open$.pipe(switchMap$1(() => interval(DC_WATCH_INTERVAL_MS)), filter$1(() => datachannel.readyState === "closing" || datachannel.readyState === "closed"), take(1), switchMap$1(() => timer(DC_CLOSING_GRACE_MS)), filter$1(() => this.dcClient === datachannel && datachannel.readyState !== "open"), takeUntil$1(merge(fromEvent(datachannel, "close"), this.disconnect$, this.destroy$))).subscribe(() => {
|
|
2875
|
+
Logger.warn(`[DATACHANNEL] "${datachannel.label}" stuck in "${datachannel.readyState}" with no close event, reconnecting the peer`);
|
|
2876
|
+
this.tryReconnectOnSendFailure();
|
|
2877
|
+
});
|
|
2878
|
+
}
|
|
2849
2879
|
onDataChannelConnected() {
|
|
2850
2880
|
let statusMessage = "Session connected, video stream starting.";
|
|
2851
2881
|
if (navigator.userAgent.includes("Firefox")) statusMessage += "\n If you are experiencing connection problems please try Google Chrome";
|
|
@@ -2908,6 +2938,13 @@ var StreamAdoptionService = class StreamAdoptionService {
|
|
|
2908
2938
|
this.store = inject(Store);
|
|
2909
2939
|
this.signalling = inject(SignallingService);
|
|
2910
2940
|
this.webRtc = inject(WebRtcPlayerService);
|
|
2941
|
+
this.report$ = new Subject();
|
|
2942
|
+
this.waitStarted$ = new Subject();
|
|
2943
|
+
this.waiting = null;
|
|
2944
|
+
}
|
|
2945
|
+
waitingReport() {
|
|
2946
|
+
const w = this.waiting;
|
|
2947
|
+
return w ? reportOf(w.parked, "waiting", w.sincePerf) : null;
|
|
2911
2948
|
}
|
|
2912
2949
|
awaitAndAdopt$() {
|
|
2913
2950
|
return defer(() => {
|
|
@@ -2917,32 +2954,47 @@ var StreamAdoptionService = class StreamAdoptionService {
|
|
|
2917
2954
|
return of(false);
|
|
2918
2955
|
}
|
|
2919
2956
|
if (isAppOwned(slot)) return of(false);
|
|
2920
|
-
if (slot.state !== "connecting") return of(this.
|
|
2957
|
+
if (slot.state !== "connecting") return of(this.settle(slot, null));
|
|
2921
2958
|
Logger.info("[Adoption] Prefetch in progress — waiting before connecting");
|
|
2959
|
+
this.waitStarted$.next();
|
|
2922
2960
|
return this.awaitSettled$(slot);
|
|
2923
2961
|
});
|
|
2924
2962
|
}
|
|
2925
2963
|
awaitSettled$(parked) {
|
|
2926
2964
|
return new Observable((subscriber) => {
|
|
2927
2965
|
let done = false;
|
|
2966
|
+
const sincePerf = performance.now();
|
|
2967
|
+
this.waiting = {
|
|
2968
|
+
parked,
|
|
2969
|
+
sincePerf
|
|
2970
|
+
};
|
|
2928
2971
|
parked.onSettled(() => {
|
|
2929
2972
|
if (done) return;
|
|
2930
2973
|
done = true;
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
adopted = this.tryAdoptOrTakeSlot();
|
|
2934
|
-
} catch (e) {
|
|
2935
|
-
Logger.error("[Adoption] Adoption threw — falling back", e);
|
|
2936
|
-
this.takeSlot();
|
|
2937
|
-
}
|
|
2938
|
-
subscriber.next(adopted);
|
|
2974
|
+
this.waiting = null;
|
|
2975
|
+
subscriber.next(this.settle(parked, sincePerf));
|
|
2939
2976
|
subscriber.complete();
|
|
2940
2977
|
});
|
|
2941
2978
|
return () => {
|
|
2979
|
+
if (done) return;
|
|
2942
2980
|
done = true;
|
|
2981
|
+
this.waiting = null;
|
|
2982
|
+
this.report$.next(reportOf(parked, "abandoned", sincePerf));
|
|
2943
2983
|
};
|
|
2944
2984
|
});
|
|
2945
2985
|
}
|
|
2986
|
+
settle(parked, sincePerf) {
|
|
2987
|
+
let adopted = false;
|
|
2988
|
+
try {
|
|
2989
|
+
adopted = this.tryAdoptOrTakeSlot();
|
|
2990
|
+
} catch (e) {
|
|
2991
|
+
Logger.error("[Adoption] Adoption threw — falling back", e);
|
|
2992
|
+
this.takeSlot();
|
|
2993
|
+
}
|
|
2994
|
+
const outcome = adopted ? "adopted" : parked.state === "failed" ? "failed" : parked.state === "ready" ? "dead" : null;
|
|
2995
|
+
if (outcome) this.report$.next(reportOf(parked, outcome, sincePerf));
|
|
2996
|
+
return adopted;
|
|
2997
|
+
}
|
|
2946
2998
|
tryAdoptOrTakeSlot() {
|
|
2947
2999
|
const adopted = this.tryAdopt();
|
|
2948
3000
|
if (!adopted) this.takeSlot();
|
|
@@ -2969,7 +3021,7 @@ var StreamAdoptionService = class StreamAdoptionService {
|
|
|
2969
3021
|
if (!slot || isAppOwned(slot)) return false;
|
|
2970
3022
|
const parked = slot;
|
|
2971
3023
|
if (parked.state !== "ready") return false;
|
|
2972
|
-
if (!parked.ws || parked.ws.readyState !== 1 || !parked.pc || !parked.dc || !parked.stream) {
|
|
3024
|
+
if (parked.deadReason || !parked.ws || parked.ws.readyState !== 1 || !parked.pc || DEAD_PC_STATES.has(parked.pc.connectionState) || !parked.dc || DEAD_DC_STATES.has(parked.dc.readyState) || !parked.stream) {
|
|
2973
3025
|
Logger.warn("[Adoption] Parked stream is ready but transport is not live");
|
|
2974
3026
|
return false;
|
|
2975
3027
|
}
|
|
@@ -2980,6 +3032,7 @@ var StreamAdoptionService = class StreamAdoptionService {
|
|
|
2980
3032
|
pollingUrl: parked.pollingUrl ?? null,
|
|
2981
3033
|
ssData: parked.ssData ?? null,
|
|
2982
3034
|
streamRequestId: parked.ids?.streamRequestId || null,
|
|
3035
|
+
correlationId: parked.ids?.correlationId || null,
|
|
2983
3036
|
kind: parked.kind ?? null,
|
|
2984
3037
|
instanceName: parked.instanceName ?? null,
|
|
2985
3038
|
eta: parked.eta ?? null,
|
|
@@ -3020,6 +3073,20 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
3020
3073
|
args: [{ providedIn: "root" }]
|
|
3021
3074
|
}]
|
|
3022
3075
|
});
|
|
3076
|
+
const DEAD_PC_STATES = /* @__PURE__ */ new Set(["failed", "closed"]);
|
|
3077
|
+
const DEAD_DC_STATES = /* @__PURE__ */ new Set(["closing", "closed"]);
|
|
3078
|
+
function reportOf(parked, outcome, sincePerf) {
|
|
3079
|
+
return {
|
|
3080
|
+
outcome,
|
|
3081
|
+
failReason: outcome === "dead" ? parked.deadReason ?? "transport-not-live" : parked.failReason ?? null,
|
|
3082
|
+
failError: parked.failError ?? null,
|
|
3083
|
+
waitMs: sincePerf === null ? null : Math.round(performance.now() - sincePerf),
|
|
3084
|
+
kind: parked.kind ?? null,
|
|
3085
|
+
instanceName: parked.instanceName ?? null,
|
|
3086
|
+
streamRequestId: parked.ids?.streamRequestId || null,
|
|
3087
|
+
trail: [...parked.trail ?? []]
|
|
3088
|
+
};
|
|
3089
|
+
}
|
|
3023
3090
|
var UnrealCallbackService = class UnrealCallbackService {
|
|
3024
3091
|
constructor() {
|
|
3025
3092
|
this.actions$ = inject(Actions);
|
|
@@ -3542,6 +3609,10 @@ const dropCodes = [
|
|
|
3542
3609
|
function OnCloseHandler(e) {
|
|
3543
3610
|
const message = `WebSocket closed: ${JSON.stringify(e.code)} - ${e.reason}`;
|
|
3544
3611
|
Logger.warn(message);
|
|
3612
|
+
this.onCirrusClose$.next({
|
|
3613
|
+
code: e.code,
|
|
3614
|
+
reason: e.reason
|
|
3615
|
+
});
|
|
3545
3616
|
this.store.dispatch(setCirrusDisconnected());
|
|
3546
3617
|
if (dropCodes.includes(e.code)) this.store.dispatch(dropConnection());
|
|
3547
3618
|
}
|
|
@@ -5155,6 +5226,7 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5155
5226
|
this.videoService = inject(VideoService);
|
|
5156
5227
|
this.signallingService = inject(SignallingService);
|
|
5157
5228
|
this.webRtcPlayer = inject(WebRtcPlayerService);
|
|
5229
|
+
this.adoption = inject(StreamAdoptionService);
|
|
5158
5230
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
5159
5231
|
this.destroyRef = inject(DestroyRef);
|
|
5160
5232
|
this.destroy$ = new Subject();
|
|
@@ -5203,6 +5275,10 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5203
5275
|
id: "region-resolving",
|
|
5204
5276
|
color: "#61afef",
|
|
5205
5277
|
milestones: [
|
|
5278
|
+
{
|
|
5279
|
+
id: "prefetch-wait-start",
|
|
5280
|
+
event: this.adoption.waitStarted$
|
|
5281
|
+
},
|
|
5206
5282
|
{
|
|
5207
5283
|
id: "region-ping-fetch-start",
|
|
5208
5284
|
event: this.actions$.pipe(ofType(regionPingFetchStart))
|
|
@@ -5235,6 +5311,10 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5235
5311
|
id: "polling-ended",
|
|
5236
5312
|
event: this.actions$.pipe(ofType(pollingEnded))
|
|
5237
5313
|
},
|
|
5314
|
+
{
|
|
5315
|
+
id: "request-stream-sent",
|
|
5316
|
+
event: this.signallingService.onRequestStreamSent$
|
|
5317
|
+
},
|
|
5238
5318
|
this.awsInstanceResolvedEntry,
|
|
5239
5319
|
this.signalingServerConnectedEntry,
|
|
5240
5320
|
{
|
|
@@ -5248,12 +5328,7 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5248
5328
|
this.configReceivedEntry,
|
|
5249
5329
|
{
|
|
5250
5330
|
id: "ssinfo-received",
|
|
5251
|
-
event: this.store.select(unrealFeature.selectSsData).pipe(filter(Boolean), take(1),
|
|
5252
|
-
client: aws.wsUrl,
|
|
5253
|
-
instanceName: aws.instanceName,
|
|
5254
|
-
...ssData,
|
|
5255
|
-
connectionId
|
|
5256
|
-
})))
|
|
5331
|
+
event: this.store.select(unrealFeature.selectSsData).pipe(filter(Boolean), take(1), map(() => this.signalingParams()))
|
|
5257
5332
|
}
|
|
5258
5333
|
]
|
|
5259
5334
|
},
|
|
@@ -5396,12 +5471,48 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5396
5471
|
handshakeFlow: null,
|
|
5397
5472
|
commandCount: 0,
|
|
5398
5473
|
times,
|
|
5399
|
-
openPhaseIdx: 0
|
|
5474
|
+
openPhaseIdx: 0,
|
|
5475
|
+
connectCorrelationId: null,
|
|
5476
|
+
orchestrationError: null,
|
|
5477
|
+
iceServers: null,
|
|
5478
|
+
cirrusClose: null,
|
|
5479
|
+
aws: null,
|
|
5480
|
+
prefetchReported: false,
|
|
5481
|
+
polls: {
|
|
5482
|
+
count: 0,
|
|
5483
|
+
errors: 0,
|
|
5484
|
+
last: null
|
|
5485
|
+
}
|
|
5400
5486
|
};
|
|
5401
5487
|
sub.add(this.store.select(selectCirrusConnectionId).pipe(filter(Boolean), take(1)).subscribe((connectionId) => this.resolveWireId(connectionId)));
|
|
5402
5488
|
sub.add(this.signallingService.onWebRtcIce$.pipe(filter(Boolean)).subscribe(() => {
|
|
5403
5489
|
if (this.session) this.session.iceCandidateCount++;
|
|
5404
5490
|
}));
|
|
5491
|
+
sub.add(this.signallingService.onRequestStreamSent$.subscribe((id) => {
|
|
5492
|
+
if (!this.session) return;
|
|
5493
|
+
this.session.connectCorrelationId = id;
|
|
5494
|
+
this.session.aws = null;
|
|
5495
|
+
}));
|
|
5496
|
+
sub.add(this.signallingService.onOrchestrationError$.subscribe((e) => {
|
|
5497
|
+
if (this.session) this.session.orchestrationError = `${e?.code}: ${e?.message ?? ""}`;
|
|
5498
|
+
}));
|
|
5499
|
+
sub.add(this.signallingService.onConfig$.pipe(take(1)).subscribe((msg) => {
|
|
5500
|
+
if (this.session) this.session.iceServers = iceServerHosts(msg?.peerConnectionOptions?.iceServers);
|
|
5501
|
+
}));
|
|
5502
|
+
sub.add(this.actions$.pipe(ofType(setAwsInstance)).subscribe(() => {
|
|
5503
|
+
if (this.session) this.session.aws = this.awsInstance$();
|
|
5504
|
+
}));
|
|
5505
|
+
sub.add(this.signallingService.onCirrusClose$.subscribe((close) => {
|
|
5506
|
+
if (this.session) this.session.cirrusClose = close;
|
|
5507
|
+
}));
|
|
5508
|
+
sub.add(this.signallingService.onPollResponse$.subscribe((poll) => {
|
|
5509
|
+
const polls = this.session?.polls;
|
|
5510
|
+
if (!polls) return;
|
|
5511
|
+
polls.count++;
|
|
5512
|
+
if (poll.status !== 200) polls.errors++;
|
|
5513
|
+
polls.last = poll;
|
|
5514
|
+
}));
|
|
5515
|
+
sub.add(this.adoption.report$.subscribe((report) => this.trackPrefetch(report)));
|
|
5405
5516
|
sub.add(this.actions$.pipe(ofType(answerSent), take(1)).subscribe(() => {
|
|
5406
5517
|
if (this.session) this.session.handshakeFlow = "server-offer";
|
|
5407
5518
|
}));
|
|
@@ -5447,7 +5558,10 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5447
5558
|
}));
|
|
5448
5559
|
});
|
|
5449
5560
|
});
|
|
5450
|
-
sub.add(this.actions$.pipe(ofType(streamAdopted)).subscribe(({ timings, region }) =>
|
|
5561
|
+
sub.add(this.actions$.pipe(ofType(streamAdopted)).subscribe(({ timings, region, correlationId }) => {
|
|
5562
|
+
if (this.session && correlationId) this.session.connectCorrelationId = correlationId;
|
|
5563
|
+
this.emitAdoptedConnection(timings, region);
|
|
5564
|
+
}));
|
|
5451
5565
|
const bootstrapInfo = this.collectBootstrapInfo();
|
|
5452
5566
|
const embedderUrl = this.collectEmbedderUrl();
|
|
5453
5567
|
this.emitLifecycle("stream.session_started", {
|
|
@@ -5475,14 +5589,19 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5475
5589
|
const errorMessage = this.errorMessage$();
|
|
5476
5590
|
const granularMessage = errorMessage?.reason === granularReason ? errorMessage.message : void 0;
|
|
5477
5591
|
const includeGranular = granularReason && granularReason !== DisconnectReason.None;
|
|
5592
|
+
const waiting = this.adoption.waitingReport();
|
|
5593
|
+
if (waiting) this.trackPrefetch(waiting);
|
|
5478
5594
|
const openPhase = this.phaseCatalog[session.openPhaseIdx];
|
|
5479
|
-
if (openPhase) this.emitPhaseEnded(openPhase, session.openPhaseIdx, null, true);
|
|
5595
|
+
if (openPhase) this.emitPhaseEnded(openPhase, session.openPhaseIdx, openPhase.id === "signaling-connection" ? this.signalingParams() : null, true);
|
|
5480
5596
|
this.flushPaks(true);
|
|
5597
|
+
const close = session.cirrusClose;
|
|
5481
5598
|
this.emitLifecycle("stream.session_ended", {
|
|
5482
5599
|
sessionId: id,
|
|
5483
5600
|
reason,
|
|
5484
5601
|
...includeGranular ? { disconnectReason: granularReason } : {},
|
|
5485
5602
|
...includeGranular && granularMessage ? { disconnectMessage: granularMessage } : {},
|
|
5603
|
+
...close && { closeCode: close.code },
|
|
5604
|
+
...close?.reason && { closeReason: close.reason },
|
|
5486
5605
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5487
5606
|
});
|
|
5488
5607
|
this.flushOutbox(session, id);
|
|
@@ -5561,7 +5680,7 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5561
5680
|
const region = parkedRegion ?? NO_REGION;
|
|
5562
5681
|
this.emitAdoptedPhase(0, startMs, 0, adoptionAtMs, regionParams(region));
|
|
5563
5682
|
this.emitAdoptedPhase(1, startMs, sigDur, adoptionAtMs, {
|
|
5564
|
-
...this.
|
|
5683
|
+
...this.signalingParams(),
|
|
5565
5684
|
...savings,
|
|
5566
5685
|
prefetchSignalingMs: sigDur
|
|
5567
5686
|
}, [{
|
|
@@ -5596,13 +5715,22 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5596
5715
|
});
|
|
5597
5716
|
this.closePhase(bucketIdx);
|
|
5598
5717
|
}
|
|
5599
|
-
|
|
5600
|
-
const
|
|
5601
|
-
const
|
|
5718
|
+
signalingParams() {
|
|
5719
|
+
const s = this.session;
|
|
5720
|
+
const aws = s?.aws ?? this.awsInstance$();
|
|
5602
5721
|
return {
|
|
5603
5722
|
client: aws?.wsUrl ?? null,
|
|
5604
5723
|
instanceName: aws?.instanceName ?? null,
|
|
5605
|
-
|
|
5724
|
+
transport: aws ? aws.kind ?? "direct" : null,
|
|
5725
|
+
orchestrationUrl: aws?.kind === "socket" ? aws.pollingUrl : null,
|
|
5726
|
+
streamRequestId: aws?.streamRequestId ?? null,
|
|
5727
|
+
connectCorrelationId: s?.connectCorrelationId ?? null,
|
|
5728
|
+
orchestrationError: s?.orchestrationError ?? null,
|
|
5729
|
+
iceServers: s?.iceServers ?? null,
|
|
5730
|
+
orchPolls: s?.polls.count || null,
|
|
5731
|
+
orchPollErrors: s?.polls.errors || null,
|
|
5732
|
+
orchLastPoll: s?.polls.last ? pollText(s.polls.last) : null,
|
|
5733
|
+
...this.ssData$() ?? {},
|
|
5606
5734
|
connectionId: this.connectionId$()
|
|
5607
5735
|
};
|
|
5608
5736
|
}
|
|
@@ -5845,6 +5973,26 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5845
5973
|
...session?.wireId ? { sessionId: session.wireId } : {}
|
|
5846
5974
|
});
|
|
5847
5975
|
}
|
|
5976
|
+
trackPrefetch(report) {
|
|
5977
|
+
const session = this.session;
|
|
5978
|
+
if (!session || session.prefetchReported) return;
|
|
5979
|
+
session.prefetchReported = true;
|
|
5980
|
+
this.track("stream.prefetch", {
|
|
5981
|
+
sessionId: session.id,
|
|
5982
|
+
outcome: report.outcome,
|
|
5983
|
+
...report.failReason && { failReason: report.failReason },
|
|
5984
|
+
...report.failError && { failError: report.failError },
|
|
5985
|
+
...report.waitMs !== null && { waitMs: report.waitMs },
|
|
5986
|
+
...report.kind && { kind: report.kind },
|
|
5987
|
+
...report.instanceName && { instanceName: report.instanceName },
|
|
5988
|
+
...report.streamRequestId && { streamRequestId: report.streamRequestId },
|
|
5989
|
+
trail: report.trail.map((entry) => ({
|
|
5990
|
+
...entry,
|
|
5991
|
+
t: Math.round(entry.t - session.anchorPerf)
|
|
5992
|
+
})),
|
|
5993
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5994
|
+
});
|
|
5995
|
+
}
|
|
5848
5996
|
emit(event, data) {
|
|
5849
5997
|
this.store.dispatch(trackTelemetryData({
|
|
5850
5998
|
event,
|
|
@@ -5915,6 +6063,26 @@ function iceParams(ice) {
|
|
|
5915
6063
|
function fmtCounts(counts) {
|
|
5916
6064
|
return Object.entries(counts).map(([k, n]) => `${k} ${n}`).join(" · ") || null;
|
|
5917
6065
|
}
|
|
6066
|
+
function pollText(poll) {
|
|
6067
|
+
return [
|
|
6068
|
+
poll.status,
|
|
6069
|
+
poll.status === 200 ? poll.ready ? "ready" : "waiting" : null,
|
|
6070
|
+
poll.percent !== null ? `${poll.percent}%` : null,
|
|
6071
|
+
poll.message,
|
|
6072
|
+
`${poll.ms}ms`
|
|
6073
|
+
].filter((part) => part !== null && part !== "").join(" ");
|
|
6074
|
+
}
|
|
6075
|
+
function iceServerHosts(servers) {
|
|
6076
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
6077
|
+
for (const server of servers ?? []) {
|
|
6078
|
+
const urls = Array.isArray(server.urls) ? server.urls : [server.urls];
|
|
6079
|
+
for (const url of urls) {
|
|
6080
|
+
const m = /^(stuns?|turns?):([^:?/]+)/i.exec(url ?? "");
|
|
6081
|
+
if (m) hosts.add(`${m[1].toLowerCase()}:${m[2].toLowerCase()}`);
|
|
6082
|
+
}
|
|
6083
|
+
}
|
|
6084
|
+
return hosts.size ? [...hosts].join(", ") : null;
|
|
6085
|
+
}
|
|
5918
6086
|
function toPhaseParams(value) {
|
|
5919
6087
|
if (!value || typeof value !== "object") return [];
|
|
5920
6088
|
const out = [];
|
|
@@ -7960,6 +8128,6 @@ function provideUnrealModule() {
|
|
|
7960
8128
|
inject(AnalyticsService);
|
|
7961
8129
|
})]);
|
|
7962
8130
|
}
|
|
7963
|
-
export { AFKService, ALL_KEYBOARD_KEYS, AUTO_HIGH_RESOLUTION_IDLE_MS, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, COLOR_CODES, ConfigHandler, ConsoleExtensionsService, ControlScheme, DATA_CHANNEL_CONNECTION_TIMEOUT, DATA_CHANNEL_TIMEOUT_RESTARTS, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DESTROY_DISCONNECT_REASONS, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, Falsy, FileHandlerService, FileReceiverService, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, HEXtoRGB, HSVtoRGB, IME_PROCESS_KEY, INNER_RETRY_LIMIT, INSTANCE_READY_TIMEOUT, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, LatencyTimings, LoadingProgressService, Logger, MINIMAL_FPS, MODIFIER_KEY_CODES, MessageType, MouseButton, MouseButtonsMask, NO_REGION, OUTER_RETRY_DELAY, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PlayerCountHandler, RECONNECT_CONFIG, REGION_PING_ACCURATE_SAMPLES, REGION_PING_BACKGROUND_REFRESH_DELAY_MS, REGION_PING_CACHE_KEY, REGION_PING_CACHE_TTL_MS, REGION_PING_PREFETCH_API_VERSION, REGION_PING_PREFETCH_GLOBAL, REGION_PING_WARMUP_DEADLINE_MS, RGBtoHEX, RGBtoHSV, RegionsPingService, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_AUDIO_ID, STREAMING_VIDEO_ID, STREAM_RESOLUTION_LIMITS, SafePipe, Semaphore, SignallingService, StatGraphComponent, StreamAdoptionService, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage, Truthy, UNREAL_CONFIG, UnrealAfkSlotDirective, UnrealCallbackService, UnrealCommunicatorService, UnrealEffects, UnrealKeyCode, UnrealResumeSlotDirective, UnrealSceneComponent, UnrealStatusMessage, UnrealStatusSlotDirective, 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, clampStreamResolution, clampf, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, dropDC, dropPC, fitIntoRectangle, floatToPercents, floatToSmoothPercents, forceResizeViewport, fpIsASameAsB, fromResizeObserver, generateUuid, getActiveUrl, getCanvasCached, getImageFromVideoStream, getResizeStudioValues, getResizeValuesUniversal, getRtcErrorMessage, getSnapshot, iceConnectionFailed, initSignalling, instanceReady, inverseLerp, isAppOwned, isMetaboxMode, keepMaxUntilReset, lerp, makeEven, pollingEnded, pollingStarted, provideUnrealModule, provideUnrealState, qpToQuality, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, regionPingFetchEnd, regionPingFetchStart, regionResolved, resetAfk, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetUserInactivityTimeout, resetWarnTimeout, resolveSkin, 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, startStream, streamAdopted, tapLog, trackMixpanelEvent, trackTelemetryData, uint8ToBase64, unrealCommandCallback, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
|
|
8131
|
+
export { AFKService, ALL_KEYBOARD_KEYS, AUTO_HIGH_RESOLUTION_IDLE_MS, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, COLOR_CODES, ConfigHandler, ConsoleExtensionsService, ControlScheme, DATA_CHANNEL_CONNECTION_TIMEOUT, DATA_CHANNEL_TIMEOUT_RESTARTS, DC_CLOSING_GRACE_MS, DC_WATCH_INTERVAL_MS, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DESTROY_DISCONNECT_REASONS, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, Falsy, FileHandlerService, FileReceiverService, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, HEXtoRGB, HSVtoRGB, IME_PROCESS_KEY, INNER_RETRY_LIMIT, INSTANCE_READY_TIMEOUT, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, LatencyTimings, LoadingProgressService, Logger, MINIMAL_FPS, MODIFIER_KEY_CODES, MessageType, MouseButton, MouseButtonsMask, NO_REGION, OUTER_RETRY_DELAY, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PlayerCountHandler, RECONNECT_CONFIG, REGION_PING_ACCURATE_SAMPLES, REGION_PING_BACKGROUND_REFRESH_DELAY_MS, REGION_PING_CACHE_KEY, REGION_PING_CACHE_TTL_MS, REGION_PING_PREFETCH_API_VERSION, REGION_PING_PREFETCH_GLOBAL, REGION_PING_WARMUP_DEADLINE_MS, RGBtoHEX, RGBtoHSV, RegionsPingService, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_AUDIO_ID, STREAMING_VIDEO_ID, STREAM_RESOLUTION_LIMITS, SafePipe, Semaphore, SignallingService, StatGraphComponent, StreamAdoptionService, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage, Truthy, UNREAL_CONFIG, UnrealAfkSlotDirective, UnrealCallbackService, UnrealCommunicatorService, UnrealEffects, UnrealKeyCode, UnrealResumeSlotDirective, UnrealSceneComponent, UnrealStatusMessage, UnrealStatusSlotDirective, 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, clampStreamResolution, clampf, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, dropDC, dropPC, fitIntoRectangle, floatToPercents, floatToSmoothPercents, forceResizeViewport, fpIsASameAsB, fromResizeObserver, generateUuid, getActiveUrl, getCanvasCached, getImageFromVideoStream, getResizeStudioValues, getResizeValuesUniversal, getRtcErrorMessage, getSnapshot, iceConnectionFailed, initSignalling, instanceReady, inverseLerp, isAppOwned, isMetaboxMode, keepMaxUntilReset, lerp, makeEven, pollingEnded, pollingStarted, provideUnrealModule, provideUnrealState, qpToQuality, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, regionPingFetchEnd, regionPingFetchStart, regionResolved, resetAfk, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetUserInactivityTimeout, resetWarnTimeout, resolveSkin, 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, startStream, streamAdopted, tapLog, trackMixpanelEvent, trackTelemetryData, uint8ToBase64, unrealCommandCallback, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
|
|
7964
8132
|
|
|
7965
8133
|
//# sourceMappingURL=3dsource-angular-unreal-module.mjs.map
|