@livepeer-frameworks/player-core 0.0.3

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.
Files changed (120) hide show
  1. package/dist/cjs/index.js +19493 -0
  2. package/dist/cjs/index.js.map +1 -0
  3. package/dist/esm/index.js +19398 -0
  4. package/dist/esm/index.js.map +1 -0
  5. package/dist/player.css +2140 -0
  6. package/dist/types/core/ABRController.d.ts +164 -0
  7. package/dist/types/core/CodecUtils.d.ts +54 -0
  8. package/dist/types/core/Disposable.d.ts +61 -0
  9. package/dist/types/core/EventEmitter.d.ts +73 -0
  10. package/dist/types/core/GatewayClient.d.ts +144 -0
  11. package/dist/types/core/InteractionController.d.ts +121 -0
  12. package/dist/types/core/LiveDurationProxy.d.ts +102 -0
  13. package/dist/types/core/MetaTrackManager.d.ts +220 -0
  14. package/dist/types/core/MistReporter.d.ts +163 -0
  15. package/dist/types/core/MistSignaling.d.ts +148 -0
  16. package/dist/types/core/PlayerController.d.ts +665 -0
  17. package/dist/types/core/PlayerInterface.d.ts +230 -0
  18. package/dist/types/core/PlayerManager.d.ts +182 -0
  19. package/dist/types/core/PlayerRegistry.d.ts +27 -0
  20. package/dist/types/core/QualityMonitor.d.ts +184 -0
  21. package/dist/types/core/ScreenWakeLockManager.d.ts +70 -0
  22. package/dist/types/core/SeekingUtils.d.ts +142 -0
  23. package/dist/types/core/StreamStateClient.d.ts +108 -0
  24. package/dist/types/core/SubtitleManager.d.ts +111 -0
  25. package/dist/types/core/TelemetryReporter.d.ts +79 -0
  26. package/dist/types/core/TimeFormat.d.ts +97 -0
  27. package/dist/types/core/TimerManager.d.ts +83 -0
  28. package/dist/types/core/UrlUtils.d.ts +81 -0
  29. package/dist/types/core/detector.d.ts +149 -0
  30. package/dist/types/core/index.d.ts +49 -0
  31. package/dist/types/core/scorer.d.ts +167 -0
  32. package/dist/types/core/selector.d.ts +9 -0
  33. package/dist/types/index.d.ts +45 -0
  34. package/dist/types/lib/utils.d.ts +2 -0
  35. package/dist/types/players/DashJsPlayer.d.ts +102 -0
  36. package/dist/types/players/HlsJsPlayer.d.ts +70 -0
  37. package/dist/types/players/MewsWsPlayer/SourceBufferManager.d.ts +119 -0
  38. package/dist/types/players/MewsWsPlayer/WebSocketManager.d.ts +60 -0
  39. package/dist/types/players/MewsWsPlayer/index.d.ts +220 -0
  40. package/dist/types/players/MewsWsPlayer/types.d.ts +89 -0
  41. package/dist/types/players/MistPlayer.d.ts +25 -0
  42. package/dist/types/players/MistWebRTCPlayer/index.d.ts +133 -0
  43. package/dist/types/players/NativePlayer.d.ts +143 -0
  44. package/dist/types/players/VideoJsPlayer.d.ts +59 -0
  45. package/dist/types/players/WebCodecsPlayer/JitterBuffer.d.ts +118 -0
  46. package/dist/types/players/WebCodecsPlayer/LatencyProfiles.d.ts +64 -0
  47. package/dist/types/players/WebCodecsPlayer/RawChunkParser.d.ts +63 -0
  48. package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +174 -0
  49. package/dist/types/players/WebCodecsPlayer/WebSocketController.d.ts +164 -0
  50. package/dist/types/players/WebCodecsPlayer/index.d.ts +149 -0
  51. package/dist/types/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.d.ts +105 -0
  52. package/dist/types/players/WebCodecsPlayer/types.d.ts +395 -0
  53. package/dist/types/players/WebCodecsPlayer/worker/decoder.worker.d.ts +13 -0
  54. package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +197 -0
  55. package/dist/types/players/index.d.ts +14 -0
  56. package/dist/types/styles/index.d.ts +11 -0
  57. package/dist/types/types.d.ts +363 -0
  58. package/dist/types/vanilla/FrameWorksPlayer.d.ts +143 -0
  59. package/dist/types/vanilla/index.d.ts +19 -0
  60. package/dist/workers/decoder.worker.js +989 -0
  61. package/dist/workers/decoder.worker.js.map +1 -0
  62. package/package.json +80 -0
  63. package/src/core/ABRController.ts +550 -0
  64. package/src/core/CodecUtils.ts +257 -0
  65. package/src/core/Disposable.ts +120 -0
  66. package/src/core/EventEmitter.ts +113 -0
  67. package/src/core/GatewayClient.ts +439 -0
  68. package/src/core/InteractionController.ts +712 -0
  69. package/src/core/LiveDurationProxy.ts +270 -0
  70. package/src/core/MetaTrackManager.ts +753 -0
  71. package/src/core/MistReporter.ts +543 -0
  72. package/src/core/MistSignaling.ts +346 -0
  73. package/src/core/PlayerController.ts +2829 -0
  74. package/src/core/PlayerInterface.ts +432 -0
  75. package/src/core/PlayerManager.ts +900 -0
  76. package/src/core/PlayerRegistry.ts +149 -0
  77. package/src/core/QualityMonitor.ts +597 -0
  78. package/src/core/ScreenWakeLockManager.ts +163 -0
  79. package/src/core/SeekingUtils.ts +364 -0
  80. package/src/core/StreamStateClient.ts +457 -0
  81. package/src/core/SubtitleManager.ts +297 -0
  82. package/src/core/TelemetryReporter.ts +308 -0
  83. package/src/core/TimeFormat.ts +205 -0
  84. package/src/core/TimerManager.ts +209 -0
  85. package/src/core/UrlUtils.ts +179 -0
  86. package/src/core/detector.ts +382 -0
  87. package/src/core/index.ts +140 -0
  88. package/src/core/scorer.ts +553 -0
  89. package/src/core/selector.ts +16 -0
  90. package/src/global.d.ts +11 -0
  91. package/src/index.ts +75 -0
  92. package/src/lib/utils.ts +6 -0
  93. package/src/players/DashJsPlayer.ts +642 -0
  94. package/src/players/HlsJsPlayer.ts +483 -0
  95. package/src/players/MewsWsPlayer/SourceBufferManager.ts +572 -0
  96. package/src/players/MewsWsPlayer/WebSocketManager.ts +241 -0
  97. package/src/players/MewsWsPlayer/index.ts +1065 -0
  98. package/src/players/MewsWsPlayer/types.ts +106 -0
  99. package/src/players/MistPlayer.ts +188 -0
  100. package/src/players/MistWebRTCPlayer/index.ts +703 -0
  101. package/src/players/NativePlayer.ts +820 -0
  102. package/src/players/VideoJsPlayer.ts +643 -0
  103. package/src/players/WebCodecsPlayer/JitterBuffer.ts +299 -0
  104. package/src/players/WebCodecsPlayer/LatencyProfiles.ts +151 -0
  105. package/src/players/WebCodecsPlayer/RawChunkParser.ts +151 -0
  106. package/src/players/WebCodecsPlayer/SyncController.ts +456 -0
  107. package/src/players/WebCodecsPlayer/WebSocketController.ts +564 -0
  108. package/src/players/WebCodecsPlayer/index.ts +1650 -0
  109. package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +379 -0
  110. package/src/players/WebCodecsPlayer/types.ts +542 -0
  111. package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +1360 -0
  112. package/src/players/WebCodecsPlayer/worker/types.ts +276 -0
  113. package/src/players/index.ts +22 -0
  114. package/src/styles/animations.css +21 -0
  115. package/src/styles/index.ts +52 -0
  116. package/src/styles/player.css +2126 -0
  117. package/src/styles/tailwind.css +1015 -0
  118. package/src/types.ts +421 -0
  119. package/src/vanilla/FrameWorksPlayer.ts +367 -0
  120. package/src/vanilla/index.ts +22 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Common Player Interface
