UNPKG

@3dsource/angular-unreal-module

Version:

Angular Unreal module for connect with unreal engine stream

1,304 lines (1,225 loc) 87 kB
import * as i0 from '@angular/core'; import { AfterViewInit, ElementRef, OnInit, InjectionToken, PipeTransform } from '@angular/core'; import { DialogRef } from '@angular/cdk/dialog'; import * as _ngrx_store from '@ngrx/store'; import { Store } from '@ngrx/store'; import * as rxjs from 'rxjs'; import { Observable, Subject } from 'rxjs'; import * as _3dsource_angular_unreal_module from '@3dsource/angular-unreal-module'; import { MetaBoxCommandPacket, MetaBoxCommandList } from '@3dsource/types-unreal'; import { IKeyCode, ImageOutputValues } from '@3dsource/utils'; import { SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser'; import * as _ngrx_effects from '@ngrx/effects'; declare class ClickableOverlayComponent { state: i0.Signal<{ message: string; className: string; isActivityDetected: boolean; onOverlayClick: () => void; } | null | undefined>; static ɵfac: i0.ɵɵFactoryDeclaration<ClickableOverlayComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<ClickableOverlayComponent, "app-clickable-overlay", never, {}, {}, never, never, true, never>; } declare class FreezeFrameComponent { private store; freezeFrameProgressMessageFromVideo: i0.Signal<number | null | undefined>; combinedFreeze: i0.Signal<string | null | undefined>; static ɵfac: i0.ɵɵFactoryDeclaration<FreezeFrameComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<FreezeFrameComponent, "app-freeze-frame", never, {}, {}, never, never, true, never>; } declare class LowBandwidthModalComponent { dialogRef: DialogRef<any, any>; close(value?: boolean): void; static ɵfac: i0.ɵɵFactoryDeclaration<LowBandwidthModalComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<LowBandwidthModalComponent, "app-low-bandwidth-modal", never, {}, {}, never, never, true, never>; } declare class ImageLoadingSrcComponent { store: Store<any>; isLoaderScreenVisible: i0.Signal<boolean>; imageLoadingSrc: i0.Signal<string>; static ɵfac: i0.ɵɵFactoryDeclaration<ImageLoadingSrcComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<ImageLoadingSrcComponent, "app-image-loading-src", never, {}, {}, never, never, true, never>; } declare class StatGraphComponent implements AfterViewInit { private el; graph: ElementRef; private canvas; private ctx; readonly color: i0.InputSignal<string>; readonly tickStep: i0.InputSignal<number>; readonly label: i0.InputSignal<string>; private scaleY; set dataTick(data: { value: number; hash: number; } | null); private data; max: number; min: number; current: number; ngAfterViewInit(): void; resize(): void; private draw; private getColor; private pushData; static ɵfac: i0.ɵɵFactoryDeclaration<StatGraphComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<StatGraphComponent, "app-stat-graph", never, { "color": { "alias": "color"; "required": false; "isSignal": true; }; "tickStep": { "alias": "tickStep"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "dataTick": { "alias": "dataTick"; "required": false; }; }, {}, never, never, true, never>; } declare class UnrealSceneComponent { isStudio: i0.InputSignal<boolean>; useContainerAsSizeProvider: i0.InputSignal<boolean>; studioResolutionSize: i0.InputSignal<{ width: number; height: number; }>; studioResolutionValues: rxjs.Observable<{ width: number; height: number; }>; readonly videoElement: i0.Signal<ElementRef<HTMLDivElement> | undefined>; changeMouseOverScene: i0.OutputEmitterRef<boolean>; private width; private height; private store; private isExistMatchUrls; readonly isDevMode: boolean; readonly lightMode: i0.Signal<boolean>; private isFreezeFrameLoading; private commandsSender; private videoService; private element; private destroyRef; private get resizeValues(); private get pixelRatio(); onMouseOver(): void; onMouseOut(): void; constructor(); private listenResizeValues; private adaptVideo; /** * This method calculates the dimensions for resizing a layout in a configurator stream. * It takes into account the pixel ratio of the device's screen and the orientation of the layout. * The method uses the `fitIntoRectangle` function to calculate the dimensions that would allow the layout to fit into the maximum space while maintaining its aspect ratio. * It also sets the maximum limits for the width and height based on the layout's orientation. * If the scale of the fitted dimensions is less than 1, it assigns the fitted dimensions to the output. Otherwise, it sets the scale of the output to 1. * @returns {Area} An object of type `Area` that contains the calculated dimensions for resizing the layout. */ private getResizeValuesUniversal; private getResizeValues; private sendResize; private makeEven; static ɵfac: i0.ɵɵFactoryDeclaration<UnrealSceneComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<UnrealSceneComponent, "app-unreal-scene", never, { "isStudio": { "alias": "isStudio"; "required": false; "isSignal": true; }; "useContainerAsSizeProvider": { "alias": "useContainerAsSizeProvider"; "required": false; "isSignal": true; }; "studioResolutionSize": { "alias": "studioResolutionSize"; "required": false; "isSignal": true; }; }, { "changeMouseOverScene": "changeMouseOverScene"; }, never, ["app-pdf", "app-show-case", "app-low-bandwidth-detector"], true, never>; } declare class IntroSrcComponent { private videoElement; private store; protected imageIntroSrc: i0.Signal<string | null>; protected videoIntroSrc: i0.Signal<string | null>; private viewportReady; constructor(); private createVideo; static ɵfac: i0.ɵɵFactoryDeclaration<IntroSrcComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<IntroSrcComponent, "app-intro-src", never, {}, {}, never, never, true, never>; } declare class VideoStatsComponent implements OnInit { collapsed: boolean; private store; private videoService; private isDevMode; private obs$; viewportReady: i0.Signal<boolean | undefined>; ssInfo: i0.Signal<string | undefined>; fpsTick: i0.Signal<any>; fpsAvgTick: i0.Signal<any>; bitrateTick: i0.Signal<any>; videoQP: i0.Signal<any>; bitrateAverageTick: i0.Signal<any>; videoStatus: i0.Signal<{ key: string; value: any; }[] | undefined>; fields: string[]; graphList: any[]; graphList$: Observable<any>; private idKey; private elementsToShow; private trigger$; constructor(); ngOnInit(): void; updateGraph(): void; toggle(): void; toggleGraph($event: MouseEvent, el: string, value?: any): void; private getFields; private writeFields; static ɵfac: i0.ɵɵFactoryDeclaration<VideoStatsComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<VideoStatsComponent, "app-video-stats", never, {}, {}, never, never, true, never>; } declare class WebrtcErrorModalComponent { private dialogRef; private store; close(): void; closeModalWithCirrusDisconnect(): void; static ɵfac: i0.ɵɵFactoryDeclaration<WebrtcErrorModalComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<WebrtcErrorModalComponent, "app-webrtc-error-modal", never, {}, {}, never, never, true, never>; } declare const WSCloseCode_NORMAL_CLOSURE = 3000; declare const WSCloseCode_NORMAL_AFK_TIMEOUT = 3001; declare const WSCloseCode_NORMAL_MANUAL_DISCONNECT = 3002; declare const WSCloseCode_FORCE_CIRRUS_CLOSE = 3003; declare const WSCloseCode_UNKNOWN = 1000; declare const WSCloseCode_CIRRUS_PLAYER_DISCONNECTED = 1001; declare const WSCloseCode_CIRRUS_ABNORMAL_CLOSURE = 1006; declare const WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR = 1013; declare const WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER = 1011; declare const WSCloseCodes: readonly [3000, 3001, 3002, 3003, 1000, 1001, 1006, 1013, 1011]; type WSCloseCodesValues = (typeof WSCloseCodes)[number]; declare const DisconnectReason: { readonly Afk: "Afk"; readonly None: "None"; readonly Destroy: "Destroy"; readonly DataChannelClosed: "DataChannelClosed"; readonly DataChannelTimeout: "DataChannelTimeout"; readonly WebRTCError: "WebRTCError"; readonly WebSocketError: "WebSocketError"; readonly WebSocketClose: "WebSocketClose"; readonly DropConnection: "DropConnection"; readonly OrchestrationPlayerDisconnected: "OrchestrationPlayerDisconnected"; readonly OrchestrationStreamerDisconnected: "OrchestrationStreamerDisconnected"; }; type DisconnectReasonType = (typeof DisconnectReason)[keyof typeof DisconnectReason]; interface ConnectionError { reason: DisconnectReasonType; message: string; } interface CloseReason { code: WSCloseCodesValues; reason: DisconnectReasonType; } interface FreezeFrameMessage { dataUrl: string | null; progress: number | null; } interface UnrealInitialConfig { customErrorsEndpoint?: string; commandTelemetryReceiver?: string; regionsPingUrl?: string; screenLockerContainerId?: string; dataChannelConnectionTimeout?: number; playwright?: boolean; } declare const SpecialKeyCodes: { BackSpace: number; Shift: number; Control: number; Alt: number; RightShift: number; RightControl: number; RightAlt: number; }; declare const MouseButton: { MainButton: number; AuxiliaryButton: number; SecondaryButton: number; FourthButton: number; FifthButton: number; }; declare const MouseButtonsMask: { PrimaryButton: number; SecondaryButton: number; AuxiliaryButton: number; FourthButton: number; FifthButton: number; }; declare const EControlSchemeType: { readonly LockedMouse: 0; readonly HoveringMouse: 1; readonly Default: 2; }; type EControlSchemeTypeValues = (typeof EControlSchemeType)[keyof typeof EControlSchemeType]; declare const EMessageType: { readonly IFrameRequest: 0; readonly RequestQualityControl: 1; readonly MaxFpsRequest: 2; readonly AverageBitrateRequest: 3; readonly StartStreaming: 4; readonly StopStreaming: 5; readonly LatencyTest: 6; readonly RequestInitialSettings: 7; readonly UIInteraction: 50; readonly Command: 51; readonly KeyDown: 60; readonly KeyUp: 61; readonly KeyPress: 62; readonly MouseEnter: 70; readonly MouseLeave: 71; readonly MouseDown: 72; readonly MouseUp: 73; readonly MouseMove: 74; readonly MouseWheel: 75; readonly TouchStart: 80; readonly TouchEnd: 81; readonly TouchMove: 82; }; type EMessageTypeValues = (typeof EMessageType)[keyof typeof EMessageType]; declare const EToClientMessageType: { readonly QualityControlOwnership: 0; readonly Response: 1; readonly Command: 2; readonly FreezeFrame: 3; readonly UnfreezeFrame: 4; readonly VideoEncoderAvgQP: 5; readonly LatencyTest: 6; readonly InitialSettings: 7; readonly FileExtension: 8; readonly FileMimeType: 9; readonly FileContents: 10; readonly TestEcho: 11; readonly InputControlOwnership: 12; readonly GamepadResponse: 13; readonly Protocol: 255; }; declare const UNREAL_CONFIG: InjectionToken<UnrealInitialConfig>; declare const InputOptions: InputProps; declare const UnrealStatusMessage: { readonly CONNECTING_TO_SESSION: "Connecting to session."; readonly STARTING_YOUR_SESSION: "Starting your session"; }; declare const DEBOUNCE_TO_MANY_RESIZE_CALLS = 100; declare const SAME_SIZE_THRESHOLD = 1.01; declare const MINIMAL_FPS = 6; declare const STREAMING_VIDEO_ID = "streamingVideo"; declare const CONSOLE_COMMAND_ENABLE_MESSAGES = "EnableAllScreenMessages"; declare const CONSOLE_COMMAND_DISABLE_MESSAGES = "DisableAllScreenMessages"; declare const CONSOLE_COMMAND_PIXEL_QUALITY = "PixelStreaming.FreezeFrameQuality 95"; declare const FULL_HD_WIDTH = 1920; declare const FULL_HD_HEIGHT = 1080; declare const WS_TIMEOUT = 2000; declare const POLLING_TIME = 4000; declare const WS_OPEN_STATE = 1; declare const DEFAULT_AFK_TIMEOUT_PERIOD = 15; declare const DEFAULT_AFK_TIMEOUT = 120; declare const DATA_CHANNEL_CONNECTION_TIMEOUT = 8000; declare const SIGNALLING_PERCENT_VALUE = 56; declare const SCREEN_LOCKER_CONTAINER_ID = "3dsource_start_screen"; declare function provideAngularUnrealModule(config?: { playwright: boolean; }): i0.EnvironmentProviders; interface NormalizeAndQuantizeUnsignedValue { inRange: boolean; x: number; y: number; } interface UnquantizeAndDenormalizeUnsignedValue { x: number; y: number; } interface NormalizeAndQuantizeSignedValue { x: number; y: number; } interface InputProps { controlScheme: EControlSchemeTypeValues; suppressBrowserKeys: boolean; fakeMouseWithTouches: boolean; } declare class SubService { store: Store<any>; disconnect$: rxjs.Observable<false>; } declare class AFKService extends SubService { private enabled; private readonly closeTimeout; private active; private warnTimer; private countdown; private countdownTimer; private selectWarnTimeout; private isViewportReady; constructor(); protected init(): void; private hideOverlay; /** * Start a timer which when elapsed will warn the user they are inactive. */ private startAfkWarningTimer; /** * If the user interacts, then reset the warning timer. */ private resetAfkWarningTimer; /** * Update the count-down spans number for the overlay * @param countdown the count down number to be inserted into the span for updating */ private updateCountDown; /** * Update the text overlays inner text * @param message the update text to be inserted into the overlay */ private dispatchMessage; private clearTimers; private stop; private reset; private showAfkOverlay; static ɵfac: i0.ɵɵFactoryDeclaration<AFKService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<AFKService>; } declare class AggregatorService extends SubService { private readonly selectStreamConfig; private readonly videoService; private readonly webrtcPlayer; private readonly freezeFrame; private readonly fileReceiver; private readonly unrealInitialConfig; private readonly responseEventListeners; /** * Never called for now */ private readonly destroy$; constructor(); protected init(): void; protected listenWebRTC(): void; protected initialize(): void; private addResponseEventListener; private showOnScreenKeyboard; private removeLoadScreen; private startListenCallbacks; private showMessageFromUnreal; private resetResponseList; private dataChannelMessageHandler; static ɵfac: i0.ɵɵFactoryDeclaration<AggregatorService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<AggregatorService>; } declare class CommandTelemetryService { private readonly appId; private commandsSent; private exileTimeout; private pollingTime; private commandSequenceNumber; /** * The time the telemetry service was started. * Initialized at a moment when connectToSignaling() was called. * @private */ private startTime; private lastTime; private uuid; private viewId; private sessionId; private userId; private payloads; private readonly httpClient; private readonly unrealInitialConfig; constructor(); protected init(): void; private get timeNow(); private get sessionTime(); private get canSkipSending(); decorate(funcToDecorate: IToBeDecorated): (data: any) => void; protected start(): void; private reset; private trackStartCommand; private trackStopCommand; private pushStatToBuffer; private trackTime; private send; /** * Listens for Unreal Engine callbacks. * Subscribes to the Unreal Engine event loop back and filters out events that do not have a tracking ID. * When a callback with a tracking ID is received, * it stops tracking the time for that command and filters out commands * that have exceeded the timeout limit. */ protected listenCallbacks(): void; private pushData; /** * Removes commands that have exceeded the timeout limit. * Iterates over all the commands sent and checks if the difference between the current time * and the time the command was sent is greater than the timeout limit. * If it is, the command is marked for deletion. * After checking all commands, those marked for deletion are removed from the commands sent. * This method is used to ensure that commands that are not responded to within a certain time frame * do not remain in the commandsSent object indefinitely, which could lead to memory leaks over time. */ private removeExileCommands; /** * Wraps the provided function with telemetry tracking. * Generates a unique tracking ID and adds it to the data object. * Pushes the command sent to the payloads with the tracking ID. * Starts tracking the time for the command. * Finally, calls the provided function with the modified data object. * * @param {IToBeDecorated} funcToDecorate - The function to be decorated with telemetry tracking. * @param {any} data - The data object to be passed to the function. It will be augmented with a unique tracking ID. */ private wrapper; static ɵfac: i0.ɵɵFactoryDeclaration<CommandTelemetryService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<CommandTelemetryService>; } type IToBeDecorated = (data: any) => unknown; declare function TelemetryStart(externalId: string): void; declare function TelemetryStop(externalId: string, payload?: any): void; declare function ResetTelemetry(): void; declare class ConsoleExtensionsService extends SubService { #private; constructor(); protected init(): void; private unrealHelp; static ɵfac: i0.ɵɵFactoryDeclaration<ConsoleExtensionsService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<ConsoleExtensionsService>; } declare class DevModeService { get isDevMode(): boolean; setDevMode(value: boolean): void; static ɵfac: i0.ɵɵFactoryDeclaration<DevModeService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<DevModeService>; } declare class FreezeFrameService extends SubService { receiving: boolean; private size; private jpeg; private freezeFrameOverlay; constructor(); protected init(): void; setData(view: Uint8Array): void; private dispatchInProgress; start(view: Uint8Array): void; invalidate(): void; private showFreezeFrame; static ɵfac: i0.ɵɵFactoryDeclaration<FreezeFrameService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<FreezeFrameService>; } declare class InputService extends SubService { private commandsSender; private isDevMode; private videoService; readonly defaultKeys: (17 | 37 | 38 | 39 | 40 | 46 | 65 | 68 | 83 | 87 | 107 | 109 | 187 | 189)[]; private availableKeys; private options; private reInit$; private deactivatedVideoTrigger$; private normalizeAndQuantizeUnsigned; private unQuantizeAndDenormalizeUnsigned; private normalizeAndQuantizeSigned; videoBoundingRect: DOMRect; fingerIds: Map<any, any>; maxByteValue: number; fingers: number[]; private offsetParams; constructor(); protected init(): void; useKeyboardKeys(keys: IKeyCode[]): void; get video(): HTMLVideoElement | null; private setup; /** * We use `object-fit: cover` on the video element. Since the video can have * a different aspect ratio from its container (and potentially be larger), * we need to calculate offsets and scale factors to map container (e.g., mouse) * coordinates back to the actual video coordinates. * * @param videoElement The video element whose scaling and positioning we need * @returns Object containing offset and scale info for coordinate normalization * @private */ private getObjectFitOffset; private setupNormalizeAndQuantize; private sendInputData; private registerInputs; private getTouchPositionWithOffset; private getMousePositionWithOffset; private registerTouchEvents; focusWindow(): void; emitMouseMove(x: number, y: number, deltaX: number, deltaY: number): void; emitMouseDown(button: number, x: number, y: number): void; emitMouseUp(button: number, x: number, y: number): void; emitMouseWheel(delta: number, x: number, y: number): void; private releaseMouseButtons; private pressMouseButtons; private registerHoveringMouseEvents; private registerMouseEnterAndLeaveEvents; private isKeyCodeBrowserKey; private getKeyCode; private registerKeyboardEvents; private startListenKeys; } declare class RegionsPingService { private httpClient; private unrealInitialConfig; config: { ping_count: number; ping_timeout: number; max_parallel_requests: number; bust_cache: boolean; }; constructor(); getFastest(regionListUrl?: string): Observable<string | undefined>; getPingResult(providers: ProvidersData): Observable<PingResult | null>; getProviders(regionList?: string): Observable<ProvidersData>; private startPinging; private checkLatency; private fetchWithTimeout; static ɵfac: i0.ɵɵFactoryDeclaration<RegionsPingService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<RegionsPingService>; } interface ProvidersData { timeout?: number; regions: Region[]; } interface Region { region_code: string; url: string; timeout?: number; } interface PingResult { region_code: string | undefined; result: number[]; } declare class SignallingService extends SubService { private readonly action$; private readonly httpClient; private readonly regionsPingService; readonly region: i0.WritableSignal<string>; readonly selectClientAndViewIds: i0.Signal<{ clientId: string | null; viewId: string | null; }>; readonly environmentId: i0.Signal<string | null>; readonly streamRequestContext: i0.Signal<_3dsource_angular_unreal_module.StreamRequestContext | null>; onOffer$: Subject<RTCSessionDescriptionInit>; onConfig$: Subject<ConfigMessage>; onWebRtcIce$: Subject<RTCIceCandidate>; onWebRtcAnswer$: Subject<RTCSessionDescriptionInit | null>; abort$: Observable<_ngrx_store.Action<string>>; private ws; private wsMsgHandlers; protected correlationId: string; constructor(); protected init(): void; connectToSignaling(urlList: string[]): Observable<WebSocket>; protected startEstablishingConnection(): void; private adaptUrlsToRegion; /** * Resolves an active AWS *signaling* instance and returns a WebSocket endpoint. * * The observable produced by this method is **cold** and executes inside a `defer`, * so each subscription (including those triggered by `retry`) pulls the **next** * URL candidate from a generator created by `getActiveUrl(urlsPool)`. * * ### Execution flow * * 1. **Telemetry** — Starts a `getSignaling` span for end-to-end timing. * 2. **Candidate URL selection** — A stateful generator (`urlGen`) is created * from `urlsPool`. Each resubscription (e.g. via `retry`) advances to the next URL. * 3. **Short-circuit for WS URLs** — If the picked candidate already matches * `ws://` or `wss://`, emit `{ wsUrl, pollingUrl: null, instanceName: null }` * immediately and complete (no HTTP request). * 4. **Await client/view identifiers** — `this.store.select(selectClientAndViewIds)` * is tapped for logging (missing IDs) and then filtered to require both `clientId` * and `viewId` to be truthy. * 5. **Single in-flight HTTP orchestration call** — Uses `exhaustMap` to issue * `GET {signalingUrl}{clientId}/{viewId}`. New `{clientId, viewId}` emissions * while the request is in flight are **ignored** until completion, preventing overlap. * 6. **Per-attempt timeout** — `timeout(WS_TIMEOUT)` caps how long we wait for a response. * On timeout, the attempt errors and the outer `retry` schedules the next URL. * 7. **Response validation & progress reporting** — A `filter`: * - Calls `TelemetryStop('getSignaling', { ...data, multi: true })` on receipt. * - If `data.signallingServer === ''` or `data.error`: * shows a status message, optionally dispatches `setStatusPercentSignallingServer` * with `data.info.percent`, and **throws** to fail the attempt (triggers `retry`). * 8. **Mapping to `AwsInstance`** — Converts the validated orchestration payload into: * - `wsUrl`: via `httpUrlToWs(\`\${location.protocol}//\${data.signallingServer}\`)` * - `pollingUrl`: the base `signalingUrl` that succeeded * - `instanceName`: the (validated) `data.signallingServer` * 9. **Retry policy** — On *any* upstream error (timeout, HTTP error, invalid payload), * `retry({ delay })`: * - Shows a “connecting” status, * - Logs the attempt number, * - Waits `WS_TIMEOUT` ms (via `timer`) and **resubscribes**, advancing `urlGen`. * * ### Concurrency semantics * * - `exhaustMap` guarantees a **single** HTTP request per attempt; subsequent * `{clientId, viewId}` emissions are ignored until the current request completes. * * ### Telemetry semantics * * - `TelemetryStart('getSignaling')` begins before work. * - `TelemetryStop('getSignaling', {...})` runs on receipt of an orchestration response. * If an attempt fails (e.g., timeout), stopping the span is the responsibility of * your telemetry layer or a `finalize` elsewhere if desired. * * ### Error & retry semantics * * - Missing/never-emitted IDs → timeout → retry with next URL. * - HTTP/network error → retry with next URL. * - Invalid orchestration payload (`error` set or empty `signallingServer`) → throw in * validation filter → retry with next URL. * - Short-circuit WS path **does not** retry (emits once, completes). * * @param urlsPool - Ordered list of base URLs to probe. Retries advance through this list * until a working signaling server is found. A candidate may also be a direct `ws://`/`wss://` * URL to short-circuit HTTP orchestration. * * @returns Observable that emits exactly one {@link AwsInstance} on success and then completes. * On failure, the stream errors; the built-in `retry` operator re-subscribes after `WS_TIMEOUT` * and advances to the next URL candidate. * * @throws Emits an error within the observable chain (not a thrown synchronous exception) when: * - The HTTP request fails or times out. * - The orchestration response indicates an error or an empty `signallingServer`. * - Any other operator in the chain surfaces an error. * * @remarks * - The URL generator (`urlGen`) is created **outside** `defer`, so resubscriptions * advance the pool. Creating it inside `defer` would restart from the first URL each retry. * - `location.protocol` is used to derive `ws` vs `wss`. If this may run in non-browser * contexts (e.g., SSR), guard or abstract this logic. * - Consider capping retries with `count` in `retry({ count, delay })` when appropriate. * * @example * ```ts * getAwsInstance(['https://signaling.example.com/', 'wss://direct.example.com']) * .subscribe({ * next: ({ wsUrl }) => connect(wsUrl), * error: (e) => console.error('Unable to establish signaling:', e), * }); * ``` * * @see httpUrlToWs * @see selectClientAndViewIds * @see setStatusPercentSignallingServer */ private getAwsInstance; private connectToCirrus; addWsHandlers(ws: WebSocket): void; showStatusMessage(statusMessage: string | null): void; /** * Close the connection with the signaling server * @param data */ close(data: CloseReason): void; send(data: AnySignalingMessage): void; private clearWs; protected handleMessage(msg: MessageBase): void; private setHandlersFromStream; protected sendRequestStream(): void; private getRegion; static ɵfac: i0.ɵɵFactoryDeclaration<SignallingService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<SignallingService>; } declare class StreamStatusTelemetryService { #private; constructor(); protected init(): void; private mapEventData; private trackEventToMixPanel; static ɵfac: i0.ɵɵFactoryDeclaration<StreamStatusTelemetryService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<StreamStatusTelemetryService>; } declare class UnrealCommunicatorService { private store; private commandTelemetryService; private freezeFrameService; private webRtcPlayerService; private videoService; private destroy$; private cirrusConnected; constructor(); protected init(): void; destroy(): void; sendCommandToUnreal(data: MetaBoxCommandPacket): void; emitUIInteraction(descriptor: MetaBoxCommandPacket): void; /** A build-in command can be sent to the UE4 client. The commands are defined by a JSON descriptor and will be executed automatically. The currently supported commands are: 1. A command to run any console command: "{ ConsoleCommand: <string> }" 2. A command to change the resolution to the given width and height. "{ Resolution.Width: <value>, Resolution.Height: <value> }" */ emitCommand(descriptor: MetaBoxCommandPacket): void; sendInputData(data: ArrayBuffer): void; private emitDescriptor; private requestInitialSettings; private requestQualityControl; protected listenVideo(): void; private prepareScreen; private showPlayOverlay; static ɵfac: i0.ɵɵFactoryDeclaration<UnrealCommunicatorService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<UnrealCommunicatorService>; } declare class VideoService extends SubService { video: HTMLVideoElement | null; audio: HTMLAudioElement | null; private container; private latencyTestTimings; private videoTrack$; private VideoEncoderQP; private aggregatedStats; private kalmanFilter1D; /** * Aggregate video stats and emit it as videoStats$ */ videoStats$: rxjs.Observable<IAggregatedStat>; constructor(); protected init(): void; setContainer(container?: HTMLDivElement | null): void; setLatencyTimings(latencyTimings: string): void; setEncoder(data: any): void; create(): void; attachVideoStream(stream: MediaStream, pcClient: RTCPeerConnection): void; attachAudioStream(stream: MediaStream): void; play(): void; safePlay(video: HTMLVideoElement | null): Promise<void>; private getStats; private generateAggregatedStatsFunction; private onAggregatedStats; private destroy; private createWebRtcVideo; private createWebRtcAudio; private playAudio; static ɵfac: i0.ɵɵFactoryDeclaration<VideoService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<VideoService>; } declare class WebRtcPlayerService extends SubService { onDataChannelMessage$: Subject<ArrayBuffer>; private pcClient; private signallingSrv; private videoService; private cfg; private useMic; private forceTURN; private forceMonoAudio; private dcClient; constructor(); protected init(): void; private createWebRtcOffer; private createDataChannel; private receiveAnswer; private handleCandidateFromServer; private mungeSDP; /** * Closes existing PeerConnection */ closePC(): void; canSend(): boolean | null; send(data: ArrayBuffer): void; private setConfig; private createPeerConnection; private handlePeerConnectionEvents; private setupTransceiversAsync; private setupDataChannelCallbacks; private onDataChannelConnected; private createOffer; static ɵfac: i0.ɵɵFactoryDeclaration<WebRtcPlayerService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<WebRtcPlayerService>; } declare class AfkPlaywrightService extends AFKService { init(): void; static ɵfac: i0.ɵɵFactoryDeclaration<AfkPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<AfkPlaywrightService>; } declare class SignallingPlaywrightService extends SignallingService { constructor(); init(): void; connectToSignaling(): rxjs.Observable<never>; static ɵfac: i0.ɵɵFactoryDeclaration<SignallingPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<SignallingPlaywrightService>; } declare class UnrealCommunicatorPlaywrightService extends UnrealCommunicatorService { init(): void; sendCommandToUnreal(): void; sendInputData(): void; listenVideo(): void; static ɵfac: i0.ɵɵFactoryDeclaration<UnrealCommunicatorPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<UnrealCommunicatorPlaywrightService>; } declare class AggregatorPlaywrightService extends AggregatorService { init(): void; static ɵfac: i0.ɵɵFactoryDeclaration<AggregatorPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<AggregatorPlaywrightService>; } declare class FreezeFramePlaywrightService extends FreezeFrameService { init(): void; static ɵfac: i0.ɵɵFactoryDeclaration<FreezeFramePlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<FreezeFramePlaywrightService>; } declare class CommandTelemetryPlaywrightService extends CommandTelemetryService { init(): void; static ɵfac: i0.ɵɵFactoryDeclaration<CommandTelemetryPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<CommandTelemetryPlaywrightService>; } declare class StreamStatusTelemetryPlaywrightService extends StreamStatusTelemetryService { init(): void; static ɵfac: i0.ɵɵFactoryDeclaration<StreamStatusTelemetryPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<StreamStatusTelemetryPlaywrightService>; } declare class ConsoleExtensionsPlaywrightService extends ConsoleExtensionsService { init(): void; static ɵfac: i0.ɵɵFactoryDeclaration<ConsoleExtensionsPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<ConsoleExtensionsPlaywrightService>; } declare const ReceivedMimeTypes: { readonly ApplicationJson: "application/json"; }; type ReceivedMimeType = (typeof ReceivedMimeTypes)[keyof typeof ReceivedMimeTypes]; declare class FileReceiverService extends SubService { fileComplete$: Subject<ReceivedFile>; private valid; private chunks; private mimetype; private receiving; private extension; private timestampStart; private data; constructor(); protected init(): void; reset(): void; private resetOnStart; /** * Processes a file extension when received over data channel * @param view - the file extension data */ setExtensionFromBytes(view: Uint8Array): void; /** * Processes a file mime type when received over data channel * @param view - the file mime type data */ setMimeTypeFromBytes(view: Uint8Array): void; setContentsFromBytes(view: Uint8Array): void; } interface ReceivedFile { blob: Blob; mimetype: ReceivedMimeType; extension: string; valid: boolean; } declare class FileReceiverPlaywrightService extends FileReceiverService { init(): void; } declare class InputPlaywrightService extends InputService { init(): void; static ɵfac: i0.ɵɵFactoryDeclaration<InputPlaywrightService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<InputPlaywrightService>; } declare class FileHandlerService { private fileService; private fileHandlers; private handleJsonFile; observeFileResponse<K extends keyof MetaBoxCommandList, T extends MetaBoxCommandList[K] = MetaBoxCommandList[K]>(mimetype: ReceivedMimeType, data: T, sender: (data: T) => void, timeOut?: number): Observable<{ commandCallback: ObservedCallbackResponse<T>; } | never>; static ɵfac: i0.ɵɵFactoryDeclaration<FileHandlerService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<FileHandlerService>; } declare function AnswerHandler(this: SignallingService, msg: RTCSessionDescriptionInit): void; declare function ConfigHandler(this: SignallingService, msg: ConfigMessage): void; declare function IceCandidateHandler(this: SignallingService, msg: { candidate: RTCIceCandidate; }): void; declare function InstanceReadyHandler(this: SignallingService): void; declare function InstanceReservedHandler(this: SignallingService, msg: InstanceReserved): void; declare function PingHandler(this: SignallingService): void; declare function PlayerCountHandler(this: SignallingService, msg: PlayerCountMessage): void; declare function SSInfoHandler(this: SignallingService, msg: SSInfo): null; declare function OnCloseHandler(this: SignallingService, e: CloseEvent): void; declare function OnErrorHandler(this: SignallingService, e: Event): void; declare function OnMessageHandler(this: SignallingService, e: MessageEvent<string | Blob>): void; declare function OnOpenHandler(this: SignallingService): void; /** * Keeps the max of numbers seen so far; resets to 0 whenever `reset$` emits. * Emits `0` immediately on reset. */ declare const keepMaxUntilReset: (reset$: Observable<unknown>) => ((source: Observable<number>) => Observable<number>); declare function observeCommandResponse<K extends keyof MetaBoxCommandList, T extends MetaBoxCommandList[K] = MetaBoxCommandList[K]>(data: T, sender: (data: T) => void, timeOut?: number, dispatchOnTimeout?: boolean): Observable<ObservedCallbackResponse<T> | never>; interface ObservedCallbackResponse<T extends MetaBoxCommandPacket> { json: { commandCallback: T; }; } declare function decodeData(anyData: any): string; declare const dispatchResize: () => void; declare const forceResizeUnrealVideo: () => void; declare function getRtcErrorMessage(code: number | null): string | undefined; type Descriptor = MetaBoxCommandList & SignalDescriptor; /** * UnrealInternalSignalEvents commands list wrapper listener * @param event */ declare function fromSignal<K extends keyof Descriptor>(event: K): Observable<Descriptor[K]>; type ArgumentType<K extends keyof Descriptor> = Descriptor[K] extends void ? never : Descriptor[K]; /** * UnrealInternalSignalEvents commands list wrapper sender * @param event * @param args */ declare function sendSignal<K extends keyof Descriptor>(event: K, ...args: ArgumentType<K> extends never ? [] : [ArgumentType<K>]): void; declare function fromUnrealCallBackSignal<K extends keyof Descriptor>(command: K): Observable<Descriptor[K]>; declare const floatToSmoothPercents: () => ((source: Observable<number>) => Observable<number>); /** * Creates an observable that emits values transitioning smoothly from the start value to the end value over a specified duration. * The transition is performed using linear interpolation (lerp) and clamped to the range [0, 1]. * * @param {number} start - The starting value of the transition. * @param {number} end - The ending value of the transition. * @param {number} duration - The duration of the transition in milliseconds. * @returns {Observable<number>} An observable that emits the interpolated values from start to end over the specified duration. */ declare const smoothTransition: (start: number, end: number, duration: number) => Observable<number>; declare const getImageFromVideoStream: (takeSizeFrom?: "video" | "constant", imageOutput?: ImageOutputValues, sizes?: StreamResolutionProps) => string | null; declare function getActiveUrl(urls: string[]): Generator<string, void, unknown>; declare class KalmanFilter1D { private estimate; private uncertainty; private processNoise; private measurementNoise; /** * @param initialEstimate Initial guess of the state. * @param initialUncertainty Initial uncertainty in the guess. * @param processNoise Process variance (Q) representing model uncertainty. * @param measurementNoise Measurement variance (R) representing noise in measurements. */ constructor(initialEstimate: number, initialUncertainty: number, processNoise: number, measurementNoise: number); /** * Incorporates a new measurement and returns the updated estimate. * @param measurement The new measurement value. */ update(measurement: number): number; config(data: FilterSettings): void; } declare class LatencyTimings { TestStartTimeMs: number | null; UEReceiptTimeMs: number | null; UEEncodeMs: number | null; UECaptureToSendMs: number | null; UETransmissionTimeMs: number | null; BrowserReceiptTimeMs: number | null; FrameDisplayDeltaTimeMs: number | null; Reset(): void; SetUETimings(UETimings: any): void; SetFrameDisplayDeltaTime(DeltaTimeMs: number): void; OnAllLatencyTimingsReady(_: any): void; } declare function mapQpToQuality(VideoEncoderQP: number): Quality; declare const trackMixpanelEvent: _ngrx_store.ActionCreator<string, (props: { event: string; data?: unknown; }) => { event: string; data?: unknown; } & _ngrx_store.Action<string>>; declare const changeLowBandwidth: _ngrx_store.ActionCreator<string, (props: { lowBandwidth: boolean; stats?: LBMStats; }) => { lowBandwidth: boolean; stats?: LBMStats; } & _ngrx_store.Action<string>>; declare const setMaxFps: _ngrx_store.ActionCreator<string, (props: { maxFps: number; }) => { maxFps: number; } & _ngrx_store.Action<string>>; declare const destroyRemoteConnections: _ngrx_store.ActionCreator<string, (props: { reason: DisconnectReasonType; }) => { reason: DisconnectReasonType; } & _ngrx_store.Action<string>>; declare const destroyUnrealScene: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setCirrusConnected: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setCirrusDisconnected: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const changeStatusMainVideoOnScene: _ngrx_store.ActionCreator<string, (props: { isVideoPlaying: boolean; }) => { isVideoPlaying: boolean; } & _ngrx_store.Action<string>>; declare const setAwsInstance: _ngrx_store.ActionCreator<string, (props: { wsUrl: string | null; pollingUrl: string | null; instanceName: string | null; }) => { wsUrl: string | null; pollingUrl: string | null; instanceName: string | null; } & _ngrx_store.Action<string>>; declare const setStatusMessage: _ngrx_store.ActionCreator<string, (props: { statusMessage: string | null; }) => { statusMessage: string | null; } & _ngrx_store.Action<string>>; declare const setStatusPercentSignallingServer: _ngrx_store.ActionCreator<string, (props: { percent: number | null; }) => { percent: number | null; } & _ngrx_store.Action<string>>; declare const setFreezeFrame: _ngrx_store.ActionCreator<string, (props: { dataUrl: string | null; progress: number | null; }) => { dataUrl: string | null; progress: number | null; } & _ngrx_store.Action<string>>; declare const setStreamClientCompanyId: _ngrx_store.ActionCreator<string, (props: { id: string; }) => { id: string; } & _ngrx_store.Action<string>>; declare const setStreamViewId: _ngrx_store.ActionCreator<string, (props: { id: string; }) => { id: string; } & _ngrx_store.Action<string>>; declare const setIntroImageSrc: _ngrx_store.ActionCreator<string, (props: { src: string; }) => { src: string; } & _ngrx_store.Action<string>>; declare const setLoadingImageSrc: _ngrx_store.ActionCreator<string, (props: { src: string; }) => { src: string; } & _ngrx_store.Action<string>>; declare const setIntroVideoSrc: _ngrx_store.ActionCreator<string, (props: { src: string; }) => { src: string; } & _ngrx_store.Action<string>>; declare const resetIntroSrc: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setFreezeFrameFromVideo: _ngrx_store.ActionCreator<string, (props: { dataUrl: string | null; progress: number | null; }) => { dataUrl: string | null; progress: number | null; } & _ngrx_store.Action<string>>; declare const setEstablishingConnection: _ngrx_store.ActionCreator<string, (props: { value: boolean; }) => { value: boolean; } & _ngrx_store.Action<string>>; declare const setDataChannelConnected: _ngrx_store.ActionCreator<string, (props: { statusMessage: string; }) => { statusMessage: string; } & _ngrx_store.Action<string>>; declare const setConfig: _ngrx_store.ActionCreator<string, (props: { config: Partial<StreamConfig>; }) => { config: Partial<StreamConfig>; } & _ngrx_store.Action<string>>; declare const disconnectStream: _ngrx_store.ActionCreator<string, (props: { reason: DisconnectReasonType; message: string; }) => { reason: DisconnectReasonType; message: string; } & _ngrx_store.Action<string>>; declare const dropConnection: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setViewportReady: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setViewportNotReady: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const changeStreamResolutionAction: _ngrx_store.ActionCreator<string, (props: { width: number | null; height: number | null; }) => { width: number | null; height: number | null; } & _ngrx_store.Action<string>>; declare const changeStreamResolutionSuccessAction: _ngrx_store.ActionCreator<string, (props: { width: number | null; height: number | null; }) => { width: number | null; height: number | null; } & _ngrx_store.Action<string>>; declare const setSignalingName: _ngrx_store.ActionCreator<string, (props: { instanceName: string; }) => { instanceName: string; } & _ngrx_store.Action<string>>; declare const setOrchestrationParameters: _ngrx_store.ActionCreator<string, (props: { instanceName: string; streamRequestId: string; eta: number; }) => { instanceName: string; streamRequestId: string; eta: number; } & _ngrx_store.Action<string>>; declare const setOrchestrationMessage: _ngrx_store.ActionCreator<string, (props: { message: string; }) => { message: string; } & _ngrx_store.Action<string>>; declare const setOrchestrationProgress: _ngrx_store.ActionCreator<string, (props: { progressComplete: number; }) => { progressComplete: number; } & _ngrx_store.Action<string>>; declare const setOrchestrationContext: _ngrx_store.ActionCreator<string, (props: { urls: string[]; environmentId: string; streamRequestContext: StreamRequestContext; }) => { urls: string[]; environmentId: string; streamRequestContext: StreamRequestContext; } & _ngrx_store.Action<string>>; declare const updateCirrusInfo: _ngrx_store.ActionCreator<string, (props: { ssInfo: string; ssData: SignalingData; }) => { ssInfo: string; ssData: SignalingData; } & _ngrx_store.Action<string>>; declare const commandStarted: _ngrx_store.ActionCreator<string, (props: { id: string; command: string; }) => { id: string; command: string; } & _ngrx_store.Action<string>>; declare const commandCompleted: _ngrx_store.ActionCreator<string, (props: { id: string; }) => { id: string; } & _ngrx_store.Action<string>>; declare const setLoopBackCommandIsCompleted: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setAfkTimerVisible: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setAfkTimerHide: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const showUnrealErrorMessage: _ngrx_store.ActionCreator<string, (props: { code: number | null; error?: string; }) => { code: number | null; error?: string; } & _ngrx_store.Action<string>>; declare const initSignalling: _ngrx_store.FunctionWithParametersType<[data?: { resetDisconnectionReason: boolean; } | undefined], { resetDisconnectionReason: boolean; } & _ngrx_store.Action<string>> & _ngrx_store.Action<string>; declare const startStream: _ngrx_store.ActionCreator<string, (props: { config: Partial<StreamConfig>; }) => { config: Partial<StreamConfig>; } & _ngrx_store.Action<string>>; declare const resetConfig: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const resetAfkAction: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const resetWarnTimeout: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const abortEstablishingConnection: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare const setUnrealPlaywrightConfig: _ngrx_store.ActionCreator<string, () => _ngrx_store.Action<string>>; declare class UnrealEffects { private actions$; private dialog; private http; private store; private isDevMode; private scrollStrategy; private unrealInitialConfig; private webRtcPlayerService; private commandsSender; private signallingService; private videoService; private dataChannelConnectionTimeout; private connectionCompl