@3dsource/angular-unreal-module 0.0.93 → 0.0.94

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3dsource/angular-unreal-module",
3
- "version": "0.0.93",
3
+ "version": "0.0.94",
4
4
  "description": "Angular Unreal module for connect with unreal engine stream",
5
5
  "keywords": [
6
6
  "3dsource",
@@ -1031,6 +1031,182 @@ declare class AnalyticsService {
1031
1031
  static ɵprov: i0.ɵɵInjectableDeclaration<AnalyticsService>;
1032
1032
  }
1033
1033
 
1034
+ /**
1035
+ * Adaptive FPS controller that monitors the incoming WebRTC video stream
1036
+ * quality and dynamically adjusts Unreal Engine's `t.MaxFPS` console variable.
1037
+ *
1038
+ * ## How it works
1039
+ *
1040
+ * The service subscribes to `VideoService.videoStats$` (emitted every 250 ms)
1041
+ * and collects samples of FPS, bitrate, and QP (Quantisation Parameter).
1042
+ * Every {@link SAMPLE_WINDOW} ticks (~2 s) it averages the collected samples
1043
+ * and feeds them into a set of **fuzzy-logic membership functions** that
1044
+ * classify each metric into overlapping quality bands.
1045
+ *
1046
+ * ### Input signals
1047
+ *
1048
+ * **1. FPS ratio** = `actualFPS / currentTargetFPS` (0..1+)
1049
+ *
1050
+ * | Band | Range | Meaning |
1051
+ * |--------|---------------------|-----------------------------------------------|
1052
+ * | low | ratio < 0.7 → 1.0, linear ramp 0.7..0.9 → 0 | Stream cannot keep up with the target |
1053
+ * | ok | triangle 0.8..1.0, peak at 0.95 | Stream roughly matches the target |
1054
+ * | high | ratio 0.9..1.0 → ramp, >1.0 → 1.0 | Stream meets or exceeds the target |
1055
+ *
1056
+ * **2. Bitrate load** = `currentBitrate / MAX_BITRATE` (0..1+)
1057
+ *
1058
+ * `MAX_BITRATE` = 20 Mbit/s — the reference ceiling for the encoder.
1059
+ *
1060
+ * | Band | Range | Meaning |
1061
+ * |--------|-------------------------------------------------|-----------------------------------------------|
1062
+ * | high | load 0.5..0.8 → ramp, >0.8 → 1.0 | Encoder is using most of the available bandwidth |
1063
+ * | not high | load < 0.5 → 0.0 | Bandwidth headroom is available |
1064
+ *
1065
+ * **3. Quality** — mapped from QP via `mapQpToQuality()` (see {@link Quality}):
1066
+ *
1067
+ * | Quality | QP range | Meaning |
1068
+ * |----------|-----------|-------------------------------------------------|
1069
+ * | `lime` | QP <= 26 | Good — encoder has enough headroom |
1070
+ * | `orange` | QP 27..35 | Fair — encoder is under moderate pressure |
1071
+ * | `red` | QP > 35 | Poor — heavy compression, visible artefacts |
1072
+ *
1073
+ * ### Decision rules (evaluated in priority order, first match wins)
1074
+ *
1075
+ * | # | Condition | Decision |
1076
+ * |---|------------------------------------------------------------|--------------|
1077
+ * | 1 | FPS ratio is **low** (membership > 0.5) | **decrease** |
1078
+ * | 2 | FPS ratio is **ok** AND quality is `red` | **decrease** |
1079
+ * | 3 | FPS ratio is **ok** AND bitrate **high** AND quality is `orange` | **hold** |
1080
+ * | 4 | FPS ratio is **high** AND quality is `lime` AND bitrate **not high** | **increase** |
1081
+ * | — | Everything else | **hold** |
1082
+ *
1083
+ * ## Cooldown-based throttling
1084
+ *
1085
+ * The service continuously evaluates fuzzy rules every sample window.
1086
+ * After each FPS step change it enforces a cooldown before the next
1087
+ * change can be applied. The cooldown duration depends on the
1088
+ * (previous decision → next decision) pair:
1089
+ *
1090
+ * | Previous | Next | Cooldown |
1091
+ * |-----------|-----------|-----------------------------------------------------|
1092
+ * | decrease | decrease | {@link COOLDOWN_DECREASE_AFTER_DECREASE_MS} (2 s) |
1093
+ * | decrease | increase | {@link COOLDOWN_INCREASE_AFTER_DECREASE_MS} (10 s) |
1094
+ * | increase | decrease | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
1095
+ * | increase | increase | {@link COOLDOWN_AFTER_INCREASE_MS} (2 s) |
1096
+ *
1097
+ * This means the system reacts quickly after an increase (2 s in any
1098
+ * direction) but is cautious about stepping back up after a decrease
1099
+ * (10 s), while still allowing consecutive decreases at 2 s intervals.
1100
+ *
1101
+ * ## FPS dispatch
1102
+ *
1103
+ * FPS changes are dispatched via the NgRx `setMaxFps` action, which triggers
1104
+ * the existing `UnrealEffects.setMaxFps$` effect that sends the
1105
+ * `t.MaxFPS <value>` console command to Unreal Engine.
1106
+ */
1107
+ declare class FpsMonitorService {
1108
+ private videoService;
1109
+ private store;
1110
+ /** Discrete FPS targets the controller can switch between (ascending order). */
1111
+ private readonly FPS_STEPS;
1112
+ /** Reference ceiling for bitrate (bits/sec) used to normalise bitrate load to 0..1. */
1113
+ private readonly MAX_BITRATE;
1114
+ /**
1115
+ * Cooldown (ms) for any decision (increase or decrease) following an increase.
1116
+ * After an increase the system should react faster.
1117
+ */
1118
+ private readonly COOLDOWN_AFTER_INCREASE_MS;
1119
+ /**
1120
+ * Cooldown (ms) for a decrease following a previous decrease.
1121
+ */
1122
+ private readonly COOLDOWN_DECREASE_AFTER_DECREASE_MS;
1123
+ /**
1124
+ * Cooldown (ms) for an increase following a previous decrease.
1125
+ * The stream needs more time to stabilise before stepping back up.
1126
+ */
1127
+ private readonly COOLDOWN_INCREASE_AFTER_DECREASE_MS;
1128
+ /**
1129
+ * Number of videoStats$ ticks to accumulate before evaluating.
1130
+ * At 250 ms per tick this gives a ~2 s sliding evaluation window,
1131
+ * long enough to smooth out single-frame jitter.
1132
+ */
1133
+ private readonly SAMPLE_WINDOW;
1134
+ /** Current FPS target; starts at max (60 FPS) and adapts downward/upward. */
1135
+ private currentFpsTarget;
1136
+ private samples;
1137
+ private lastDecisionTime;
1138
+ private lastUpgrade;
1139
+ constructor();
1140
+ protected init(): void;
1141
+ /**
1142
+ * Called on every videoStats$ emission (~250 ms).
1143
+ * Accumulates samples and evaluates once per SAMPLE_WINDOW.
1144
+ */
1145
+ private processTick;
1146
+ private handleMonitoring;
1147
+ /**
1148
+ * Combines fuzzy membership values into a single discrete decision.
1149
+ * Rules are evaluated in priority order — first match wins.
1150
+ *
1151
+ * Inputs:
1152
+ * - `fpsRatio` = avgFPS / currentTargetFPS (e.g. 45/60 = 0.75)
1153
+ * - `bitrateLoad` = avgBitrate / 20 Mbit/s (e.g. 12M/20M = 0.6)
1154
+ * - `quality` = mapQpToQuality(avgQP) → 'lime' | 'orange' | 'red'
1155
+ */
1156
+ private evaluateDecision;
1157
+ /**
1158
+ * FPS ratio membership "low".
1159
+ * Input: ratio = actualFPS / targetFPS (e.g. 42/60 = 0.70).
1160
+ *
1161
+ * ratio < 0.7 → 1.0 (clearly failing, e.g. 40/60)
1162
+ * ratio 0.7..0.9 → linear ramp down (e.g. 0.8 → 0.5)
1163
+ * ratio > 0.9 → 0.0 (keeping up)
1164
+ */
1165
+ private membershipFpsLow;
1166
+ /**
1167
+ * FPS ratio membership "ok" — triangle shape.
1168
+ * Input: ratio = actualFPS / targetFPS.
1169
+ *
1170
+ * ratio < 0.8 → 0.0
1171
+ * ratio 0.8..0.95 → ramp up, peak at 0.95 (e.g. 57/60)
1172
+ * ratio 0.95..1.0 → ramp down
1173
+ * ratio > 1.0 → 0.0
1174
+ */
1175
+ private membershipFpsOk;
1176
+ /**
1177
+ * FPS ratio membership "high".
1178
+ * Input: ratio = actualFPS / targetFPS.
1179
+ *
1180
+ * ratio < 0.9 → 0.0
1181
+ * ratio 0.9..1.0 → linear ramp up (e.g. 0.95 → 0.5)
1182
+ * ratio >= 1.0 → 1.0 (meeting or exceeding target, e.g. 60/60)
1183
+ */
1184
+ private membershipFpsHigh;
1185
+ /**
1186
+ * Bitrate load membership "high".
1187
+ * Input: load = currentBitrate / MAX_BITRATE (20 Mbit/s).
1188
+ *
1189
+ * load < 0.5 → 0.0 (below 10 Mbit/s — plenty of headroom)
1190
+ * load 0.5..0.8 → linear ramp (e.g. 13M/20M = 0.65 → 0.5)
1191
+ * load > 0.8 → 1.0 (above 16 Mbit/s — near capacity)
1192
+ */
1193
+ private membershipBitrateHigh;
1194
+ private upgradeFps;
1195
+ /**
1196
+ * Get the next FPS target based on current target and decision.
1197
+ * Clamps to valid FPS_STEPS range.
1198
+ */
1199
+ private getNextFpsTarget;
1200
+ /**
1201
+ * Find the closest FPS step index for a given target value.
1202
+ */
1203
+ private findClosestFpsIndex;
1204
+ /** Average all collected samples for the current evaluation window. */
1205
+ private averageSamples;
1206
+ static ɵfac: i0.ɵɵFactoryDeclaration<FpsMonitorService, never>;
1207
+ static ɵprov: i0.ɵɵInjectableDeclaration<FpsMonitorService>;
1208
+ }
1209
+
1034
1210
  declare function AnswerHandler(this: SignallingService, msg: RTCSessionDescriptionInit): void;
1035
1211
 
1036
1212
  declare function ConfigHandler(this: SignallingService, msg: ConfigMessage): void;
@@ -2163,5 +2339,5 @@ declare class SafePipe implements PipeTransform {
2163
2339
  static ɵpipe: i0.ɵɵPipeDeclaration<SafePipe, "safe", true>;
2164
2340
  }
2165
2341
 
2166
- export { AFKService, AfkPlaywrightService, AggregatorPlaywrightService, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, ClickableOverlayComponent, CommandTelemetryPlaywrightService, CommandTelemetryService, ConfigHandler, ConsoleExtensionsPlaywrightService, ConsoleExtensionsService, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DEFAULT_RECONNECT_DELAY_MS, DEFAULT_RECONNECT_ENABLED, DEFAULT_RECONNECT_MAX_ATTEMPTS, DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE, DEFAULT_RECONNECT_ON_ICE_FAILURE, DataFlowMonitor, DevModeService, DisconnectReason, EControlSchemeType, EMessageType, EToClientMessageType, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverPlaywrightService, FileReceiverService, FilterSettingsComponent, FreezeFrameComponent, FreezeFramePlaywrightService, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputPlaywrightService, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, RegionsPingService, ResetTelemetry, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_VIDEO_ID, SafePipe, SignallingPlaywrightService, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryPlaywrightService, StreamStatusTelemetryService, SubService, TelemetryStart, TelemetryStop, UNREAL_CONFIG, UnrealCommunicatorPlaywrightService, UnrealCommunicatorService, UnrealEffects, UnrealInternalSignalEvents, UnrealSceneComponent, UnrealStatusMessage, VideoRecorder, 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_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, changeLowBandwidth, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, floatToSmoothPercents, forceResizeUnrealVideo, fromResizeObserver, fromSignal, fromUnrealCallBackSignal, getActiveUrl, getImageFromVideoStream, getRtcErrorMessage, iceConnectionFailed, initSignalling, initialState, isLoaderScreenVisible, keepMaxUntilReset, mapQpToQuality, observeCommandResponse, provideAngularUnrealModule, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, removeExileCommands, resetAfk, resetAfkAction, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetWarnTimeout, saveAnalyticsEvent, selectClientAndViewIds, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsVideoPlayingAndDataChannelConnected, selectLastCommandInProgress, selectLoaderCommands, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, sendSignal, setAfkTimerHide, setAfkTimerVisible, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setDataChannelConnected, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMaxFps, setOrchestrationContext, setOrchestrationMessage, setOrchestrationParameters, setOrchestrationProgress, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setUnrealPlaywrightConfig, setViewportNotReady, setViewportReady, showPopupWithoutAutoStart, showUnrealErrorMessage, smoothTransition, startStream, trackMixpanelEvent, unrealFeature, unrealReducer, updateCirrusInfo };
2342
+ export { AFKService, AfkPlaywrightService, AggregatorPlaywrightService, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, ClickableOverlayComponent, CommandTelemetryPlaywrightService, CommandTelemetryService, ConfigHandler, ConsoleExtensionsPlaywrightService, ConsoleExtensionsService, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DEFAULT_RECONNECT_DELAY_MS, DEFAULT_RECONNECT_ENABLED, DEFAULT_RECONNECT_MAX_ATTEMPTS, DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE, DEFAULT_RECONNECT_ON_ICE_FAILURE, DataFlowMonitor, DevModeService, DisconnectReason, EControlSchemeType, EMessageType, EToClientMessageType, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverPlaywrightService, FileReceiverService, FilterSettingsComponent, FpsMonitorService, FreezeFrameComponent, FreezeFramePlaywrightService, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputPlaywrightService, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, RegionsPingService, ResetTelemetry, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_VIDEO_ID, SafePipe, SignallingPlaywrightService, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryPlaywrightService, StreamStatusTelemetryService, SubService, TelemetryStart, TelemetryStop, UNREAL_CONFIG, UnrealCommunicatorPlaywrightService, UnrealCommunicatorService, UnrealEffects, UnrealInternalSignalEvents, UnrealSceneComponent, UnrealStatusMessage, VideoRecorder, 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_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, changeLowBandwidth, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, floatToSmoothPercents, forceResizeUnrealVideo, fromResizeObserver, fromSignal, fromUnrealCallBackSignal, getActiveUrl, getImageFromVideoStream, getRtcErrorMessage, iceConnectionFailed, initSignalling, initialState, isLoaderScreenVisible, keepMaxUntilReset, mapQpToQuality, observeCommandResponse, provideAngularUnrealModule, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, removeExileCommands, resetAfk, resetAfkAction, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetWarnTimeout, saveAnalyticsEvent, selectClientAndViewIds, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsVideoPlayingAndDataChannelConnected, selectLastCommandInProgress, selectLoaderCommands, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, sendSignal, setAfkTimerHide, setAfkTimerVisible, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setDataChannelConnected, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMaxFps, setOrchestrationContext, setOrchestrationMessage, setOrchestrationParameters, setOrchestrationProgress, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setUnrealPlaywrightConfig, setViewportNotReady, setViewportReady, showPopupWithoutAutoStart, showUnrealErrorMessage, smoothTransition, startStream, trackMixpanelEvent, unrealFeature, unrealReducer, updateCirrusInfo };
2167
2343
  export type { AnySignalingMessage, AwsInstance, CandidateMessage, CloseReason, CommandsLoaderState, ConfigMessage, ConnectionError, DataFlowCheckResult, DisconnectReasonType, EControlSchemeTypeValues, EMessageTypeValues, ForceClientDisconnect, FreezeFrameMessage, IAggregatedStat, InboundVideoStats, InputProps, InstanceReady, InstanceReserved, InterruptClientStream, LBMStats, ListStreamersMessage, MessageBase, NormalizeAndQuantizeSignedValue, NormalizeAndQuantizeUnsignedValue, ObservedCallbackResponse, OrchestrationErrorMessage, OrchestrationMessageType, P2PEstablishedMessage, PingMessage, PlayerCountMessage, PollingOrchestrationMessage, Quality, ReceivedFile, ReconnectConfig, RequestStream, SSInfo, SignalDescriptor, SignalingData, SignalingMessageHandler, SignalingMessageMap, StreamConfig, StreamRequestContext, StreamResolutionProps, StreamerListMessage, TelemetryType, UnknownFields, UnquantizeAndDenormalizeUnsignedValue, UnrealCallBackJson, UnrealInitialConfig, UnrealState, WSCloseCodesValues, WrappedMetaBoxCommandPacket, streamPreparedForUserInteractionMessage };