3
+ *
4
+ * All player implementations must implement this interface to ensure
5
+ * consistent behavior and enable the PlayerManager selection system
6
+ */
7
+ export interface StreamSource {
8
+ url: string;
9
+ type: string;
10
+ index?: number;
11
+ streamName?: string;
12
+ mistPlayerUrl?: string;
13
+ }
14
+ export interface StreamTrack {
15
+ type: 'video' | 'audio' | 'meta';
16
+ codec: string;
17
+ codecstring?: string;
18
+ init?: string;
19
+ /** Track index from MistServer (used for binary chunk routing) */
20
+ idx?: number;
21
+ width?: number;
22
+ height?: number;
23
+ fpks?: number;
24
+ channels?: number;
25
+ rate?: number;
26
+ size?: number;
27
+ }
28
+ export interface StreamInfo {
29
+ source: StreamSource[];
30
+ meta: {
31
+ tracks: StreamTrack[];
32
+ };
33
+ type?: 'live' | 'vod';
34
+ }
35
+ export interface PlayerOptions {
36
+ autoplay?: boolean;
37
+ muted?: boolean;
38
+ controls?: boolean;
39
+ loop?: boolean;
40
+ poster?: string;
41
+ width?: number;
42
+ height?: number;
43
+ /** Enable dev mode - for Legacy player, uses MistServer's dev skin with source selection */
44
+ devMode?: boolean;
45
+ onReady?: (element: HTMLVideoElement) => void;
46
+ onError?: (error: string | Error) => void;
47
+ onPlay?: () => void;
48
+ onPause?: () => void;
49
+ onEnded?: () => void;
50
+ onTimeUpdate?: (currentTime: number) => void;
51
+ onWaiting?: () => void;
52
+ onPlaying?: () => void;
53
+ onCanPlay?: () => void;
54
+ onDurationChange?: (duration: number) => void;
55
+ }
56
+ export interface PlayerCapability {
57
+ /** Player name for display */
58
+ name: string;
59
+ /** Unique identifier */
60
+ shortname: string;
61
+ /** Priority (lower number = higher priority) */
62
+ priority: number;
63
+ /** MIME types this player can handle */
64
+ mimes: string[];
65
+ }
66
+ export interface PlayerEvents {
67
+ ready: HTMLVideoElement;
68
+ error: string | Error;
69
+ play: void;
70
+ pause: void;
71
+ ended: void;
72
+ timeupdate: number;
73
+ /** Request to reload the player (e.g., Firefox segment error recovery) */
74
+ reloadrequested: {
75
+ reason: string;
76
+ };
77
+ /** Seekable range changed */
78
+ seekablechange: {
79
+ start: number;
80
+ end: number;
81
+ bufferWindow: number;
82
+ };
83
+ }
84
+ /**
85
+ * Base interface all players must implement
86
+ */
87
+ export interface IPlayer {
88
+ /** Player metadata */
89
+ readonly capability: PlayerCapability;
90
+ /**
91
+ * Check if this player supports the given MIME type
92
+ */
93
+ isMimeSupported(mimetype: string): boolean;
94
+ /**
95
+ * Check if this player can play in the current browser environment
96
+ * @param mimetype - MIME type to test
97
+ * @param source - Source information
98
+ * @param streamInfo - Stream metadata
99
+ * @returns false if not supported, true if supported (no track info),
100
+ * or array of supported track types
101
+ */
102
+ isBrowserSupported(mimetype: string, source: StreamSource, streamInfo: StreamInfo): boolean | string[];
103
+ /**
104
+ * Initialize the player with given source and options
105
+ * @param container - Container element to render in
106
+ * @param source - Source to play
107
+ * @param options - Player options
108
+ * @param streamInfo - Full stream metadata (optional, for players that need track details)
109
+ * @returns Promise resolving to video element
110
+ */
111
+ initialize(container: HTMLElement, source: StreamSource, options: PlayerOptions, streamInfo?: StreamInfo): Promise<HTMLVideoElement>;
112
+ /**
113
+ * Clean up and destroy the player.
114
+ * May be async if cleanup requires network requests (e.g., WHEP session DELETE).
115
+ */
116
+ destroy(): void | Promise<void>;
117
+ /**
118
+ * Get the underlying video element (if available)
119
+ */
120
+ getVideoElement(): HTMLVideoElement | null;
121
+ /**
122
+ * Set video size
123
+ */
124
+ setSize?(width: number, height: number): void;
125
+ /**
126
+ * Add event listener
127
+ */
128
+ on<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void;
129
+ /**
130
+ * Remove event listener
131
+ */
132
+ off<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void;
133
+ /**
134
+ * Get current playback state
135
+ */
136
+ getCurrentTime?(): number;
137
+ getDuration?(): number;
138
+ isPaused?(): boolean;
139
+ isMuted?(): boolean;
140
+ /** Optional: provide an override seekable range (seconds) */
141
+ getSeekableRange?(): {
142
+ start: number;
143
+ end: number;
144
+ } | null;
145
+ /** Optional: provide buffered ranges override */
146
+ getBufferedRanges?(): TimeRanges | null;
147
+ /**
148
+ * Control playback
149
+ */
150
+ play?(): Promise<void>;
151
+ pause?(): void;
152
+ seek?(time: number): void;
153
+ setVolume?(volume: number): void;
154
+ setMuted?(muted: boolean): void;
155
+ setPlaybackRate?(rate: number): void;
156
+ getTextTracks?(): Array<{
157
+ id: string;
158
+ label: string;
159
+ lang?: string;
160
+ active: boolean;
161
+ }>;
162
+ selectTextTrack?(id: string | null): void;
163
+ getQualities?(): Array<{
164
+ id: string;
165
+ label: string;
166
+ bitrate?: number;
167
+ width?: number;
168
+ height?: number;
169
+ isAuto?: boolean;
170
+ active?: boolean;
171
+ }>;
172
+ selectQuality?(id: string): void;
173
+ getCurrentQuality?(): string | null;
174
+ isLive?(): boolean;
175
+ jumpToLive?(): void;
176
+ requestPiP?(): Promise<void>;
177
+ /**
178
+ * Optional: Retrieve player-specific stats (e.g., WebRTC inbound-rtp)
179
+ */
180
+ getStats?(): Promise<any>;
181
+ /**
182
+ * Optional: Retrieve approximate playback latency stats
183
+ */
184
+ getLatency?(): Promise<any>;
185
+ }
186
+ /**
187
+ * Base class providing common functionality
188
+ */
189
+ export declare abstract class BasePlayer implements IPlayer {
190
+ abstract readonly capability: PlayerCapability;
191
+ protected listeners: Map<string, Set<Function>>;
192
+ protected videoElement: HTMLVideoElement | null;
193
+ abstract isMimeSupported(mimetype: string): boolean;
194
+ abstract isBrowserSupported(mimetype: string, source: StreamSource, streamInfo: StreamInfo): boolean | string[];
195
+ abstract initialize(container: HTMLElement, source: StreamSource, options: PlayerOptions, streamInfo?: StreamInfo): Promise<HTMLVideoElement>;
196
+ abstract destroy(): void | Promise<void>;
197
+ getVideoElement(): HTMLVideoElement | null;
198
+ on<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void;
199
+ off<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void;
200
+ protected emit<K extends keyof PlayerEvents>(event: K, data: PlayerEvents[K]): void;
201
+ protected setupVideoEventListeners(video: HTMLVideoElement, options: PlayerOptions): void;
202
+ getCurrentTime(): number;
203
+ getDuration(): number;
204
+ getSeekableRange(): {
205
+ start: number;
206
+ end: number;
207
+ } | null;
208
+ getBufferedRanges(): TimeRanges | null;
209
+ isPaused(): boolean;
210
+ isMuted(): boolean;
211
+ play(): Promise<void>;
212
+ pause(): void;
213
+ seek(time: number): void;
214
+ setVolume(volume: number): void;
215
+ setMuted(muted: boolean): void;
216
+ setPlaybackRate(rate: number): void;
217
+ getTextTracks(): Array<{
218
+ id: string;
219
+ label: string;
220
+ lang?: string;
221
+ active: boolean;
222
+ }>;
223
+ selectTextTrack(id: string | null): void;
224
+ isLive(): boolean;
225
+ jumpToLive(): void;
226
+ requestPiP(): Promise<void>;
227
+ setSize(width: number, height: number): void;
228
+ getStats(): Promise<any>;
229
+ getLatency(): Promise<any>;
230
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * PlayerManager
3
+ *
4
+ * Central orchestrator for player selection and lifecycle management.
5
+ * Single source of truth for all scoring logic.
6
+ *
7
+ * Architecture:
8
+ * - `getAllCombinations()` is THE single function that computes player+source scores
9
+ * - Results are cached by content (source types + track codecs), not object identity
10
+ * - Events fire only when selection actually changes (no render spam)
11
+ * - `selectBestPlayer()` returns cached winner without recomputation
12
+ */
13
+ import { IPlayer, StreamSource, StreamInfo, PlayerOptions } from './PlayerInterface';
14
+ import type { PlaybackMode } from '../types';
15
+ export interface PlayerSelection {
16
+ score: number;
17
+ player: string;
18
+ source: StreamSource;
19
+ source_index: number;
20
+ }
21
+ export interface PlayerManagerOptions {
22
+ /** Force a specific player */
23
+ forcePlayer?: string;
24
+ /** Force a specific source index */
25
+ forceSource?: number;
26
+ /** Force a specific MIME type */
27
+ forceType?: string;
28
+ /** Enable debug logging (logs selection changes only, not every render) */
29
+ debug?: boolean;
30
+ /** Automatic fallback on player failure */
31
+ autoFallback?: boolean;
32
+ /** Maximum fallback attempts */
33
+ maxFallbackAttempts?: number;
34
+ /** Playback mode for protocol selection */
35
+ playbackMode?: PlaybackMode;
36
+ }
37
+ export interface PlayerManagerEvents {
38
+ playerSelected: {
39
+ player: string;
40
+ source: StreamSource;
41
+ score: number;
42
+ };
43
+ playerInitialized: {
44
+ player: IPlayer;
45
+ videoElement: HTMLVideoElement;
46
+ };
47
+ playerFailed: {
48
+ player: string;
49
+ error: string;
50
+ };
51
+ fallbackAttempted: {
52
+ fromPlayer: string;
53
+ toPlayer: string;
54
+ };
55
+ /** Fires when selection changes (different player+source than before) */
56
+ 'selection-changed': PlayerSelection | null;
57
+ /** Fires when combinations are recomputed (cache miss) */
58
+ 'combinations-updated': PlayerCombination[];
59
+ }
60
+ /** Full combination info including scoring breakdown */
61
+ export interface PlayerCombination {
62
+ player: string;
63
+ playerName: string;
64
+ source: StreamSource;
65
+ sourceIndex: number;
66
+ sourceType: string;
67
+ score: number;
68
+ compatible: boolean;
69
+ incompatibleReason?: string;
70
+ /** True when player supports MIME but codec is incompatible */
71
+ codecIncompatible?: boolean;
72
+ scoreBreakdown?: {
73
+ trackScore: number;
74
+ trackTypes: string[];
75
+ priorityScore: number;
76
+ sourceScore: number;
77
+ reliabilityScore?: number;
78
+ modeBonus?: number;
79
+ routingBonus?: number;
80
+ weights: {
81
+ tracks: number;
82
+ priority: number;
83
+ source: number;
84
+ reliability?: number;
85
+ mode?: number;
86
+ routing?: number;
87
+ };
88
+ };
89
+ }
90
+ export declare class PlayerManager {
91
+ private players;
92
+ private currentPlayer;
93
+ private listeners;
94
+ private fallbackAttempts;
95
+ private options;
96
+ private cachedCombinations;
97
+ private cachedSelection;
98
+ private cacheKey;
99
+ private lastLoggedWinner;
100
+ private lastContainer;
101
+ private lastStreamInfo;
102
+ private lastPlayerOptions;
103
+ private lastManagerOptions;
104
+ private excludedPlayers;
105
+ private opQueue;
106
+ constructor(options?: PlayerManagerOptions);
107
+ registerPlayer(player: IPlayer): void;
108
+ unregisterPlayer(shortname: string): void;
109
+ getRegisteredPlayers(): IPlayer[];
110
+ /**
111
+ * Compute cache key based on CONTENT, not object identity.
112
+ * Prevents recalculation when streamInfo is a new object with same data.
113
+ */
114
+ private computeCacheKey;
115
+ /** Invalidate cache (called when player registrations change) */
116
+ invalidateCache(): void;
117
+ /** Get cached selection without recomputing */
118
+ getCurrentSelection(): PlayerSelection | null;
119
+ /** Get cached combinations without recomputing */
120
+ getCachedCombinations(): PlayerCombination[] | null;
121
+ /**
122
+ * THE single source of truth for player+source scoring.
123
+ * Returns ALL combinations (compatible and incompatible) with scores.
124
+ * Results are cached - won't recompute if source types/tracks haven't changed.
125
+ */
126
+ getAllCombinations(streamInfo: StreamInfo, playbackMode?: PlaybackMode): PlayerCombination[];
127
+ /**
128
+ * Select the best player for given stream info.
129
+ * Uses cached combinations - won't recompute if data hasn't changed.
130
+ */
131
+ selectBestPlayer(streamInfo: StreamInfo, options?: PlayerManagerOptions): PlayerSelection | false;
132
+ /**
133
+ * Internal: compute all combinations (no caching)
134
+ */
135
+ private computeAllCombinations;
136
+ /**
137
+ * Pick best compatible combination
138
+ */
139
+ private pickBestFromCombinations;
140
+ /**
141
+ * Check if selection changed
142
+ */
143
+ private hasSelectionChanged;
144
+ private enqueueOp;
145
+ initializePlayer(container: HTMLElement, streamInfo: StreamInfo, playerOptions?: PlayerOptions, managerOptions?: PlayerManagerOptions): Promise<HTMLVideoElement>;
146
+ private tryInitializePlayer;
147
+ tryPlaybackFallback(): Promise<boolean>;
148
+ getRemainingFallbackAttempts(): number;
149
+ canAttemptFallback(): boolean;
150
+ getCurrentPlayer(): IPlayer | null;
151
+ getBrowserCapabilities(): {
152
+ browser: import("./detector").BrowserInfo;
153
+ compatibility: {
154
+ supportsNativeHLS: boolean | 0 | null;
155
+ supportsMSE: boolean;
156
+ supportsWebSocket: boolean;
157
+ supportsWebRTC: boolean;
158
+ preferVideoJs: boolean | 0 | null;
159
+ avoidMEWSOnMac: boolean;
160
+ fileProtocolLimitations: boolean;
161
+ };
162
+ supportedMimeTypes: string[];
163
+ availablePlayers: {
164
+ name: string;
165
+ shortname: string;
166
+ priority: number;
167
+ mimes: string[];
168
+ }[];
169
+ };
170
+ private getSupportedMimeTypes;
171
+ private getAvailablePlayerInfo;
172
+ destroy(): Promise<void>;
173
+ removeAllListeners(): void;
174
+ on<K extends keyof PlayerManagerEvents>(event: K, listener: (data: PlayerManagerEvents[K]) => void): () => void;
175
+ off<K extends keyof PlayerManagerEvents>(event: K, listener: (data: PlayerManagerEvents[K]) => void): void;
176
+ private emit;
177
+ private log;
178
+ testSource(source: StreamSource, streamInfo: StreamInfo): Promise<{
179
+ canPlay: boolean;
180
+ players: string[];
181
+ }>;
182
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Player Registry
3
+ *
4
+ * Central registration of all available player implementations
5
+ */
6
+ import { PlayerManager } from './PlayerManager';
7
+ export declare function ensurePlayersRegistered(manager?: PlayerManager): Promise<void>;
8
+ export declare const globalPlayerManager: PlayerManager;
9
+ /**
10
+ * Register all available players (async for backwards compatibility)
11
+ */
12
+ export declare function registerAllPlayers(manager?: PlayerManager): Promise<void>;
13
+ /**
14
+ * Create a new PlayerManager instance with all players registered
15
+ */
16
+ export declare function createPlayerManager(options?: ConstructorParameters<typeof PlayerManager>[0]): PlayerManager;
17
+ /**
18
+ * Export individual player classes for direct use
19
+ */
20
+ export { NativePlayerImpl, DirectPlaybackPlayerImpl } from '../players/NativePlayer';
21
+ export { HlsJsPlayerImpl } from '../players/HlsJsPlayer';
22
+ export { DashJsPlayerImpl } from '../players/DashJsPlayer';
23
+ export { VideoJsPlayerImpl } from '../players/VideoJsPlayer';
24
+ export { MistPlayerImpl } from '../players/MistPlayer';
25
+ export { MewsWsPlayerImpl } from '../players/MewsWsPlayer';
26
+ export { MistWebRTCPlayerImpl } from '../players/MistWebRTCPlayer';
27
+ export { WebCodecsPlayerImpl } from '../players/WebCodecsPlayer';
@@ -0,0 +1,184 @@
1
+ import type { PlaybackQuality, QualityThresholds } from '../types';
2
+ /** Protocol type for threshold selection */
3
+ export type PlayerProtocol = 'webrtc' | 'hls' | 'dash' | 'html5' | 'unknown';
4
+ /** Protocol-specific playback score thresholds (MistMetaPlayer reference) */
5
+ export declare const PROTOCOL_THRESHOLDS: Record<PlayerProtocol, number>;
6
+ export interface QualityMonitorOptions {
7
+ /** Sample interval in ms */
8
+ sampleInterval?: number;
9
+ /** Quality thresholds */
10
+ thresholds?: Partial<QualityThresholds>;
11
+ /** Callback when quality degrades */
12
+ onQualityDegraded?: (quality: PlaybackQuality) => void;
13
+ /** Callback on every sample */
14
+ onSample?: (quality: PlaybackQuality) => void;
15
+ /** Current player protocol for threshold selection */
16
+ protocol?: PlayerProtocol;
17
+ /** Custom playback score threshold (overrides protocol default) */
18
+ playbackScoreThreshold?: number;
19
+ /**
20
+ * Callback when sustained poor quality triggers a fallback request
21
+ * Reference: player.js:654-665 - "nextCombo" action
22
+ */
23
+ onFallbackRequest?: (reason: {
24
+ score: number;
25
+ consecutivePoorSamples: number;
26
+ }) => void;
27
+ /**
28
+ * Number of consecutive poor samples before requesting fallback
29
+ * Default: 5 (2.5 seconds at 500ms sample interval)
30
+ */
31
+ poorSamplesBeforeFallback?: number;
32
+ }
33
+ export interface QualityMonitorState {
34
+ isMonitoring: boolean;
35
+ quality: PlaybackQuality | null;
36
+ history: PlaybackQuality[];
37
+ }
38
+ /**
39
+ * QualityMonitor - Tracks playback quality metrics
40
+ *
41
+ * Monitors:
42
+ * - Buffer health (seconds ahead)
43
+ * - Stall count (waiting events)
44
+ * - Frame drop rate (via video.getVideoPlaybackQuality())
45
+ * - Estimated bitrate
46
+ * - Latency (for live streams)
47
+ *
48
+ * Calculates a composite quality score (0-100) and triggers
49
+ * callbacks when quality degrades below thresholds.
50
+ */
51
+ export declare class QualityMonitor {
52
+ private videoElement;
53
+ private options;
54
+ private thresholds;
55
+ private timers;
56
+ private stallCount;
57
+ private lastStallTime;
58
+ private totalStallMs;
59
+ private history;
60
+ private lastBytesLoaded;
61
+ private lastBytesTime;
62
+ private listeners;
63
+ private playbackScoreHistory;
64
+ private playbackScore;
65
+ private readonly PLAYBACK_SCORE_AVERAGING_STEPS;
66
+ private consecutivePoorSamples;
67
+ private fallbackTriggered;
68
+ constructor(options?: QualityMonitorOptions);
69
+ /**
70
+ * Set the current player protocol for threshold selection
71
+ */
72
+ setProtocol(protocol: PlayerProtocol): void;
73
+ /**
74
+ * Get the current player protocol
75
+ */
76
+ getProtocol(): PlayerProtocol;
77
+ /**
78
+ * Get the playback score threshold for the current protocol
79
+ */
80
+ getPlaybackScoreThreshold(): number;
81
+ /**
82
+ * Set a custom playback score threshold (overrides protocol default)
83
+ */
84
+ setPlaybackScoreThreshold(threshold: number | null): void;
85
+ /**
86
+ * Start monitoring a video element
87
+ */
88
+ start(videoElement: HTMLVideoElement): void;
89
+ /**
90
+ * Stop monitoring
91
+ */
92
+ stop(): void;
93
+ /**
94
+ * Take a quality sample
95
+ */
96
+ private sample;
97
+ /**
98
+ * Calculate current quality metrics
99
+ */
100
+ private calculateQuality;
101
+ /**
102
+ * Calculate composite quality score
103
+ *
104
+ * D4: Duration-weighted stall tracking - stall penalty considers both
105
+ * count AND duration. 10x 0.1s stalls (1s total) weighs less than 1x 1s stall.
106
+ */
107
+ private calculateScore;
108
+ /**
109
+ * Get current quality metrics
110
+ */
111
+ getCurrentQuality(): PlaybackQuality | null;
112
+ /**
113
+ * Get rolling average quality
114
+ */
115
+ getAverageQuality(): PlaybackQuality | null;
116
+ /**
117
+ * Get quality history
118
+ */
119
+ getHistory(): PlaybackQuality[];
120
+ /**
121
+ * Reset stall counters
122
+ */
123
+ resetStallCounters(): void;
124
+ /**
125
+ * Get total stall time in ms
126
+ */
127
+ getTotalStallMs(): number;
128
+ /**
129
+ * Check if currently monitoring
130
+ */
131
+ isMonitoring(): boolean;
132
+ /**
133
+ * Calculate playback score entry value
134
+ * Compares video time progress vs wall clock time
135
+ */
136
+ private getPlaybackScoreValue;
137
+ /**
138
+ * Calculate score between two entries
139
+ * Returns 1.0 for normal playback, >1.0 if faster, <1.0 if stalled, <0 if backwards
140
+ */
141
+ private calculatePlaybackScoreFromEntries;
142
+ /**
143
+ * Calculate and update the playback score
144
+ * Like MistPlayer's calcScore function
145
+ */
146
+ private updatePlaybackScore;
147
+ /**
148
+ * Get current playback score (MistPlayer-style 0-2.0 scale)
149
+ *
150
+ * - 1.0 = normal playback (video progresses at expected rate)
151
+ * - > 1.0 = faster than expected (catching up)
152
+ * - < 1.0 = slower than expected (stalling/buffering)
153
+ * - < 0 = video went backwards
154
+ *
155
+ * Threshold recommendations:
156
+ * - WebRTC: warn below 0.95
157
+ * - HLS/DASH: warn below 0.75
158
+ */
159
+ getPlaybackScore(): number;
160
+ /**
161
+ * Check if playback quality is poor based on score
162
+ * Uses protocol-specific thresholds (MistPlayer-style)
163
+ * WebRTC: 0.95 (strict), HLS/DASH/HTML5: 0.75 (lenient)
164
+ */
165
+ isPlaybackPoor(): boolean;
166
+ /**
167
+ * Reset playback score tracking
168
+ */
169
+ resetPlaybackScore(): void;
170
+ /**
171
+ * Reset fallback state
172
+ * Call after a player switch to allow fallback to trigger again
173
+ */
174
+ resetFallbackState(): void;
175
+ /**
176
+ * Get consecutive poor sample count (for debugging)
177
+ */
178
+ getConsecutivePoorSamples(): number;
179
+ /**
180
+ * Check if fallback has been triggered (for debugging)
181
+ */
182
+ hasFallbackTriggered(): boolean;
183
+ }
184
+ export default QualityMonitor;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ScreenWakeLockManager - Prevents device sleep during video playback
3
+ *
4
+ * Uses the Screen Wake Lock API to keep the screen awake during:
5
+ * - Fullscreen video playback
6
+ * - Active video playback (optional)
7
+ *
8
+ * Gracefully falls back to no-op on unsupported browsers.
9
+ */
10
+ export interface ScreenWakeLockConfig {
11
+ /** Acquire wake lock on any playback, not just fullscreen (default: false) */
12
+ acquireOnPlay?: boolean;
13
+ /** Callback when wake lock is acquired */
14
+ onAcquire?: () => void;
15
+ /** Callback when wake lock is released */
16
+ onRelease?: () => void;
17
+ /** Callback on error */
18
+ onError?: (error: Error) => void;
19
+ }
20
+ export declare class ScreenWakeLockManager {
21
+ private wakeLock;
22
+ private config;
23
+ private isSupported;
24
+ private isPlaying;
25
+ private isFullscreen;
26
+ private isDestroyed;
27
+ private boundVisibilityChange;
28
+ constructor(config?: ScreenWakeLockConfig);
29
+ /**
30
+ * Check if Screen Wake Lock API is supported
31
+ */
32
+ static isSupported(): boolean;
33
+ /**
34
+ * Update playing state
35
+ */
36
+ setPlaying(isPlaying: boolean): void;
37
+ /**
38
+ * Update fullscreen state
39
+ */
40
+ setFullscreen(isFullscreen: boolean): void;
41
+ /**
42
+ * Check if wake lock is currently held
43
+ */
44
+ isHeld(): boolean;
45
+ /**
46
+ * Manually acquire wake lock
47
+ */
48
+ acquire(): Promise<void>;
49
+ /**
50
+ * Manually release wake lock
51
+ */
52
+ release(): void;
53
+ /**
54
+ * Destroy the manager and release wake lock
55
+ */
56
+ destroy(): void;
57
+ /**
58
+ * Update wake lock based on current state
59
+ */
60
+ private updateWakeLock;
61
+ /**
62
+ * Handle wake lock release event
63
+ */
64
+ private handleRelease;
65
+ /**
66
+ * Handle visibility change - re-acquire if page becomes visible
67
+ */
68
+ private handleVisibilityChange;
69
+ }
70
+ export default ScreenWakeLockManager;