@3dsource/angular-unreal-module 0.0.175 → 0.0.181
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/README.md +50 -19
- package/fesm2022/3dsource-angular-unreal-module-config.mjs +10 -0
- package/fesm2022/3dsource-angular-unreal-module-config.mjs.map +1 -0
- package/fesm2022/3dsource-angular-unreal-module.mjs +1055 -507
- package/fesm2022/3dsource-angular-unreal-module.mjs.map +1 -1
- package/package.json +8 -4
- package/types/3dsource-angular-unreal-module-config.d.ts +27 -0
- package/types/3dsource-angular-unreal-module.d.ts +246 -165
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@3dsource/angular-unreal-module",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.181",
|
|
4
4
|
"description": "Angular integration for Unreal Engine Pixel Streaming",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"3dsource",
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"author": "3dsource",
|
|
17
17
|
"sideEffects": false,
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"tslib": "^2.8.1"
|
|
19
|
+
"tslib": "^2.8.1",
|
|
20
|
+
"uuid": "^14.0.2"
|
|
20
21
|
},
|
|
21
22
|
"peerDependencies": {
|
|
22
|
-
"@3dsource/types-unreal": ">=0.0.
|
|
23
|
-
"@3dsource/utils": ">=1.0.21",
|
|
23
|
+
"@3dsource/types-unreal": ">=0.0.14 <0.1.0",
|
|
24
24
|
"@angular/cdk": ">=19.0.0 <23.0.0",
|
|
25
25
|
"@angular/common": ">=19.0.0 <23.0.0",
|
|
26
26
|
"@angular/core": ">=19.0.0 <23.0.0",
|
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
".": {
|
|
42
42
|
"types": "./types/3dsource-angular-unreal-module.d.ts",
|
|
43
43
|
"default": "./fesm2022/3dsource-angular-unreal-module.mjs"
|
|
44
|
+
},
|
|
45
|
+
"./config": {
|
|
46
|
+
"types": "./types/3dsource-angular-unreal-module-config.d.ts",
|
|
47
|
+
"default": "./fesm2022/3dsource-angular-unreal-module-config.mjs"
|
|
44
48
|
}
|
|
45
49
|
},
|
|
46
50
|
"type": "module"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Which command protocol the module speaks.
|
|
5
|
+
*
|
|
6
|
+
* - `'metabox'` (default) — the full Metabox command protocol.
|
|
7
|
+
* - `'default'` — a stock Pixel Streaming application: the module sends none of
|
|
8
|
+
* its own `MetaBoxCommand` packets.
|
|
9
|
+
*/
|
|
10
|
+
type UnrealMode = 'metabox' | 'default';
|
|
11
|
+
interface UnrealInitialConfig {
|
|
12
|
+
mode?: UnrealMode;
|
|
13
|
+
playwright?: boolean;
|
|
14
|
+
customErrorsEndpoint?: string;
|
|
15
|
+
commandTelemetryReceiver?: string;
|
|
16
|
+
regionsPingUrl?: string;
|
|
17
|
+
screenLockerContainerId?: string;
|
|
18
|
+
dataChannelConnectionTimeout?: number;
|
|
19
|
+
streamTelemetryV2Url?: string;
|
|
20
|
+
fpsMonitor?: boolean;
|
|
21
|
+
autoHighResolution?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare const UNREAL_CONFIG: InjectionToken<UnrealInitialConfig>;
|
|
25
|
+
|
|
26
|
+
export { UNREAL_CONFIG };
|
|
27
|
+
export type { UnrealInitialConfig, UnrealMode };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as _3dsource_angular_unreal_module from '@3dsource/angular-unreal-module';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { Signal, TemplateRef, ElementRef,
|
|
3
|
+
import { Signal, TemplateRef, ElementRef, DestroyRef, PipeTransform } from '@angular/core';
|
|
4
|
+
import { UnrealInitialConfig } from '@3dsource/angular-unreal-module/config';
|
|
5
|
+
export { UNREAL_CONFIG, UnrealInitialConfig, UnrealMode } from '@3dsource/angular-unreal-module/config';
|
|
4
6
|
import * as _ngrx_store from '@ngrx/store';
|
|
5
7
|
import { Store } from '@ngrx/store';
|
|
6
8
|
import * as rxjs from 'rxjs';
|
|
7
9
|
import { Subject, Observable, Subscription, OperatorFunction } from 'rxjs';
|
|
8
10
|
import * as _ngrx_effects from '@ngrx/effects';
|
|
9
11
|
import { Actions } from '@ngrx/effects';
|
|
10
|
-
import { IKeyCode, ImageOutputValues, Area } from '@3dsource/utils';
|
|
11
12
|
import { SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser';
|
|
12
13
|
import { MetaBoxCommandPacket, MetaBoxCommandList, MetaBoxCallbackList, FOnSceneStateCallback, FOnFocusObjectCallback, FCameraChangedCallback, FOnObjectTransformChangedCallback, FOnChangeSequenceChangedCallback, FOnFinishSequenceChangedCallback } from '@3dsource/types-unreal';
|
|
13
14
|
|
|
@@ -258,6 +259,148 @@ declare const MouseButtonsMask: {
|
|
|
258
259
|
FifthButton: number;
|
|
259
260
|
};
|
|
260
261
|
|
|
262
|
+
/**
|
|
263
|
+
* `KeyboardEvent.code` → the Windows virtual-key code Unreal expects.
|
|
264
|
+
*
|
|
265
|
+
* Only keys whose `event.keyCode` cannot be trusted belong here. The browser
|
|
266
|
+
* already resolves `keyCode` correctly for everything else, so the table exists
|
|
267
|
+
* for two cases: browsers that disagree on a value (Gecko reports the
|
|
268
|
+
* punctuation keys by ASCII — `;` as 59, `=` as 61, `-` as 173) and keys Unreal
|
|
269
|
+
* numbers differently from the DOM (the right-hand modifiers, the Cmd/Win keys).
|
|
270
|
+
*
|
|
271
|
+
* The numpad is deliberately absent. A numpad key reports the same `code` in
|
|
272
|
+
* both NumLock states but a different virtual key — `Numpad4` is 37/`VK_LEFT`
|
|
273
|
+
* with NumLock off and 100/`VK_NUMPAD4` with it on — so any entry here would
|
|
274
|
+
* have to commit to one state and be wrong in the other. Falling through to
|
|
275
|
+
* `event.keyCode` is right in both. `NumpadAdd`/`Subtract`/`Multiply`/`Divide`
|
|
276
|
+
* stay because they do not change with NumLock.
|
|
277
|
+
*
|
|
278
|
+
* `SpecialKeyCodes` in `./buttons-codes` repeats seven of these entries with
|
|
279
|
+
* the same values. The two are kept apart because both are public API; merging
|
|
280
|
+
* them would be a breaking change.
|
|
281
|
+
*
|
|
282
|
+
* Values must stay unique so `InvertedKeyMap` is lossless. The `OSLeft`/
|
|
283
|
+
* `MetaLeft` and `OSRight`/`MetaRight` pairs share a value on purpose: they are
|
|
284
|
+
* legacy and current names for the same physical key.
|
|
285
|
+
*/
|
|
286
|
+
declare const KeyboardNumericCode: {
|
|
287
|
+
readonly Backspace: 8;
|
|
288
|
+
readonly Tab: 9;
|
|
289
|
+
readonly Enter: 13;
|
|
290
|
+
readonly ShiftLeft: 16;
|
|
291
|
+
readonly ControlLeft: 17;
|
|
292
|
+
readonly AltLeft: 18;
|
|
293
|
+
readonly Escape: 27;
|
|
294
|
+
readonly Space: 32;
|
|
295
|
+
readonly ArrowLeft: 37;
|
|
296
|
+
readonly ArrowUp: 38;
|
|
297
|
+
readonly ArrowRight: 39;
|
|
298
|
+
readonly ArrowDown: 40;
|
|
299
|
+
readonly Digit0: 48;
|
|
300
|
+
readonly Digit1: 49;
|
|
301
|
+
readonly Digit2: 50;
|
|
302
|
+
readonly Digit3: 51;
|
|
303
|
+
readonly Digit4: 52;
|
|
304
|
+
readonly Digit5: 53;
|
|
305
|
+
readonly Digit6: 54;
|
|
306
|
+
readonly Digit7: 55;
|
|
307
|
+
readonly Digit8: 56;
|
|
308
|
+
readonly Digit9: 57;
|
|
309
|
+
readonly KeyA: 65;
|
|
310
|
+
readonly KeyB: 66;
|
|
311
|
+
readonly KeyC: 67;
|
|
312
|
+
readonly KeyD: 68;
|
|
313
|
+
readonly KeyE: 69;
|
|
314
|
+
readonly KeyF: 70;
|
|
315
|
+
readonly KeyG: 71;
|
|
316
|
+
readonly KeyH: 72;
|
|
317
|
+
readonly KeyI: 73;
|
|
318
|
+
readonly KeyJ: 74;
|
|
319
|
+
readonly KeyK: 75;
|
|
320
|
+
readonly KeyL: 76;
|
|
321
|
+
readonly KeyM: 77;
|
|
322
|
+
readonly KeyN: 78;
|
|
323
|
+
readonly KeyO: 79;
|
|
324
|
+
readonly KeyP: 80;
|
|
325
|
+
readonly KeyQ: 81;
|
|
326
|
+
readonly KeyR: 82;
|
|
327
|
+
readonly KeyS: 83;
|
|
328
|
+
readonly KeyT: 84;
|
|
329
|
+
readonly KeyU: 85;
|
|
330
|
+
readonly KeyV: 86;
|
|
331
|
+
readonly KeyW: 87;
|
|
332
|
+
readonly KeyX: 88;
|
|
333
|
+
readonly KeyY: 89;
|
|
334
|
+
readonly KeyZ: 90;
|
|
335
|
+
readonly OSLeft: 91;
|
|
336
|
+
readonly MetaLeft: 91;
|
|
337
|
+
readonly OSRight: 92;
|
|
338
|
+
readonly MetaRight: 92;
|
|
339
|
+
readonly ContextMenu: 93;
|
|
340
|
+
readonly NumpadMultiply: 106;
|
|
341
|
+
readonly NumpadAdd: 107;
|
|
342
|
+
readonly NumpadSubtract: 109;
|
|
343
|
+
readonly NumpadDivide: 111;
|
|
344
|
+
readonly F1: 112;
|
|
345
|
+
readonly F2: 113;
|
|
346
|
+
readonly F3: 114;
|
|
347
|
+
readonly F4: 115;
|
|
348
|
+
readonly F5: 116;
|
|
349
|
+
readonly F6: 117;
|
|
350
|
+
readonly F7: 118;
|
|
351
|
+
readonly F8: 119;
|
|
352
|
+
readonly F9: 120;
|
|
353
|
+
readonly F10: 121;
|
|
354
|
+
readonly F11: 122;
|
|
355
|
+
readonly F12: 123;
|
|
356
|
+
readonly NumLock: 144;
|
|
357
|
+
readonly ScrollLock: 145;
|
|
358
|
+
readonly Semicolon: 186;
|
|
359
|
+
readonly Equal: 187;
|
|
360
|
+
readonly Comma: 188;
|
|
361
|
+
readonly Minus: 189;
|
|
362
|
+
readonly Period: 190;
|
|
363
|
+
readonly Slash: 191;
|
|
364
|
+
readonly Backquote: 192;
|
|
365
|
+
readonly BracketLeft: 219;
|
|
366
|
+
readonly Backslash: 220;
|
|
367
|
+
readonly BracketRight: 221;
|
|
368
|
+
readonly Quote: 222;
|
|
369
|
+
readonly IntlBackslash: 226;
|
|
370
|
+
readonly ShiftRight: 253;
|
|
371
|
+
readonly ControlRight: 254;
|
|
372
|
+
readonly AltRight: 255;
|
|
373
|
+
};
|
|
374
|
+
/**
|
|
375
|
+
* The `keyCode` a browser reports while an IME is composing (`VK_PROCESSKEY`).
|
|
376
|
+
*
|
|
377
|
+
* `event.code` keeps naming the *physical* key during composition — `KeyW`,
|
|
378
|
+
* `KeyA` and friends — so a consumer that forwards keys has to drop these
|
|
379
|
+
* events explicitly or typing CJK text turns into keystrokes.
|
|
380
|
+
*/
|
|
381
|
+
declare const IME_PROCESS_KEY = 229;
|
|
382
|
+
/**
|
|
383
|
+
* Codes of the keys that are themselves modifiers. A modifier's own `keydown`
|
|
384
|
+
* already reports `ctrlKey`/`metaKey` as pressed, so a "browser shortcut in
|
|
385
|
+
* flight" check has to exempt them or `ControlRight` would block itself.
|
|
386
|
+
*/
|
|
387
|
+
declare const MODIFIER_KEY_CODES: ReadonlySet<string>;
|
|
388
|
+
type IKeyName = keyof typeof KeyboardNumericCode;
|
|
389
|
+
type IKeyCode = (typeof KeyboardNumericCode)[IKeyName];
|
|
390
|
+
/**
|
|
391
|
+
* A physical key name as reported by `KeyboardEvent.code`.
|
|
392
|
+
*
|
|
393
|
+
* The union lists the names this table knows a virtual-key code for, so editors
|
|
394
|
+
* complete them. The `string` branch keeps every other DOM code assignable —
|
|
395
|
+
* `'Numpad4'`, `'Delete'`, `'Home'` — since a key needs no entry here to be
|
|
396
|
+
* matched against `event.code`.
|
|
397
|
+
*/
|
|
398
|
+
type IKeyCodeName = IKeyName | (string & Record<never, never>);
|
|
399
|
+
type InvertedKeyMapType = {
|
|
400
|
+
[K in IKeyName as (typeof KeyboardNumericCode)[K]]: K;
|
|
401
|
+
};
|
|
402
|
+
declare const InvertedKeyMap: InvertedKeyMapType;
|
|
403
|
+
|
|
261
404
|
declare const ControlScheme: {
|
|
262
405
|
readonly LockedMouse: 0;
|
|
263
406
|
readonly HoveringMouse: 1;
|
|
@@ -355,26 +498,32 @@ interface FreezeFrameMessage {
|
|
|
355
498
|
}
|
|
356
499
|
|
|
357
500
|
/**
|
|
358
|
-
*
|
|
501
|
+
* Geometry primitives used by the resize helpers.
|
|
359
502
|
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
* its own `MetaBoxCommand` packets.
|
|
503
|
+
* Collapsed into one file from the four these were split across, so the
|
|
504
|
+
* package no longer names another library in its public type surface.
|
|
363
505
|
*/
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
506
|
+
interface Size {
|
|
507
|
+
w: number;
|
|
508
|
+
h: number;
|
|
509
|
+
}
|
|
510
|
+
interface Coords {
|
|
511
|
+
x: number;
|
|
512
|
+
y: number;
|
|
513
|
+
}
|
|
514
|
+
interface Rect extends Size, Coords {
|
|
515
|
+
}
|
|
516
|
+
interface Area extends Rect {
|
|
517
|
+
scale: number;
|
|
376
518
|
}
|
|
377
519
|
|
|
520
|
+
/**
|
|
521
|
+
* Output format accepted by {@link getImageFromVideoStream}.
|
|
522
|
+
*
|
|
523
|
+
* `'canvas'` returns the element itself; the MIME types return a data URL.
|
|
524
|
+
*/
|
|
525
|
+
type ImageOutputValues = 'canvas' | 'image/png' | 'image/webp' | 'image/jpeg';
|
|
526
|
+
|
|
378
527
|
interface SignalingData {
|
|
379
528
|
instanceType: string;
|
|
380
529
|
branchInfo: string;
|
|
@@ -1020,8 +1169,6 @@ type UnrealUiClasses = Partial<Record<UnrealUiPart, string | string[]>>;
|
|
|
1020
1169
|
|
|
1021
1170
|
type TelemetryType = 'commandSent' | 'commandStop';
|
|
1022
1171
|
|
|
1023
|
-
declare const UNREAL_CONFIG: InjectionToken<UnrealInitialConfig>;
|
|
1024
|
-
|
|
1025
1172
|
declare const InputOptions: InputProps;
|
|
1026
1173
|
|
|
1027
1174
|
/** Disconnect reasons that should trigger remote connection cleanup. */
|
|
@@ -1282,10 +1429,10 @@ declare class FreezeFrameService extends SubService {
|
|
|
1282
1429
|
|
|
1283
1430
|
declare class InputService extends SubService {
|
|
1284
1431
|
private readonly commandsSender;
|
|
1285
|
-
private readonly
|
|
1432
|
+
private readonly devModeService;
|
|
1286
1433
|
private readonly videoService;
|
|
1287
1434
|
private readonly unrealConfig;
|
|
1288
|
-
readonly defaultKeys:
|
|
1435
|
+
readonly defaultKeys: readonly IKeyCodeName[];
|
|
1289
1436
|
private availableKeys;
|
|
1290
1437
|
private options;
|
|
1291
1438
|
private reInit$;
|
|
@@ -1296,6 +1443,7 @@ declare class InputService extends SubService {
|
|
|
1296
1443
|
private fingerIds;
|
|
1297
1444
|
private maxByteValue;
|
|
1298
1445
|
private fingers;
|
|
1446
|
+
private readonly heldKeys;
|
|
1299
1447
|
private readonly mouseMoveView;
|
|
1300
1448
|
private readonly mouseButtonView;
|
|
1301
1449
|
private readonly mouseWheelView;
|
|
@@ -1307,7 +1455,16 @@ declare class InputService extends SubService {
|
|
|
1307
1455
|
private offsetParams;
|
|
1308
1456
|
constructor();
|
|
1309
1457
|
protected init(): void;
|
|
1310
|
-
|
|
1458
|
+
/**
|
|
1459
|
+
* Replaces the forwarded-key allow-list. Takes physical key names
|
|
1460
|
+
* (`KeyboardEvent.code`) such as `'KeyW'` or `'BracketLeft'`.
|
|
1461
|
+
*
|
|
1462
|
+
* Legacy numeric `keyCode` values are still accepted and converted, but they
|
|
1463
|
+
* cannot express every key: `InvertedKeyMap` is many-to-one, so 37 resolves
|
|
1464
|
+
* to `'ArrowLeft'` and 17 to `'ControlLeft'`, and `'Numpad4'`/`'ControlRight'`
|
|
1465
|
+
* are unreachable through the numeric form. Pass names.
|
|
1466
|
+
*/
|
|
1467
|
+
useKeyboardKeys(keys: readonly (IKeyCode | IKeyCodeName)[]): void;
|
|
1311
1468
|
get video(): HTMLVideoElement | null;
|
|
1312
1469
|
private setup;
|
|
1313
1470
|
/**
|
|
@@ -1336,22 +1493,46 @@ declare class InputService extends SubService {
|
|
|
1336
1493
|
private pressMouseButtons;
|
|
1337
1494
|
private registerHoveringMouseEvents;
|
|
1338
1495
|
private registerMouseEnterAndLeaveEvents;
|
|
1339
|
-
private isKeyCodeBrowserKey;
|
|
1340
1496
|
/**
|
|
1341
|
-
*
|
|
1497
|
+
* Keys whose default browser action fights the stream: the function keys
|
|
1498
|
+
* (F5 reloads mid-session), Tab (moves focus out of the player) and the
|
|
1499
|
+
* arrows (scroll the page while they steer the camera).
|
|
1500
|
+
*
|
|
1501
|
+
* Takes the *resolved* virtual-key code rather than `event.code`, so a numpad
|
|
1502
|
+
* key acting as an arrow with NumLock off is caught as well.
|
|
1503
|
+
*/
|
|
1504
|
+
private isBrowserKey;
|
|
1505
|
+
/**
|
|
1506
|
+
* The key code Unreal expects — the Windows virtual-key code — or `null` when
|
|
1507
|
+
* the event carries no key worth forwarding.
|
|
1342
1508
|
*
|
|
1343
|
-
* `
|
|
1344
|
-
*
|
|
1345
|
-
*
|
|
1346
|
-
* `KeyboardNumericCode` is keyed by `e.code` and holds the virtual-key value,
|
|
1347
|
-
* so it resolves the same number on every browser; a no-op on Chrome.
|
|
1509
|
+
* `KeyboardNumericCode` covers only the keys whose `event.keyCode` cannot be
|
|
1510
|
+
* trusted; everything else, the numpad included, falls through to the value
|
|
1511
|
+
* the browser resolved.
|
|
1348
1512
|
*
|
|
1349
|
-
*
|
|
1350
|
-
*
|
|
1513
|
+
* Returns `null` for an IME composition — `event.code` still names the
|
|
1514
|
+
* physical key there, so the keystrokes would otherwise reach the engine as
|
|
1515
|
+
* camera movement — and for a `keyCode` of 0, which no engine key uses.
|
|
1351
1516
|
*/
|
|
1352
1517
|
private getKeyCode;
|
|
1518
|
+
/**
|
|
1519
|
+
* True while a focused element owns the keyboard. Read off `composedPath()`
|
|
1520
|
+
* rather than `event.target`: retargeting reports the host element for an
|
|
1521
|
+
* `<input>` inside a shadow root, so a `target`-based check never fires in an
|
|
1522
|
+
* app built from web components.
|
|
1523
|
+
*/
|
|
1524
|
+
private isTextEntryTarget;
|
|
1525
|
+
/** True when `event.code` is on the allow-list, or dev mode waives it. */
|
|
1526
|
+
private isKeyAllowed;
|
|
1527
|
+
private sendKeyUp;
|
|
1528
|
+
/**
|
|
1529
|
+
* Releases everything the engine still believes is held. Needed because a
|
|
1530
|
+
* `keyup` is not guaranteed to arrive: the window can lose focus to a browser
|
|
1531
|
+
* dialog or another tab first, and then the engine keeps moving the camera
|
|
1532
|
+
* forever.
|
|
1533
|
+
*/
|
|
1534
|
+
private releaseKeys;
|
|
1353
1535
|
private registerKeyboardEvents;
|
|
1354
|
-
private startListenKeys;
|
|
1355
1536
|
static ɵfac: i0.ɵɵFactoryDeclaration<InputService, never>;
|
|
1356
1537
|
static ɵprov: i0.ɵɵInjectableDeclaration<InputService>;
|
|
1357
1538
|
}
|
|
@@ -1804,11 +1985,10 @@ declare class StreamStatusTelemetryService2 {
|
|
|
1804
1985
|
/**
|
|
1805
1986
|
* Emit the region / signaling / webrtc phases for an ADOPTED connection.
|
|
1806
1987
|
*
|
|
1807
|
-
* The prefetch script established the connection in
|
|
1808
|
-
* so
|
|
1809
|
-
*
|
|
1810
|
-
*
|
|
1811
|
-
* happened while the page was loading. Each phase ships:
|
|
1988
|
+
* The prefetch script established the connection in parallel with page load,
|
|
1989
|
+
* so phases sit at their real anchor-relative spans — shifted left to overlap
|
|
1990
|
+
* the HTML-loading / route-idle rows instead of following them. Each phase
|
|
1991
|
+
* ships:
|
|
1812
1992
|
* - `duration` — the real sub-step time the prefetch spent.
|
|
1813
1993
|
* - `spanStartMs` — anchor-relative start, so the viewer left-shifts the bar.
|
|
1814
1994
|
* - `adoptionAtMs` — where Angular took over (the next phase, Unreal
|
|
@@ -1855,22 +2035,15 @@ declare class StreamStatusTelemetryService2 {
|
|
|
1855
2035
|
*/
|
|
1856
2036
|
private collectBootstrapInfo;
|
|
1857
2037
|
/**
|
|
1858
|
-
*
|
|
1859
|
-
*
|
|
1860
|
-
*
|
|
1861
|
-
*
|
|
1862
|
-
*
|
|
1863
|
-
*
|
|
1864
|
-
* - `lazyResources` — fetched after `loadEventEnd` (= typically the
|
|
1865
|
-
* route's lazy-loaded chunks, JSON manifests etc. that download
|
|
1866
|
-
* when the user navigates to a sub-route the streamer lives on).
|
|
2038
|
+
* Aggregates `performance.getEntriesByType('resource')` by `initiatorType`,
|
|
2039
|
+
* split at `window.load`: `resources` for entries before `loadEventEnd` (the
|
|
2040
|
+
* actual page weight) and `lazyResources` for those after it (typically the
|
|
2041
|
+
* route's lazy chunks and manifests, downloaded when the user navigates to the
|
|
2042
|
+
* sub-route the streamer lives on). If `loadEventEnd` is 0 or unknown,
|
|
2043
|
+
* everything lands in `resources` and `lazyResources` is null.
|
|
1867
2044
|
*
|
|
1868
|
-
*
|
|
1869
|
-
*
|
|
1870
|
-
*
|
|
1871
|
-
* `transferSize === 0 && decodedBodySize > 0` means the resource came from
|
|
1872
|
-
* the HTTP cache — counted separately so cached hits don't inflate
|
|
1873
|
-
* the "bytes on the wire" metric.
|
|
2045
|
+
* `transferSize === 0 && decodedBodySize > 0` means an HTTP-cache hit, counted
|
|
2046
|
+
* separately so it does not inflate the bytes-on-the-wire metric.
|
|
1874
2047
|
*/
|
|
1875
2048
|
private collectResourceTotals;
|
|
1876
2049
|
private aggregate;
|
|
@@ -2197,77 +2370,22 @@ declare class AnalyticsService extends SubService {
|
|
|
2197
2370
|
}
|
|
2198
2371
|
|
|
2199
2372
|
/**
|
|
2200
|
-
* Adaptive FPS controller
|
|
2201
|
-
*
|
|
2202
|
-
*
|
|
2203
|
-
* ## How it works
|
|
2204
|
-
*
|
|
2205
|
-
* The service subscribes to `VideoService.videoStats$` (emitted every 250 ms)
|
|
2206
|
-
* and collects samples of FPS, bitrate, and QP (Quantization Parameter).
|
|
2207
|
-
* Every {@link SAMPLE_WINDOW} ticks (~2 s) it averages the collected samples
|
|
2208
|
-
* and feeds them into a set of **fuzzy-logic membership functions** that
|
|
2209
|
-
* classify each metric into overlapping quality bands.
|
|
2210
|
-
*
|
|
2211
|
-
* ### Input signals
|
|
2212
|
-
*
|
|
2213
|
-
* **1. FPS ratio** = `actualFPS / currentTargetFPS` (0..1+)
|
|
2214
|
-
*
|
|
2215
|
-
* | Band | Range | Meaning |
|
|
2216
|
-
* |--------|---------------------|-----------------------------------------------|
|
|
2217
|
-
* | low | ratio < 0.7 → 1.0, linear ramp 0.7..0.9 → 0 | Stream cannot keep up with the target |
|
|
2218
|
-
* | okays | triangle 0.8..1.0, peak at 0.95 | Stream roughly matches the target |
|
|
2219
|
-
* | high | ratio 0.9..1.0 → ramp, >1.0 → 1.0 | Stream meets or exceeds the target |
|
|
2220
|
-
*
|
|
2221
|
-
* **2. Bitrate load** = `currentBitrate / MAX_BITRATE` (0..1+)
|
|
2222
|
-
*
|
|
2223
|
-
* `MAX_BITRATE` = 20 Mbit/s — the reference ceiling for the encoder.
|
|
2224
|
-
*
|
|
2225
|
-
* | Band | Range | Meaning |
|
|
2226
|
-
* |--------|-------------------------------------------------|-----------------------------------------------|
|
|
2227
|
-
* | high | load 0.5..0.8 → ramp, >0.8 → 1.0 | Encoder is using most of the available bandwidth |
|
|
2228
|
-
* | not high | load < 0.5 → 0.0 | Bandwidth headroom is available |
|
|
2229
|
-
*
|
|
2230
|
-
* **3. Quality** — mapped from QP via `mapQpToQuality()` (see {@link Quality}):
|
|
2231
|
-
*
|
|
2232
|
-
* | Quality | QP range | Meaning |
|
|
2233
|
-
* |----------|-----------|-------------------------------------------------|
|
|
2234
|
-
* | `lime` | QP <= 26 | Good — encoder has enough headroom |
|
|
2235
|
-
* | `orange` | QP 27..35 | Fair — encoder is under moderate pressure |
|
|
2236
|
-
* | `red` | QP > 35 | Poor — heavy compression, visible artifacts |
|
|
2237
|
-
*
|
|
2238
|
-
* ### Decision rules (evaluated in priority order, first match wins)
|
|
2239
|
-
*
|
|
2240
|
-
* | # | Condition | Decision |
|
|
2241
|
-
* |---|------------------------------------------------------------|--------------|
|
|
2242
|
-
* | 1 | FPS ratio is **low** (membership > 0.5) | **decrease** |
|
|
2243
|
-
* | 2 | FPS ratio is **ok** AND quality is `red` | **decrease** |
|
|
2244
|
-
* | 3 | FPS ratio is **ok** AND bitrate **high** AND quality is `orange` | **hold** |
|
|
2245
|
-
* | 4 | FPS ratio is **high** AND quality is `lime` AND bitrate **not high** | **increase** |
|
|
2246
|
-
* | — | Everything else | **hold** |
|
|
2247
|
-
*
|
|
2248
|
-
* ## Cooldown-based throttling
|
|
2373
|
+
* Adaptive FPS controller: watches the incoming WebRTC stream and steers Unreal's
|
|
2374
|
+
* `t.MaxFPS` between the discrete {@link FPS_STEPS}.
|
|
2249
2375
|
*
|
|
2250
|
-
*
|
|
2251
|
-
*
|
|
2252
|
-
*
|
|
2253
|
-
*
|
|
2376
|
+
* Every {@link SAMPLE_WINDOW} ticks of `VideoService.videoStats$` (250 ms each)
|
|
2377
|
+
* it averages FPS, bitrate and QP, runs them through the fuzzy membership
|
|
2378
|
+
* functions below, and picks a decision by first-match rules. Fuzzy bands rather
|
|
2379
|
+
* than hard thresholds so a metric sitting on a boundary does not oscillate.
|
|
2254
2380
|
*
|
|
2255
|
-
*
|
|
2256
|
-
*
|
|
2257
|
-
*
|
|
2258
|
-
*
|
|
2259
|
-
* | increase | decrease | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
|
|
2260
|
-
* | increase | increase | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
|
|
2381
|
+
* Cooldowns between steps are deliberately asymmetric: stepping *down* again is
|
|
2382
|
+
* allowed after {@link COOLDOWN_DECREASE_AFTER_DECREASE_MS}, but stepping back
|
|
2383
|
+
* *up* after a decrease waits {@link COOLDOWN_INCREASE_AFTER_DECREASE_MS} — a
|
|
2384
|
+
* stream that just failed its target is likely to fail it again.
|
|
2261
2385
|
*
|
|
2262
|
-
*
|
|
2263
|
-
*
|
|
2264
|
-
*
|
|
2265
|
-
*
|
|
2266
|
-
* ## FPS dispatch
|
|
2267
|
-
*
|
|
2268
|
-
* FPS changes are dispatched via the NgRx `setMaxFps` action, which triggers
|
|
2269
|
-
* the existing `UnrealEffects.setMaxFps$` effect that sends the
|
|
2270
|
-
* `t.MaxFPS <value>` console command to Unreal Engine.
|
|
2386
|
+
* Changes go out as the `setMaxFps` action, not a direct command: the existing
|
|
2387
|
+
* `UnrealEffects.setMaxFps$` effect turns it into the `t.MaxFPS <value>` console
|
|
2388
|
+
* command.
|
|
2271
2389
|
*/
|
|
2272
2390
|
declare class FpsMonitorService extends SubService {
|
|
2273
2391
|
private readonly videoService;
|
|
@@ -2320,52 +2438,15 @@ declare class FpsMonitorService extends SubService {
|
|
|
2320
2438
|
*/
|
|
2321
2439
|
private processTick;
|
|
2322
2440
|
private handleMonitoring;
|
|
2323
|
-
/**
|
|
2324
|
-
* Combines fuzzy membership values into a single discrete decision.
|
|
2325
|
-
* Rules are evaluated in priority order — first match wins.
|
|
2326
|
-
*
|
|
2327
|
-
* Inputs:
|
|
2328
|
-
* - `fpsRatio` = avgFPS / currentTargetFPS (e.g., 45/60 = 0.75)
|
|
2329
|
-
* - `bitrateLoad` = avgBitrate / 20 Mbit/s (e.g., 12M/20M = 0.6)
|
|
2330
|
-
* - `quality` = mapQpToQuality(avgQP) → 'lime' | 'orange' | 'red'
|
|
2331
|
-
*/
|
|
2441
|
+
/** Rules are evaluated in priority order — first match wins. */
|
|
2332
2442
|
private evaluateDecision;
|
|
2333
|
-
/**
|
|
2334
|
-
* FPS ratio membership "low".
|
|
2335
|
-
* Input: a ratio = actualFPS / targetFPS (e.g., 42/60 = 0.70).
|
|
2336
|
-
*
|
|
2337
|
-
* ratio < 0.7 → 1.0 (clearly failing, e.g., 40/60)
|
|
2338
|
-
* ratio 0.7..0.9 → linear ramp down (e.g., 0.8 → 0.5)
|
|
2339
|
-
* a ratio > 0.9 → 0.0 (keeping up)
|
|
2340
|
-
*/
|
|
2443
|
+
/** "low" — the stream cannot keep up with its target. */
|
|
2341
2444
|
private membershipFpsLow;
|
|
2342
|
-
/**
|
|
2343
|
-
* FPS ratio membership "ok" — triangle shape.
|
|
2344
|
-
* Input: ratio = actualFPS / targetFPS.
|
|
2345
|
-
*
|
|
2346
|
-
* ratio < 0.8 → 0.0
|
|
2347
|
-
* ratio 0.8..0.95 → ramp up, peak at 0.95 (e.g., 57/60)
|
|
2348
|
-
* ratio 0.95..1.0 → ramp down
|
|
2349
|
-
* a ratio > 1.0 → 0.0
|
|
2350
|
-
*/
|
|
2445
|
+
/** "ok" — triangle peaking just under the target. */
|
|
2351
2446
|
private membershipFpsOk;
|
|
2352
|
-
/**
|
|
2353
|
-
* FPS ratio membership "high".
|
|
2354
|
-
* Input: ratio = actualFPS / targetFPS.
|
|
2355
|
-
*
|
|
2356
|
-
* ratio < 0.9 → 0.0
|
|
2357
|
-
* ratio 0.9..1.0 → linear ramp up (e.g., 0.95 → 0.5)
|
|
2358
|
-
* a ratio >= 1.0 → 1.0 (meeting or exceeding target, e.g., 60/60)
|
|
2359
|
-
*/
|
|
2447
|
+
/** "high" — the stream meets or exceeds its target. */
|
|
2360
2448
|
private membershipFpsHigh;
|
|
2361
|
-
/**
|
|
2362
|
-
* Bitrate load membership "high".
|
|
2363
|
-
* Input: a load = currentBitrate / MAX_BITRATE (20 Mbit/s).
|
|
2364
|
-
*
|
|
2365
|
-
* load < 0.5 → 0.0 (below 10 Mbit/s — plenty of headroom)
|
|
2366
|
-
* load 0.5..0.8 → linear ramp (e.g., 13M/20M = 0.65 → 0.5)
|
|
2367
|
-
* load > 0.8 → 1.0 (above 16 Mbit/s — near capacity)
|
|
2368
|
-
*/
|
|
2449
|
+
/** "high" — the encoder is using most of the available bandwidth. */
|
|
2369
2450
|
private membershipBitrateHigh;
|
|
2370
2451
|
private upgradeFps;
|
|
2371
2452
|
/**
|
|
@@ -3502,5 +3583,5 @@ declare const selectUserInactivityDetected: _ngrx_store.MemoizedSelector<Record<
|
|
|
3502
3583
|
/** Used by external consumers (e.g., metabox). Do not remove. */
|
|
3503
3584
|
declare const selectIsVideoPlayingAndDataChannelConnected: _ngrx_store.MemoizedSelector<Record<string, any>, boolean, (s1: boolean, s2: boolean) => boolean>;
|
|
3504
3585
|
|
|
3505
|
-
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, DESTROY_DISCONNECT_REASONS, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverService, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, INNER_RETRY_LIMIT, INSTANCE_READY_TIMEOUT, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, LatencyTimings, LoadingProgressService, MINIMAL_FPS, MIN_CONTAINER_SIZE, MessageType, MouseButton, MouseButtonsMask, 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_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, StreamAdoptionService, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage,
|
|
3506
|
-
export type { AggregatedStat, AnySignalingMessage, AppOwnedStream, AwsInstance, BootstrapInfo, CandidateMessage, CirrusRequestKind, CloseReason, CommandInProgress, ConfigMessage, ConnectionError, ControlSchemeValues, DisconnectReasonType, EmittedMilestone, EventId, FpsLowData, FreezeFrameMessage, InboundVideoStats, InputProps, InstanceReady, InstanceReserved, InterruptClientStream, ListStreamersMessage, MessageBase, MessageTypeValues, OrchestrationErrorMessage, OrchestrationMessageType, P2PEstablishedMessage, ParkedStream, PhaseEndedData, PhaseOverlay, PhaseParam, PlayerCountMessage, PollingOrchestrationMessage, Quality, QualityAnomalyData, ReceivedFile, RequestStream, ResourceBucket, ResourceTotals, SSInfo, SampleData, SelectedIceCandidatePair, SessionEndReason, SessionEndedData, SessionStartedData, SignalingData, SignalingMessageHandler, SignalingMessageMap, SignalingRetryData, SignalingRetryKind, SlowResource, StreamConfig, StreamRequestContext, StreamResolutionProps, StreamTelemetryEvent, StreamTelemetryEventMap, StreamTelemetryEventName, StreamTelemetryLifecycleData, StreamTelemetryLifecycleEventName, StreamTelemetryTrackData, StreamerListMessage, TelemetryEventEnvelope, TelemetryLifecycleEnvelope, TelemetryType, UnknownFields, UnrealAfkSlotContext, UnrealCallbackDescriptor, UnrealCallbackEventMap, UnrealCallbackJson, UnrealCallbackJsonWrapped,
|
|
3586
|
+
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, DESTROY_DISCONNECT_REASONS, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverService, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, IME_PROCESS_KEY, INNER_RETRY_LIMIT, INSTANCE_READY_TIMEOUT, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, InvertedKeyMap, KeyboardNumericCode, LatencyTimings, LoadingProgressService, MINIMAL_FPS, MIN_CONTAINER_SIZE, MODIFIER_KEY_CODES, MessageType, MouseButton, MouseButtonsMask, 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_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, StreamAdoptionService, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage, UnrealAfkSlotDirective, UnrealCallbackService, UnrealCommunicatorService, UnrealEffects, 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, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, dropDC, dropPC, floatToPercents, floatToSmoothPercents, forceResizeViewport, fromResizeObserver, getActiveUrl, getImageFromVideoStream, getResizeStudioValues, getResizeValuesUniversal, getRtcErrorMessage, iceConnectionFailed, initSignalling, instanceReady, isAppOwned, isMetaboxMode, keepMaxUntilReset, 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, trackMixpanelEvent, trackTelemetryData, uint8ToBase64, unrealCommandCallback, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
|
|
3587
|
+
export type { AggregatedStat, AnySignalingMessage, AppOwnedStream, Area, AwsInstance, BootstrapInfo, CandidateMessage, CirrusRequestKind, CloseReason, CommandInProgress, ConfigMessage, ConnectionError, ControlSchemeValues, Coords, DisconnectReasonType, EmittedMilestone, EventId, FpsLowData, FreezeFrameMessage, IKeyCode, IKeyCodeName, IKeyName, ImageOutputValues, InboundVideoStats, InputProps, InstanceReady, InstanceReserved, InterruptClientStream, ListStreamersMessage, MessageBase, MessageTypeValues, OrchestrationErrorMessage, OrchestrationMessageType, P2PEstablishedMessage, ParkedStream, PhaseEndedData, PhaseOverlay, PhaseParam, PlayerCountMessage, PollingOrchestrationMessage, Quality, QualityAnomalyData, ReceivedFile, Rect, RequestStream, ResourceBucket, ResourceTotals, SSInfo, SampleData, SelectedIceCandidatePair, SessionEndReason, SessionEndedData, SessionStartedData, SignalingData, SignalingMessageHandler, SignalingMessageMap, SignalingRetryData, SignalingRetryKind, Size, SlowResource, StreamConfig, StreamRequestContext, StreamResolutionProps, StreamTelemetryEvent, StreamTelemetryEventMap, StreamTelemetryEventName, StreamTelemetryLifecycleData, StreamTelemetryLifecycleEventName, StreamTelemetryTrackData, StreamerListMessage, TelemetryEventEnvelope, TelemetryLifecycleEnvelope, TelemetryType, UnknownFields, UnrealAfkSlotContext, UnrealCallbackDescriptor, UnrealCallbackEventMap, UnrealCallbackJson, UnrealCallbackJsonWrapped, UnrealResumeSlotContext, UnrealSlotTemplateContext, UnrealState, UnrealStatusSlotContext, UnrealUiClasses, UnrealUiPart, WSCloseCodesValues, WindowAggregate };
|