@3dsource/angular-unreal-module 0.0.192 → 0.0.193
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 +0 -0
- package/README.md +0 -1
- package/fesm2022/3dsource-angular-unreal-module.mjs +260 -288
- package/fesm2022/3dsource-angular-unreal-module.mjs.map +1 -1
- package/package.json +1 -1
- package/types/3dsource-angular-unreal-module-config.d.ts +0 -1
- package/types/3dsource-angular-unreal-module.d.ts +81 -99
|
@@ -1356,6 +1356,13 @@ const tapLog = (text, ...args) => (source) => source.pipe(tap$1((data) => {
|
|
|
1356
1356
|
function isMetaboxMode(config) {
|
|
1357
1357
|
return (config?.mode ?? "metabox") === "metabox";
|
|
1358
1358
|
}
|
|
1359
|
+
function callbackCorrelationId(json) {
|
|
1360
|
+
return "commandCallback" in json ? json.commandCallback?.correlationId : json?.correlationId;
|
|
1361
|
+
}
|
|
1362
|
+
function callbackStamps(json) {
|
|
1363
|
+
const raw = json;
|
|
1364
|
+
return raw.timestamp ?? raw.timeStamp;
|
|
1365
|
+
}
|
|
1359
1366
|
const selectCommandProgress = createSelector(unrealFeature.selectTotalCommandsStarted, unrealFeature.selectTotalCommandsCompleted, (started, completed) => started ? completed / started : 0);
|
|
1360
1367
|
const selectFreezeFrameDataUrlFromVideo = createSelector(unrealFeature.selectFreezeFrameFromVideo, (freezeFrameFromVideo) => freezeFrameFromVideo?.dataUrl || null);
|
|
1361
1368
|
const selectFreezeFrameProgressMessageFromVideo = createSelector(unrealFeature.selectFreezeFrameFromVideo, (freezeFrameFromVideo) => freezeFrameFromVideo?.progress || null);
|
|
@@ -1472,205 +1479,6 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
1472
1479
|
}]
|
|
1473
1480
|
}]
|
|
1474
1481
|
});
|
|
1475
|
-
var SubService = class {
|
|
1476
|
-
constructor() {
|
|
1477
|
-
this.destroyRef = inject(DestroyRef);
|
|
1478
|
-
this.destroy$ = new Subject();
|
|
1479
|
-
this.actions$ = inject(Actions);
|
|
1480
|
-
this.store = inject(Store);
|
|
1481
|
-
this.disconnect$ = this.store.select(unrealFeature.selectCirrusConnected).pipe(skip(1), filter$1(Falsy), share());
|
|
1482
|
-
this.destroyRef.onDestroy(() => {
|
|
1483
|
-
this.destroy$.next();
|
|
1484
|
-
this.destroy$.complete();
|
|
1485
|
-
});
|
|
1486
|
-
}
|
|
1487
|
-
};
|
|
1488
|
-
var CommandTelemetryService = class CommandTelemetryService extends SubService {
|
|
1489
|
-
constructor() {
|
|
1490
|
-
super();
|
|
1491
|
-
this.appId = "metabox-telemetry";
|
|
1492
|
-
this.commandsSent = {};
|
|
1493
|
-
this.exileTimeout = 6e4;
|
|
1494
|
-
this.pollingTime = 5e3;
|
|
1495
|
-
this.commandSequenceNumber = 0;
|
|
1496
|
-
this.payloads = [];
|
|
1497
|
-
this.httpClient = inject(HttpClient);
|
|
1498
|
-
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
1499
|
-
this.init();
|
|
1500
|
-
}
|
|
1501
|
-
init() {
|
|
1502
|
-
if (!this.unrealConfig?.commandTelemetryReceiver || this.unrealConfig?.playwright) return;
|
|
1503
|
-
this.reset();
|
|
1504
|
-
this.sessionId = sessionStorage.getItem(this.appId) || this.uuid;
|
|
1505
|
-
this.userId = localStorage.getItem(this.appId) || this.uuid;
|
|
1506
|
-
sessionStorage.setItem(this.appId, this.sessionId);
|
|
1507
|
-
localStorage.setItem(this.appId, this.userId);
|
|
1508
|
-
timer(0, this.pollingTime).pipe(takeUntil$1(this.destroy$)).subscribe(() => {
|
|
1509
|
-
this.send(this.payloads);
|
|
1510
|
-
});
|
|
1511
|
-
}
|
|
1512
|
-
get timeNow() {
|
|
1513
|
-
return Date.now();
|
|
1514
|
-
}
|
|
1515
|
-
get sessionTime() {
|
|
1516
|
-
return this.timeNow - this.startTime;
|
|
1517
|
-
}
|
|
1518
|
-
get canSkipSending() {
|
|
1519
|
-
return !(this.timeNow - this.lastTime > this.pollingTime * 2);
|
|
1520
|
-
}
|
|
1521
|
-
decorate(funcToDecorate) {
|
|
1522
|
-
this.listenCallbacks();
|
|
1523
|
-
return this.wrapper.bind(this, funcToDecorate);
|
|
1524
|
-
}
|
|
1525
|
-
trackStartCommand(trackingId) {
|
|
1526
|
-
const out = {
|
|
1527
|
-
command: trackingId,
|
|
1528
|
-
trackingId
|
|
1529
|
-
};
|
|
1530
|
-
const timers = { sessionElapsedTime: this.sessionTime };
|
|
1531
|
-
this.pushStatToBuffer("commandSent", out, timers);
|
|
1532
|
-
this.trackTime(out);
|
|
1533
|
-
}
|
|
1534
|
-
trackStopCommand(trackingId, multi = false, response = {}, timeStampsRaw) {
|
|
1535
|
-
const commandResponse = this.commandsSent[trackingId];
|
|
1536
|
-
if (!commandResponse) return;
|
|
1537
|
-
const totalRoundTripTime = this.timeNow - commandResponse.timeStampJs;
|
|
1538
|
-
const commandSentJsTime = commandResponse.timeStampJs - this.startTime;
|
|
1539
|
-
let unrealTimers = {};
|
|
1540
|
-
const t = timeStampsRaw?.timeStampCommand;
|
|
1541
|
-
if (t) unrealTimers = {
|
|
1542
|
-
unrealRoundTripTime: t.onCompleteCommand.timestamp - t.onRequestCommand.timestamp,
|
|
1543
|
-
unrealExecutionDuration: t.onCompleteCommand.timestamp - t.onStartCommand.timestamp,
|
|
1544
|
-
timeDiffRequest: t.onRequestCommand.timestamp - commandResponse.timeStampJs,
|
|
1545
|
-
timeDiffCallBack: this.timeNow - t.onCompleteCommand.timestamp
|
|
1546
|
-
};
|
|
1547
|
-
const timers = {
|
|
1548
|
-
sessionElapsedTime: this.sessionTime,
|
|
1549
|
-
commandSentJsTime,
|
|
1550
|
-
totalRoundTripTime,
|
|
1551
|
-
...unrealTimers
|
|
1552
|
-
};
|
|
1553
|
-
this.pushStatToBuffer("commandStop", {
|
|
1554
|
-
...commandResponse.command,
|
|
1555
|
-
response
|
|
1556
|
-
}, timers, timeStampsRaw);
|
|
1557
|
-
if (!multi) delete this.commandsSent[trackingId];
|
|
1558
|
-
}
|
|
1559
|
-
reset() {
|
|
1560
|
-
this.uuid = generateUuid();
|
|
1561
|
-
this.commandSequenceNumber = 0;
|
|
1562
|
-
this.viewId = this.uuid;
|
|
1563
|
-
this.startTime = this.timeNow;
|
|
1564
|
-
this.payloads.length = 0;
|
|
1565
|
-
this.commandsSent = {};
|
|
1566
|
-
}
|
|
1567
|
-
pushStatToBuffer(type, commandContent, computedTimers, timeStampsRaw) {
|
|
1568
|
-
this.pushData({
|
|
1569
|
-
type,
|
|
1570
|
-
commandSequenceNumber: this.commandSequenceNumber++,
|
|
1571
|
-
commandContent,
|
|
1572
|
-
timeStampsRaw,
|
|
1573
|
-
computedTimers
|
|
1574
|
-
});
|
|
1575
|
-
}
|
|
1576
|
-
trackTime(command) {
|
|
1577
|
-
this.commandsSent[command.trackingId] = {
|
|
1578
|
-
timeStampJs: this.timeNow,
|
|
1579
|
-
command
|
|
1580
|
-
};
|
|
1581
|
-
}
|
|
1582
|
-
send(payload) {
|
|
1583
|
-
if (payload.length === 0 || this.canSkipSending && payload.length < 10) return;
|
|
1584
|
-
this.lastTime = this.timeNow;
|
|
1585
|
-
const out = {
|
|
1586
|
-
appId: this.appId,
|
|
1587
|
-
sessionId: this.sessionId,
|
|
1588
|
-
viewId: this.viewId,
|
|
1589
|
-
userId: this.userId,
|
|
1590
|
-
ua: navigator.userAgent,
|
|
1591
|
-
timeStamp: new Date(this.timeNow).toString(),
|
|
1592
|
-
href: location.href,
|
|
1593
|
-
resolution: {
|
|
1594
|
-
width: window.screen.width,
|
|
1595
|
-
height: window.screen.height,
|
|
1596
|
-
pixelRatio: window.devicePixelRatio
|
|
1597
|
-
},
|
|
1598
|
-
payload
|
|
1599
|
-
};
|
|
1600
|
-
const lastIndex = payload[payload.length - 1].commandSequenceNumber;
|
|
1601
|
-
this.httpClient.post(this.unrealConfig?.commandTelemetryReceiver || "", out).pipe(catchError(() => of(null)), take(1)).subscribe(() => {
|
|
1602
|
-
this.payloads = this.payloads.filter((p) => p.commandSequenceNumber > lastIndex);
|
|
1603
|
-
});
|
|
1604
|
-
}
|
|
1605
|
-
listenCallbacks() {
|
|
1606
|
-
this.actions$.pipe(ofType(unrealCommandCallback), filter$1(({ json }) => {
|
|
1607
|
-
const callback = "commandCallback" in json ? json.commandCallback : json;
|
|
1608
|
-
return Truthy(callback?.trackingId);
|
|
1609
|
-
}), takeUntil$1(this.destroy$)).subscribe(({ json }) => {
|
|
1610
|
-
const callback = "commandCallback" in json ? json.commandCallback : json;
|
|
1611
|
-
const timeStampsRaw = "timeStamp" in json ? json?.timeStamp : void 0;
|
|
1612
|
-
const trackingId = callback?.trackingId || "";
|
|
1613
|
-
this.trackStopCommand(trackingId, false, {}, timeStampsRaw);
|
|
1614
|
-
this.removeExileCommands();
|
|
1615
|
-
});
|
|
1616
|
-
}
|
|
1617
|
-
pushData(payload) {
|
|
1618
|
-
this.payloads.push(payload);
|
|
1619
|
-
}
|
|
1620
|
-
removeExileCommands() {
|
|
1621
|
-
const time = (/* @__PURE__ */ new Date()).getTime();
|
|
1622
|
-
const markForDelete = [];
|
|
1623
|
-
Object.entries(this.commandsSent).forEach(([trackingId, { timeStampJs }]) => {
|
|
1624
|
-
if (time - timeStampJs > this.exileTimeout) markForDelete.push(trackingId);
|
|
1625
|
-
});
|
|
1626
|
-
markForDelete.forEach((trackingId) => {
|
|
1627
|
-
delete this.commandsSent[trackingId];
|
|
1628
|
-
});
|
|
1629
|
-
}
|
|
1630
|
-
wrapper(funcToDecorate, data) {
|
|
1631
|
-
const out = {
|
|
1632
|
-
...data,
|
|
1633
|
-
trackingId: generateUuid()
|
|
1634
|
-
};
|
|
1635
|
-
const timers = { sessionElapsedTime: this.sessionTime };
|
|
1636
|
-
this.pushStatToBuffer("commandSent", {
|
|
1637
|
-
...out,
|
|
1638
|
-
trackingId: `${out.trackingId}`
|
|
1639
|
-
}, timers);
|
|
1640
|
-
this.trackTime(out);
|
|
1641
|
-
funcToDecorate(out);
|
|
1642
|
-
}
|
|
1643
|
-
static {
|
|
1644
|
-
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
1645
|
-
minVersion: "12.0.0",
|
|
1646
|
-
version: "22.2.0",
|
|
1647
|
-
ngImport: i0,
|
|
1648
|
-
type: CommandTelemetryService,
|
|
1649
|
-
deps: [],
|
|
1650
|
-
target: i0.ɵɵFactoryTarget.Injectable
|
|
1651
|
-
});
|
|
1652
|
-
}
|
|
1653
|
-
static {
|
|
1654
|
-
this.ɵprov = i0.ɵɵngDeclareInjectable({
|
|
1655
|
-
minVersion: "12.0.0",
|
|
1656
|
-
version: "22.2.0",
|
|
1657
|
-
ngImport: i0,
|
|
1658
|
-
type: CommandTelemetryService,
|
|
1659
|
-
providedIn: "root"
|
|
1660
|
-
});
|
|
1661
|
-
}
|
|
1662
|
-
};
|
|
1663
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1664
|
-
minVersion: "12.0.0",
|
|
1665
|
-
version: "22.2.0",
|
|
1666
|
-
ngImport: i0,
|
|
1667
|
-
type: CommandTelemetryService,
|
|
1668
|
-
decorators: [{
|
|
1669
|
-
type: Injectable,
|
|
1670
|
-
args: [{ providedIn: "root" }]
|
|
1671
|
-
}],
|
|
1672
|
-
ctorParameters: () => []
|
|
1673
|
-
});
|
|
1674
1482
|
var DevModeService = class DevModeService {
|
|
1675
1483
|
get isDevMode() {
|
|
1676
1484
|
return Truthy(localStorage.getItem("devMode"));
|
|
@@ -1907,6 +1715,19 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
1907
1715
|
}],
|
|
1908
1716
|
ctorParameters: () => []
|
|
1909
1717
|
});
|
|
1718
|
+
var SubService = class {
|
|
1719
|
+
constructor() {
|
|
1720
|
+
this.destroyRef = inject(DestroyRef);
|
|
1721
|
+
this.destroy$ = new Subject();
|
|
1722
|
+
this.actions$ = inject(Actions);
|
|
1723
|
+
this.store = inject(Store);
|
|
1724
|
+
this.disconnect$ = this.store.select(unrealFeature.selectCirrusConnected).pipe(skip(1), filter$1(Falsy), share());
|
|
1725
|
+
this.destroyRef.onDestroy(() => {
|
|
1726
|
+
this.destroy$.next();
|
|
1727
|
+
this.destroy$.complete();
|
|
1728
|
+
});
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1910
1731
|
function StreamerListHandler(msg) {
|
|
1911
1732
|
this.send(JSON.stringify({
|
|
1912
1733
|
type: "subscribe",
|
|
@@ -2000,7 +1821,6 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
2000
1821
|
super();
|
|
2001
1822
|
this.httpClient = inject(HttpClient);
|
|
2002
1823
|
this.regionsPingService = inject(RegionsPingService);
|
|
2003
|
-
this.commandTelemetryService = inject(CommandTelemetryService);
|
|
2004
1824
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
2005
1825
|
this.region = signal("", ...ngDevMode ? [{ debugName: "region" }] : /* istanbul ignore next */ []);
|
|
2006
1826
|
this.selectClientAndViewIds = this.store.selectSignal(selectClientAndViewIds);
|
|
@@ -2045,7 +1865,6 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
2045
1865
|
Logger.log("CONNECT TO SIGNALLING");
|
|
2046
1866
|
return defer(() => {
|
|
2047
1867
|
this.correlationId = generateUuid();
|
|
2048
|
-
this.commandTelemetryService.reset();
|
|
2049
1868
|
this.startEstablishingConnection();
|
|
2050
1869
|
return this.getRegion().pipe(tap$1((region) => this.region.set(region ?? "")), map$1((region) => this.adaptUrlsToRegion(urlList, region)), switchMap((urls) => this.connectAttempt(urls)), takeUntil$1(this.abort$)).pipe(retry({ delay: (err, attempt) => {
|
|
2051
1870
|
this.store.dispatch(signalingRetryAttempted({
|
|
@@ -2053,7 +1872,7 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
2053
1872
|
reason: err?.message ?? "unknown",
|
|
2054
1873
|
kind: "region-cycle"
|
|
2055
1874
|
}));
|
|
2056
|
-
Logger.info(`Outer retry (region re-
|
|
1875
|
+
Logger.info(`Outer retry (region re-resolve) in ${OUTER_RETRY_DELAY}ms. Attempt# ${attempt}.`, err?.message);
|
|
2057
1876
|
return timer(OUTER_RETRY_DELAY);
|
|
2058
1877
|
} }));
|
|
2059
1878
|
}).pipe(takeUntil$1(this.abort$));
|
|
@@ -2117,39 +1936,22 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
2117
1936
|
}
|
|
2118
1937
|
requestCirrusViaPolling(url) {
|
|
2119
1938
|
return defer(() => {
|
|
2120
|
-
let lastResp;
|
|
2121
1939
|
this.store.dispatch(pollingStarted());
|
|
2122
|
-
this.commandTelemetryService.trackStartCommand("EXT-getSignaling");
|
|
2123
1940
|
return this.store.select(selectClientAndViewIds).pipe(tap$1(({ clientId, viewId }) => {
|
|
2124
1941
|
if (!clientId || !viewId) Logger.error("Client ID or View ID is not set");
|
|
2125
|
-
}), filter$1(({ clientId, viewId }) => !!clientId && !!viewId), take(1), switchMap(({ clientId, viewId }) => this.pollLoop(`${url}${clientId}/${viewId}`)
|
|
2126
|
-
lastResp = data;
|
|
2127
|
-
}))), map$1((data) => ({
|
|
1942
|
+
}), filter$1(({ clientId, viewId }) => !!clientId && !!viewId), take(1), switchMap(({ clientId, viewId }) => this.pollLoop(`${url}${clientId}/${viewId}`)), map$1((data) => ({
|
|
2128
1943
|
wsUrl: httpUrlToWs(`${location.protocol}//${data.signallingServer}`),
|
|
2129
1944
|
pollingUrl: url,
|
|
2130
1945
|
instanceName: data.signallingServer ?? "",
|
|
2131
1946
|
streamRequestId: data.streamRequestId,
|
|
2132
1947
|
kind: "polling"
|
|
2133
|
-
})), finalize(() =>
|
|
2134
|
-
this.commandTelemetryService.trackStopCommand("EXT-getSignaling", true, {
|
|
2135
|
-
...lastResp ?? {},
|
|
2136
|
-
multi: true
|
|
2137
|
-
});
|
|
2138
|
-
this.store.dispatch(pollingEnded());
|
|
2139
|
-
}));
|
|
1948
|
+
})), finalize(() => this.store.dispatch(pollingEnded())));
|
|
2140
1949
|
});
|
|
2141
1950
|
}
|
|
2142
1951
|
requestCirrusViaSocket(url) {
|
|
2143
1952
|
return defer(() => {
|
|
2144
|
-
let resolved;
|
|
2145
1953
|
this.orchestrationRetryCount = 0;
|
|
2146
|
-
this.
|
|
2147
|
-
return this.waitForClientAndViewIds().pipe(switchMap(() => createWebSocket(url)), switchMap((control) => this.awaitInstanceReady(control, url)), tap$1((instance) => {
|
|
2148
|
-
resolved = instance;
|
|
2149
|
-
}), finalize(() => this.commandTelemetryService.trackStopCommand("EXT-getSignaling", true, {
|
|
2150
|
-
...resolved ?? {},
|
|
2151
|
-
multi: true
|
|
2152
|
-
})));
|
|
1954
|
+
return this.waitForClientAndViewIds().pipe(switchMap(() => createWebSocket(url)), switchMap((control) => this.awaitInstanceReady(control, url)));
|
|
2153
1955
|
});
|
|
2154
1956
|
}
|
|
2155
1957
|
awaitInstanceReady(control, orchestrationUrl) {
|
|
@@ -2197,10 +1999,7 @@ var SignallingService = class SignallingService extends SubService {
|
|
|
2197
1999
|
reason: DisconnectReason.NewConnectionAttempt
|
|
2198
2000
|
});
|
|
2199
2001
|
return createWebSocket(wsUrl);
|
|
2200
|
-
}).pipe(takeUntil$1(this.abort$), tapLog("WS CREATED"), tap$1((ws) =>
|
|
2201
|
-
this.commandTelemetryService.trackStartCommand("EXT-iceCandidate");
|
|
2202
|
-
this.addWsHandlers(ws);
|
|
2203
|
-
}));
|
|
2002
|
+
}).pipe(takeUntil$1(this.abort$), tapLog("WS CREATED"), tap$1((ws) => this.addWsHandlers(ws)));
|
|
2204
2003
|
}
|
|
2205
2004
|
addWsHandlers(ws) {
|
|
2206
2005
|
ws.onmessage = OnMessageHandler.bind(this);
|
|
@@ -2362,6 +2161,58 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2362
2161
|
}],
|
|
2363
2162
|
ctorParameters: () => []
|
|
2364
2163
|
});
|
|
2164
|
+
function finite(value) {
|
|
2165
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2166
|
+
}
|
|
2167
|
+
function candidateInfo(candidate, isLocal) {
|
|
2168
|
+
if (!candidate) return {};
|
|
2169
|
+
const isRelay = candidate.candidateType === "relay";
|
|
2170
|
+
return {
|
|
2171
|
+
type: candidate.candidateType,
|
|
2172
|
+
protocol: candidate.protocol,
|
|
2173
|
+
...isRelay ? {
|
|
2174
|
+
address: candidate.address ?? void 0,
|
|
2175
|
+
port: finite(candidate.port)
|
|
2176
|
+
} : {},
|
|
2177
|
+
...isLocal ? {
|
|
2178
|
+
url: candidate.url,
|
|
2179
|
+
relayProtocol: candidate.relayProtocol
|
|
2180
|
+
} : {}
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
function selectedPairId(stats) {
|
|
2184
|
+
let fromTransport;
|
|
2185
|
+
let flagged;
|
|
2186
|
+
stats.forEach((r) => {
|
|
2187
|
+
if (r.type === "transport" && r.selectedCandidatePairId) fromTransport = r.selectedCandidatePairId;
|
|
2188
|
+
if (r.type === "candidate-pair" && r.selected === true) flagged = r.id;
|
|
2189
|
+
});
|
|
2190
|
+
return fromTransport ?? flagged;
|
|
2191
|
+
}
|
|
2192
|
+
function iceSnapshot(stats) {
|
|
2193
|
+
const count = (type, key) => {
|
|
2194
|
+
const out = {};
|
|
2195
|
+
stats.forEach((r) => {
|
|
2196
|
+
if (r.type !== type) return;
|
|
2197
|
+
const k = r[key] || "unknown";
|
|
2198
|
+
out[k] = (out[k] ?? 0) + 1;
|
|
2199
|
+
});
|
|
2200
|
+
return out;
|
|
2201
|
+
};
|
|
2202
|
+
const pairId = selectedPairId(stats);
|
|
2203
|
+
const pair = pairId ? stats.get(pairId) : void 0;
|
|
2204
|
+
const rtt = finite(pair?.currentRoundTripTime);
|
|
2205
|
+
return {
|
|
2206
|
+
local: count("local-candidate", "candidateType"),
|
|
2207
|
+
remote: count("remote-candidate", "candidateType"),
|
|
2208
|
+
pairs: count("candidate-pair", "state"),
|
|
2209
|
+
selected: pair ? {
|
|
2210
|
+
local: candidateInfo(stats.get(pair.localCandidateId), true),
|
|
2211
|
+
remote: candidateInfo(stats.get(pair.remoteCandidateId), false)
|
|
2212
|
+
} : null,
|
|
2213
|
+
...rtt !== void 0 && { selectedRttMs: Math.round(rtt * 1e3) }
|
|
2214
|
+
};
|
|
2215
|
+
}
|
|
2365
2216
|
var VideoService = class VideoService extends SubService {
|
|
2366
2217
|
constructor() {
|
|
2367
2218
|
super();
|
|
@@ -2486,21 +2337,17 @@ var VideoService = class VideoService extends SubService {
|
|
|
2486
2337
|
}
|
|
2487
2338
|
generateAggregatedStatsFunction(stats, pcEpoch = 0) {
|
|
2488
2339
|
const newStat = {};
|
|
2489
|
-
let selectedPairId;
|
|
2490
|
-
let flaggedPairId;
|
|
2491
2340
|
newStat.codecs = {};
|
|
2492
2341
|
newStat.currentRoundTripTime = -1;
|
|
2493
2342
|
stats.forEach((report) => {
|
|
2494
2343
|
if (report.type === "inbound-rtp" && report.kind === "video") this.applyInboundVideoReport(newStat, report);
|
|
2495
2344
|
if (report.type === "candidate-pair" && report.nominated === true && Object.hasOwn(report, "currentRoundTripTime")) newStat.currentRoundTripTime = report.currentRoundTripTime ?? 0;
|
|
2496
|
-
if (report.type === "transport" && report.selectedCandidatePairId) selectedPairId = report.selectedCandidatePairId;
|
|
2497
|
-
if (report.type === "candidate-pair" && report.selected === true) flaggedPairId = report.id;
|
|
2498
2345
|
if (Object.hasOwn(newStat, "codecs") && report.type === "codec" && report.mimeType && report.id) {
|
|
2499
2346
|
const codecId = report.id;
|
|
2500
2347
|
newStat.codecs[codecId] = report.mimeType.replace("video/", "").replace("audio/", "");
|
|
2501
2348
|
}
|
|
2502
2349
|
});
|
|
2503
|
-
this.applySelectedPair(newStat, stats, selectedPairId
|
|
2350
|
+
this.applySelectedPair(newStat, stats, selectedPairId(stats), pcEpoch);
|
|
2504
2351
|
this.applySessionTotals(newStat);
|
|
2505
2352
|
this.aggregatedStats = newStat;
|
|
2506
2353
|
return this.onAggregatedStats(newStat);
|
|
@@ -2638,25 +2485,6 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2638
2485
|
function pinBaseline(pinned, current) {
|
|
2639
2486
|
return pinned || current;
|
|
2640
2487
|
}
|
|
2641
|
-
function finite(value) {
|
|
2642
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2643
|
-
}
|
|
2644
|
-
function candidateInfo(candidate, isLocal) {
|
|
2645
|
-
if (!candidate) return {};
|
|
2646
|
-
const isRelay = candidate.candidateType === "relay";
|
|
2647
|
-
return {
|
|
2648
|
-
type: candidate.candidateType,
|
|
2649
|
-
protocol: candidate.protocol,
|
|
2650
|
-
...isRelay ? {
|
|
2651
|
-
address: candidate.address ?? void 0,
|
|
2652
|
-
port: finite(candidate.port)
|
|
2653
|
-
} : {},
|
|
2654
|
-
...isLocal ? {
|
|
2655
|
-
url: candidate.url,
|
|
2656
|
-
relayProtocol: candidate.relayProtocol
|
|
2657
|
-
} : {}
|
|
2658
|
-
};
|
|
2659
|
-
}
|
|
2660
2488
|
function isAutoplayBlocked(error) {
|
|
2661
2489
|
return !!error && typeof error === "object" && "name" in error && error.name === "NotAllowedError";
|
|
2662
2490
|
}
|
|
@@ -2664,11 +2492,11 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2664
2492
|
constructor() {
|
|
2665
2493
|
super();
|
|
2666
2494
|
this.onDataChannelMessage$ = new Subject();
|
|
2495
|
+
this.iceState$ = new Subject();
|
|
2667
2496
|
this.pcClient = null;
|
|
2668
2497
|
this.dcClient = null;
|
|
2669
2498
|
this.signallingSrv = inject(SignallingService);
|
|
2670
2499
|
this.videoService = inject(VideoService);
|
|
2671
|
-
this.commandTelemetryService = inject(CommandTelemetryService);
|
|
2672
2500
|
this.cfg = {};
|
|
2673
2501
|
this.useMic = false;
|
|
2674
2502
|
this.forceTURN = false;
|
|
@@ -2693,7 +2521,6 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2693
2521
|
this.handleServerAnswer(answer);
|
|
2694
2522
|
});
|
|
2695
2523
|
this.signallingSrv.onWebRtcIce$.pipe(takeUntil$1(this.destroy$)).subscribe((candidate) => {
|
|
2696
|
-
this.commandTelemetryService.trackStopCommand("EXT-iceCandidate", true, { multi: true });
|
|
2697
2524
|
if (this.remoteDescriptionSet) this.handleCandidateFromServer(candidate);
|
|
2698
2525
|
else this.iceCandidateBuffer.push(candidate);
|
|
2699
2526
|
});
|
|
@@ -2755,9 +2582,6 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2755
2582
|
this.closePC();
|
|
2756
2583
|
Logger.log("Creating new RTCPeerConnection with config");
|
|
2757
2584
|
this.pcClient = new RTCPeerConnection(config);
|
|
2758
|
-
this.commandTelemetryService.trackStartCommand("EXT-Browser ICE gathering");
|
|
2759
|
-
this.commandTelemetryService.trackStartCommand("EXT-Browser ICE connection");
|
|
2760
|
-
this.commandTelemetryService.trackStartCommand("EXT-Signaling state change");
|
|
2761
2585
|
this.handlePeerConnectionEvents(this.pcClient);
|
|
2762
2586
|
this.disconnect$.pipe(take(1), takeUntil$1(this.destroy$)).subscribe(() => {
|
|
2763
2587
|
this.closePC();
|
|
@@ -2831,6 +2655,15 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2831
2655
|
canSend() {
|
|
2832
2656
|
return this.dcClient && this.dcClient.readyState === "open";
|
|
2833
2657
|
}
|
|
2658
|
+
async readIceSnapshot() {
|
|
2659
|
+
const pc = this.pcClient;
|
|
2660
|
+
if (!pc || pc.connectionState === "closed") return null;
|
|
2661
|
+
try {
|
|
2662
|
+
return iceSnapshot(await pc.getStats(null));
|
|
2663
|
+
} catch {
|
|
2664
|
+
return null;
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2834
2667
|
describeConnectionState() {
|
|
2835
2668
|
const pc = this.pcClient;
|
|
2836
2669
|
return pc ? `signaling=${pc.signalingState}, ice=${pc.iceConnectionState}, connection=${pc.connectionState}` : "no peer connection";
|
|
@@ -2890,7 +2723,6 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2890
2723
|
dc.onclose = null;
|
|
2891
2724
|
this.dcClient = this.setupDataChannelCallbacks(dc);
|
|
2892
2725
|
for (const buffered of dcBuffer) this.onDataChannelMessage$.next(buffered);
|
|
2893
|
-
this.commandTelemetryService.trackStopCommand("EXT-DataChannel Connection");
|
|
2894
2726
|
this.onDataChannelConnected();
|
|
2895
2727
|
this.videoService.create();
|
|
2896
2728
|
this.videoService.attachVideoStream(stream, pc);
|
|
@@ -2917,23 +2749,19 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2917
2749
|
handlePeerConnectionEvents(pcClient) {
|
|
2918
2750
|
fromEvent(pcClient, "signalingstatechange").pipe(map$1(() => this.pcClient?.signalingState), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe((state) => {
|
|
2919
2751
|
Logger.info("[Signaling state change] |", state, "|");
|
|
2920
|
-
this.commandTelemetryService.trackStopCommand("EXT-Signaling state change", true, {
|
|
2921
|
-
state,
|
|
2922
|
-
multi: true
|
|
2923
|
-
});
|
|
2924
2752
|
});
|
|
2925
2753
|
fromEvent(pcClient, "iceconnectionstatechange").pipe(map$1(() => this.pcClient?.iceConnectionState), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe((state) => {
|
|
2926
2754
|
Logger.info("[Browser ICE connection] |", state, "|");
|
|
2927
|
-
this.
|
|
2928
|
-
|
|
2929
|
-
|
|
2755
|
+
if (state) this.iceState$.next({
|
|
2756
|
+
kind: "connection",
|
|
2757
|
+
state
|
|
2930
2758
|
});
|
|
2931
2759
|
});
|
|
2932
2760
|
fromEvent(pcClient, "icegatheringstatechange").pipe(map$1(() => this.pcClient?.iceGatheringState), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe((state) => {
|
|
2933
2761
|
Logger.info("[Browser ICE gathering] |", state, "|");
|
|
2934
|
-
this.
|
|
2935
|
-
|
|
2936
|
-
|
|
2762
|
+
if (state) this.iceState$.next({
|
|
2763
|
+
kind: "gathering",
|
|
2764
|
+
state
|
|
2937
2765
|
});
|
|
2938
2766
|
});
|
|
2939
2767
|
fromEvent(pcClient, "connectionstatechange").pipe(map$1(() => this.pcClient?.connectionState), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe((state) => {
|
|
@@ -2993,7 +2821,6 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
2993
2821
|
setupDataChannelCallbacks(datachannel) {
|
|
2994
2822
|
try {
|
|
2995
2823
|
Logger.log(`[DATACHANNEL] Setting up datachannel "${datachannel.label}" callbacks...`);
|
|
2996
|
-
this.commandTelemetryService.trackStartCommand("EXT-DataChannel Connection");
|
|
2997
2824
|
datachannel.binaryType = "arraybuffer";
|
|
2998
2825
|
fromEvent(datachannel, "close").pipe(filter$1(() => !this.isReconnecting()), take(1), takeUntil$1(this.destroy$)).subscribe((e) => {
|
|
2999
2826
|
Logger.warn(`[DATACHANNEL] Data channel disconnected: ${datachannel.label}(${datachannel.id})`, e);
|
|
@@ -3008,10 +2835,7 @@ var WebRtcPlayerService = class WebRtcPlayerService extends SubService {
|
|
|
3008
2835
|
});
|
|
3009
2836
|
fromEvent(datachannel, "open").pipe(tap(() => {
|
|
3010
2837
|
Logger.info(`[DATACHANNEL] Data channel "${datachannel.label}" connected. id:${datachannel.id}`);
|
|
3011
|
-
}), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe(() =>
|
|
3012
|
-
this.commandTelemetryService.trackStopCommand("EXT-DataChannel Connection");
|
|
3013
|
-
this.onDataChannelConnected();
|
|
3014
|
-
});
|
|
2838
|
+
}), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe(() => this.onDataChannelConnected());
|
|
3015
2839
|
fromEvent(datachannel, "message").pipe(map$1((e) => e.data), takeUntil$1(merge(this.disconnect$, this.destroy$))).subscribe((data) => this.onDataChannelMessage$.next(data));
|
|
3016
2840
|
return datachannel;
|
|
3017
2841
|
} catch (e) {
|
|
@@ -3244,10 +3068,24 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
3244
3068
|
args: [{ providedIn: "root" }]
|
|
3245
3069
|
}]
|
|
3246
3070
|
});
|
|
3071
|
+
function collectPakPaths(payload) {
|
|
3072
|
+
const found = /* @__PURE__ */ new Set();
|
|
3073
|
+
const walk = (value) => {
|
|
3074
|
+
if (Array.isArray(value)) {
|
|
3075
|
+
value.forEach(walk);
|
|
3076
|
+
return;
|
|
3077
|
+
}
|
|
3078
|
+
if (!value || typeof value !== "object") return;
|
|
3079
|
+
for (const [key, v] of Object.entries(value)) if (key === "pakFilePath") {
|
|
3080
|
+
if (typeof v === "string" && v) found.add(v);
|
|
3081
|
+
} else walk(v);
|
|
3082
|
+
};
|
|
3083
|
+
walk(payload);
|
|
3084
|
+
return found.size ? [...found].join(", ") : void 0;
|
|
3085
|
+
}
|
|
3247
3086
|
var UnrealCommunicatorService = class UnrealCommunicatorService extends SubService {
|
|
3248
3087
|
constructor() {
|
|
3249
3088
|
super();
|
|
3250
|
-
this.commandTelemetryService = inject(CommandTelemetryService);
|
|
3251
3089
|
this.webRtcPlayerService = inject(WebRtcPlayerService);
|
|
3252
3090
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
3253
3091
|
this.cirrusConnected = this.store.selectSignal(unrealFeature.selectCirrusConnected);
|
|
@@ -3259,7 +3097,6 @@ var UnrealCommunicatorService = class UnrealCommunicatorService extends SubServi
|
|
|
3259
3097
|
}
|
|
3260
3098
|
init() {
|
|
3261
3099
|
if (this.isPlaywrightMode()) return;
|
|
3262
|
-
this.emitUIInteraction = this.commandTelemetryService.decorate(this.emitUIInteraction.bind(this));
|
|
3263
3100
|
this.actions$.pipe(ofType(dataChannelConnected), takeUntil(this.destroy$)).subscribe(() => {
|
|
3264
3101
|
this.requestInitialSettings();
|
|
3265
3102
|
this.requestQualityControl();
|
|
@@ -3280,7 +3117,8 @@ var UnrealCommunicatorService = class UnrealCommunicatorService extends SubServi
|
|
|
3280
3117
|
this.store.dispatch(commandStarted({
|
|
3281
3118
|
id: uniqId,
|
|
3282
3119
|
command: data.command,
|
|
3283
|
-
timeStamp: Date.now()
|
|
3120
|
+
timeStamp: Date.now(),
|
|
3121
|
+
paks: collectPakPaths(data)
|
|
3284
3122
|
}));
|
|
3285
3123
|
}
|
|
3286
3124
|
}
|
|
@@ -3428,7 +3266,6 @@ var UnrealEffects = class UnrealEffects {
|
|
|
3428
3266
|
this.unrealInitialConfig = inject(UNREAL_CONFIG);
|
|
3429
3267
|
this.webRtcPlayerService = inject(WebRtcPlayerService);
|
|
3430
3268
|
this.commandsSender = inject(UnrealCommunicatorService);
|
|
3431
|
-
this.commandTelemetryService = inject(CommandTelemetryService);
|
|
3432
3269
|
this.regionsPingService = inject(RegionsPingService);
|
|
3433
3270
|
this.signallingService = inject(SignallingService);
|
|
3434
3271
|
this.streamAdoptionService = inject(StreamAdoptionService);
|
|
@@ -3532,12 +3369,11 @@ var UnrealEffects = class UnrealEffects {
|
|
|
3532
3369
|
command: MetaBoxCommand.FDebugModeCommand,
|
|
3533
3370
|
payload: { value: this.isDevMode }
|
|
3534
3371
|
});
|
|
3535
|
-
this.commandTelemetryService.trackStartCommand("EXT-SetViewportReady");
|
|
3536
3372
|
return this.actions$.pipe(ofType(commandStarted), debounceTime(50), take(1), switchMap(() => this.unrealCallbackService.observeCommandResponse({ command: MetaBoxCommand.FLoopBackCommand }, (data) => this.commandsSender.sendCommandToUnreal(data))), switchMap(() => this.videoService.videoStats$), filter$1(({ aggregatedStats: s }) => !!s.framesPerSecond && s.framesPerSecond > 6 && (s.framesDecoded ?? 0) > 15), take(1), map(() => setLoopBackCommandIsCompleted()));
|
|
3537
3373
|
}));
|
|
3538
3374
|
});
|
|
3539
3375
|
this.setViewportReadyBySetLoopBackCommandIsCompleted$ = createEffect(() => {
|
|
3540
|
-
return this.actions$.pipe(ofType(setLoopBackCommandIsCompleted, reconnectPeerSuccess),
|
|
3376
|
+
return this.actions$.pipe(ofType(setLoopBackCommandIsCompleted, reconnectPeerSuccess), map(() => setViewportReady()));
|
|
3541
3377
|
});
|
|
3542
3378
|
this.startStream$ = createEffect(() => {
|
|
3543
3379
|
return this.actions$.pipe(ofType(startStream), map(() => initSignalling()));
|
|
@@ -3614,7 +3450,7 @@ var UnrealEffects = class UnrealEffects {
|
|
|
3614
3450
|
}))));
|
|
3615
3451
|
}, { dispatch: false });
|
|
3616
3452
|
this.listenUnrealCallbackByInitSignalling$ = createEffect(() => {
|
|
3617
|
-
return this.actions$.pipe(ofType(initSignalling), filter$1(() => !this.unrealInitialConfig?.playwright), switchMap(() => this.actions$.pipe(ofType(unrealCommandCallback), map(({ json }) =>
|
|
3453
|
+
return this.actions$.pipe(ofType(initSignalling), filter$1(() => !this.unrealInitialConfig?.playwright), switchMap(() => this.actions$.pipe(ofType(unrealCommandCallback), map(({ json }) => callbackCorrelationId(json)), filter$1(Truthy), map((id) => commandCompleted({
|
|
3618
3454
|
id,
|
|
3619
3455
|
now: Date.now()
|
|
3620
3456
|
})))));
|
|
@@ -5222,6 +5058,67 @@ var RouteLog = class {
|
|
|
5222
5058
|
};
|
|
5223
5059
|
}
|
|
5224
5060
|
};
|
|
5061
|
+
var PakLog = class {
|
|
5062
|
+
constructor(anchorPerf) {
|
|
5063
|
+
this.anchorPerf = anchorPerf;
|
|
5064
|
+
this.inFlight = /* @__PURE__ */ new Map();
|
|
5065
|
+
this.done = [];
|
|
5066
|
+
}
|
|
5067
|
+
start(id, pak, command, nowPerf) {
|
|
5068
|
+
this.inFlight.set(id, {
|
|
5069
|
+
pak,
|
|
5070
|
+
command,
|
|
5071
|
+
sentPerf: nowPerf
|
|
5072
|
+
});
|
|
5073
|
+
}
|
|
5074
|
+
complete(id, nowPerf, stamps) {
|
|
5075
|
+
const sent = this.inFlight.get(id);
|
|
5076
|
+
if (!sent) return;
|
|
5077
|
+
this.inFlight.delete(id);
|
|
5078
|
+
this.done.push({
|
|
5079
|
+
...this.base(sent),
|
|
5080
|
+
totalMs: Math.round(nowPerf - sent.sentPerf),
|
|
5081
|
+
...unrealTimings(stamps)
|
|
5082
|
+
});
|
|
5083
|
+
}
|
|
5084
|
+
take(nowPerf, final = false) {
|
|
5085
|
+
for (const [id, sent] of this.inFlight) if (final || nowPerf - sent.sentPerf > 6e4) {
|
|
5086
|
+
this.inFlight.delete(id);
|
|
5087
|
+
this.done.push({
|
|
5088
|
+
...this.base(sent),
|
|
5089
|
+
lost: true
|
|
5090
|
+
});
|
|
5091
|
+
}
|
|
5092
|
+
const out = this.done;
|
|
5093
|
+
this.done = [];
|
|
5094
|
+
return out;
|
|
5095
|
+
}
|
|
5096
|
+
base({ pak, command, sentPerf }) {
|
|
5097
|
+
return {
|
|
5098
|
+
pak,
|
|
5099
|
+
command,
|
|
5100
|
+
sentMs: Math.round(sentPerf - this.anchorPerf)
|
|
5101
|
+
};
|
|
5102
|
+
}
|
|
5103
|
+
};
|
|
5104
|
+
function unrealTimings(stamps) {
|
|
5105
|
+
const cmd = field(stamps, "timeStampCommand");
|
|
5106
|
+
const at = (key) => {
|
|
5107
|
+
const t = field(field(cmd, key), "timestamp");
|
|
5108
|
+
return typeof t === "number" && Number.isFinite(t) ? t : void 0;
|
|
5109
|
+
};
|
|
5110
|
+
const span = (from, to) => from !== void 0 && to !== void 0 && to >= from ? Math.round(to - from) : void 0;
|
|
5111
|
+
const start = at("onStartCommand");
|
|
5112
|
+
const queueMs = span(at("onRequestCommand"), start);
|
|
5113
|
+
const execMs = span(start, at("onCompleteCommand"));
|
|
5114
|
+
return {
|
|
5115
|
+
...queueMs !== void 0 && { queueMs },
|
|
5116
|
+
...execMs !== void 0 && { execMs }
|
|
5117
|
+
};
|
|
5118
|
+
}
|
|
5119
|
+
function field(value, key) {
|
|
5120
|
+
return value && typeof value === "object" ? value[key] : void 0;
|
|
5121
|
+
}
|
|
5225
5122
|
function shortResourceName(url) {
|
|
5226
5123
|
try {
|
|
5227
5124
|
return new URL(url).pathname;
|
|
@@ -5229,6 +5126,12 @@ function shortResourceName(url) {
|
|
|
5229
5126
|
return (url || "").split("?")[0];
|
|
5230
5127
|
}
|
|
5231
5128
|
}
|
|
5129
|
+
var PinnedEnd = class {
|
|
5130
|
+
constructor(atPerf, extras) {
|
|
5131
|
+
this.atPerf = atPerf;
|
|
5132
|
+
this.extras = extras;
|
|
5133
|
+
}
|
|
5134
|
+
};
|
|
5232
5135
|
const QP_RED_THRESHOLD = 35;
|
|
5233
5136
|
const FPS_LOW_RATIO = .7;
|
|
5234
5137
|
const UNLIMITED_REFERENCE_FPS = 60;
|
|
@@ -5245,6 +5148,7 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5245
5148
|
this.actions$ = inject(Actions);
|
|
5246
5149
|
this.videoService = inject(VideoService);
|
|
5247
5150
|
this.signallingService = inject(SignallingService);
|
|
5151
|
+
this.webRtcPlayer = inject(WebRtcPlayerService);
|
|
5248
5152
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
5249
5153
|
this.destroyRef = inject(DestroyRef);
|
|
5250
5154
|
this.destroy$ = new Subject();
|
|
@@ -5276,6 +5180,14 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5276
5180
|
id: "signaling-ws-connected",
|
|
5277
5181
|
event: this.store.select(unrealFeature.selectCirrusConnected).pipe(filter(Boolean), take(1))
|
|
5278
5182
|
};
|
|
5183
|
+
this.iceCheckingEntry = {
|
|
5184
|
+
id: "ice-checking",
|
|
5185
|
+
event: this.iceConnection$("checking")
|
|
5186
|
+
};
|
|
5187
|
+
this.iceConnectedEntry = {
|
|
5188
|
+
id: "ice-connected",
|
|
5189
|
+
event: this.iceConnection$("connected", "completed")
|
|
5190
|
+
};
|
|
5279
5191
|
this.configReceivedEntry = {
|
|
5280
5192
|
id: "config-received",
|
|
5281
5193
|
event: this.signallingService.onConfig$.pipe(filter(Boolean), take(1))
|
|
@@ -5342,6 +5254,11 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5342
5254
|
{
|
|
5343
5255
|
id: "webrtc-negotiation",
|
|
5344
5256
|
color: "#e5c07b",
|
|
5257
|
+
overlays: [{
|
|
5258
|
+
from: this.iceCheckingEntry,
|
|
5259
|
+
to: this.iceConnectedEntry,
|
|
5260
|
+
id: "ice-connectivity-checks"
|
|
5261
|
+
}],
|
|
5345
5262
|
milestones: [
|
|
5346
5263
|
{
|
|
5347
5264
|
id: "offer-received",
|
|
@@ -5364,12 +5281,28 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5364
5281
|
event: this.signallingService.onWebRtcIce$.pipe(filter(Boolean)),
|
|
5365
5282
|
mode: "last"
|
|
5366
5283
|
},
|
|
5284
|
+
this.iceCheckingEntry,
|
|
5285
|
+
{
|
|
5286
|
+
id: "ice-gathering-complete",
|
|
5287
|
+
event: this.webRtcPlayer.iceState$.pipe(filter((e) => e.kind === "gathering" && e.state === "complete"))
|
|
5288
|
+
},
|
|
5289
|
+
this.iceConnectedEntry,
|
|
5290
|
+
{
|
|
5291
|
+
id: "ice-failed",
|
|
5292
|
+
event: this.iceConnection$("failed")
|
|
5293
|
+
},
|
|
5367
5294
|
{
|
|
5368
5295
|
id: "datachannel-connected",
|
|
5369
5296
|
event: this.store.select(unrealFeature.selectDataChannelConnected).pipe(filter(Boolean), take(1), map(() => ({
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5297
|
+
atPerf: performance.now(),
|
|
5298
|
+
extras: {
|
|
5299
|
+
iceCandidateCount: this.session?.iceCandidateCount ?? 0,
|
|
5300
|
+
handshakeFlow: this.session?.handshakeFlow ?? null
|
|
5301
|
+
}
|
|
5302
|
+
})), switchMap(({ atPerf, extras }) => from(this.webRtcPlayer.readIceSnapshot()).pipe(map((ice) => new PinnedEnd(atPerf, {
|
|
5303
|
+
...extras,
|
|
5304
|
+
...iceParams(ice)
|
|
5305
|
+
})))))
|
|
5373
5306
|
}
|
|
5374
5307
|
]
|
|
5375
5308
|
},
|
|
@@ -5449,6 +5382,7 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5449
5382
|
sub,
|
|
5450
5383
|
bytes: new CounterWindow(),
|
|
5451
5384
|
routes: new RouteLog(),
|
|
5385
|
+
paks: new PakLog(anchorPerf),
|
|
5452
5386
|
qpBad: false,
|
|
5453
5387
|
fpsLow: false,
|
|
5454
5388
|
maxFpsTarget: UNLIMITED_REFERENCE_FPS,
|
|
@@ -5468,9 +5402,17 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5468
5402
|
sub.add(this.signallingService.onWebRtcAnswer$.pipe(filter(Boolean), take(1)).subscribe(() => {
|
|
5469
5403
|
if (this.session) this.session.handshakeFlow = "client-offer";
|
|
5470
5404
|
}));
|
|
5471
|
-
sub.add(this.actions$.pipe(ofType(commandStarted)).subscribe(() => {
|
|
5472
|
-
if (this.session)
|
|
5405
|
+
sub.add(this.actions$.pipe(ofType(commandStarted)).subscribe(({ id, command, paks }) => {
|
|
5406
|
+
if (!this.session) return;
|
|
5407
|
+
this.session.commandCount++;
|
|
5408
|
+
if (paks) this.session.paks.start(id, paks, command, performance.now());
|
|
5409
|
+
}));
|
|
5410
|
+
sub.add(this.actions$.pipe(ofType(unrealCommandCallback)).subscribe(({ json }) => {
|
|
5411
|
+
const id = callbackCorrelationId(json);
|
|
5412
|
+
if (!id || !this.session) return;
|
|
5413
|
+
this.session.paks.complete(id, performance.now(), callbackStamps(json));
|
|
5473
5414
|
}));
|
|
5415
|
+
sub.add(interval(SAMPLE_WINDOW_MS).subscribe(() => this.flushPaks()));
|
|
5474
5416
|
sub.add(this.actions$.pipe(ofType(signalingRetryAttempted)).subscribe(({ attempt, reason, kind }) => {
|
|
5475
5417
|
if (!this.session) return;
|
|
5476
5418
|
this.track("stream.signaling_retry", {
|
|
@@ -5489,7 +5431,8 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5489
5431
|
if (!this.session) return;
|
|
5490
5432
|
if (isCloser) {
|
|
5491
5433
|
if (this.adopted$() && PREFETCHED_PHASE_IDS.has(bucket.id)) return;
|
|
5492
|
-
|
|
5434
|
+
const pinned = value instanceof PinnedEnd ? value : null;
|
|
5435
|
+
this.emitPhaseEnded(bucket, bucketIdx, pinned ? pinned.extras : value, false, pinned?.atPerf);
|
|
5493
5436
|
return;
|
|
5494
5437
|
}
|
|
5495
5438
|
const time = Math.round(performance.now() - this.session.anchorPerf);
|
|
@@ -5526,6 +5469,7 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5526
5469
|
const includeGranular = granularReason && granularReason !== DisconnectReason.None;
|
|
5527
5470
|
const openPhase = this.phaseCatalog[session.openPhaseIdx];
|
|
5528
5471
|
if (openPhase) this.emitPhaseEnded(openPhase, session.openPhaseIdx, null, true);
|
|
5472
|
+
this.flushPaks(true);
|
|
5529
5473
|
this.emitLifecycle("stream.session_ended", {
|
|
5530
5474
|
sessionId: id,
|
|
5531
5475
|
reason,
|
|
@@ -5561,9 +5505,9 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5561
5505
|
});
|
|
5562
5506
|
this.session.lastMilestonePerf = now;
|
|
5563
5507
|
}
|
|
5564
|
-
emitPhaseEnded(bucket, bucketIdx, extrasValue, incomplete = false) {
|
|
5508
|
+
emitPhaseEnded(bucket, bucketIdx, extrasValue, incomplete = false, atPerf) {
|
|
5565
5509
|
if (!this.session) return;
|
|
5566
|
-
const now = performance.now();
|
|
5510
|
+
const now = atPerf ?? performance.now();
|
|
5567
5511
|
const phaseStartMs = Math.round(this.session.lastMilestonePerf - this.session.anchorPerf);
|
|
5568
5512
|
const phaseEndMs = Math.round(now - this.session.anchorPerf);
|
|
5569
5513
|
const milestones = this.milestonesOfBucket(bucket);
|
|
@@ -5578,7 +5522,7 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5578
5522
|
params,
|
|
5579
5523
|
overlays,
|
|
5580
5524
|
...incomplete && { incomplete: true }
|
|
5581
|
-
});
|
|
5525
|
+
}, now);
|
|
5582
5526
|
this.closePhase(bucketIdx);
|
|
5583
5527
|
}
|
|
5584
5528
|
closePhase(bucketIdx) {
|
|
@@ -5714,6 +5658,20 @@ var StreamStatusTelemetryService2 = class StreamStatusTelemetryService2 {
|
|
|
5714
5658
|
});
|
|
5715
5659
|
s.fpsLow = fpsLowNow;
|
|
5716
5660
|
}
|
|
5661
|
+
flushPaks(final = false) {
|
|
5662
|
+
const s = this.session;
|
|
5663
|
+
if (!s) return;
|
|
5664
|
+
const items = s.paks.take(performance.now(), final);
|
|
5665
|
+
if (!items.length) return;
|
|
5666
|
+
this.track("stream.pak_timing", {
|
|
5667
|
+
sessionId: s.id,
|
|
5668
|
+
seq: s.seq,
|
|
5669
|
+
items
|
|
5670
|
+
});
|
|
5671
|
+
}
|
|
5672
|
+
iceConnection$(...states) {
|
|
5673
|
+
return this.webRtcPlayer.iceState$.pipe(filter((e) => e.kind === "connection" && states.includes(e.state)));
|
|
5674
|
+
}
|
|
5717
5675
|
updateMaxFpsTarget(maxFps) {
|
|
5718
5676
|
if (this.session) this.session.maxFpsTarget = maxFps;
|
|
5719
5677
|
}
|
|
@@ -5928,6 +5886,20 @@ function fmtCandidate(c) {
|
|
|
5928
5886
|
if (!c?.type) return null;
|
|
5929
5887
|
return c.url ? `${c.type} (${c.url})` : c.type;
|
|
5930
5888
|
}
|
|
5889
|
+
function iceParams(ice) {
|
|
5890
|
+
if (!ice) return {};
|
|
5891
|
+
return {
|
|
5892
|
+
localCandidates: fmtCounts(ice.local),
|
|
5893
|
+
remoteCandidates: fmtCounts(ice.remote),
|
|
5894
|
+
candidatePairs: fmtCounts(ice.pairs),
|
|
5895
|
+
selectedLocal: fmtCandidate(ice.selected?.local),
|
|
5896
|
+
selectedRemote: fmtCandidate(ice.selected?.remote),
|
|
5897
|
+
selectedRttMs: ice.selectedRttMs ?? null
|
|
5898
|
+
};
|
|
5899
|
+
}
|
|
5900
|
+
function fmtCounts(counts) {
|
|
5901
|
+
return Object.entries(counts).map(([k, n]) => `${k} ${n}`).join(" · ") || null;
|
|
5902
|
+
}
|
|
5931
5903
|
function toPhaseParams(value) {
|
|
5932
5904
|
if (!value || typeof value !== "object") return [];
|
|
5933
5905
|
const out = [];
|
|
@@ -7971,6 +7943,6 @@ function provideUnrealModule() {
|
|
|
7971
7943
|
inject(AnalyticsService);
|
|
7972
7944
|
})]);
|
|
7973
7945
|
}
|
|
7974
|
-
export { AFKService, ALL_KEYBOARD_KEYS, AUTO_HIGH_RESOLUTION_IDLE_MS, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, COLOR_CODES,
|
|
7946
|
+
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 };
|
|
7975
7947
|
|
|
7976
7948
|
//# sourceMappingURL=3dsource-angular-unreal-module.mjs.map
|