@livepeer-frameworks/player-core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -9
- package/dist/cjs/core/ABRController.js +456 -0
- package/dist/cjs/core/ABRController.js.map +1 -0
- package/dist/cjs/core/CodecUtils.js +195 -0
- package/dist/cjs/core/CodecUtils.js.map +1 -0
- package/dist/cjs/core/ErrorClassifier.js +410 -0
- package/dist/cjs/core/ErrorClassifier.js.map +1 -0
- package/dist/cjs/core/EventEmitter.js +108 -0
- package/dist/cjs/core/EventEmitter.js.map +1 -0
- package/dist/cjs/core/GatewayClient.js +342 -0
- package/dist/cjs/core/GatewayClient.js.map +1 -0
- package/dist/cjs/core/InteractionController.js +606 -0
- package/dist/cjs/core/InteractionController.js.map +1 -0
- package/dist/cjs/core/LiveDurationProxy.js +186 -0
- package/dist/cjs/core/LiveDurationProxy.js.map +1 -0
- package/dist/cjs/core/MetaTrackManager.js +624 -0
- package/dist/cjs/core/MetaTrackManager.js.map +1 -0
- package/dist/cjs/core/MistReporter.js +449 -0
- package/dist/cjs/core/MistReporter.js.map +1 -0
- package/dist/cjs/core/MistSignaling.js +264 -0
- package/dist/cjs/core/MistSignaling.js.map +1 -0
- package/dist/cjs/core/PlayerController.js +2658 -0
- package/dist/cjs/core/PlayerController.js.map +1 -0
- package/dist/cjs/core/PlayerInterface.js +269 -0
- package/dist/cjs/core/PlayerInterface.js.map +1 -0
- package/dist/cjs/core/PlayerManager.js +806 -0
- package/dist/cjs/core/PlayerManager.js.map +1 -0
- package/dist/cjs/core/PlayerRegistry.js +270 -0
- package/dist/cjs/core/PlayerRegistry.js.map +1 -0
- package/dist/cjs/core/QualityMonitor.js +474 -0
- package/dist/cjs/core/QualityMonitor.js.map +1 -0
- package/dist/cjs/core/SeekingUtils.js +292 -0
- package/dist/cjs/core/SeekingUtils.js.map +1 -0
- package/dist/cjs/core/StreamStateClient.js +381 -0
- package/dist/cjs/core/StreamStateClient.js.map +1 -0
- package/dist/cjs/core/SubtitleManager.js +227 -0
- package/dist/cjs/core/SubtitleManager.js.map +1 -0
- package/dist/cjs/core/TelemetryReporter.js +258 -0
- package/dist/cjs/core/TelemetryReporter.js.map +1 -0
- package/dist/cjs/core/TimeFormat.js +176 -0
- package/dist/cjs/core/TimeFormat.js.map +1 -0
- package/dist/cjs/core/TimerManager.js +176 -0
- package/dist/cjs/core/TimerManager.js.map +1 -0
- package/dist/cjs/core/UrlUtils.js +160 -0
- package/dist/cjs/core/UrlUtils.js.map +1 -0
- package/dist/cjs/core/detector.js +293 -0
- package/dist/cjs/core/detector.js.map +1 -0
- package/dist/cjs/core/scorer.js +443 -0
- package/dist/cjs/core/scorer.js.map +1 -0
- package/dist/cjs/index.js +121 -20134
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/utils.js +11 -0
- package/dist/cjs/lib/utils.js.map +1 -0
- package/dist/cjs/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js +6 -0
- package/dist/cjs/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/cjs/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js +3042 -0
- package/dist/cjs/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/dist/cjs/players/DashJsPlayer.js +638 -0
- package/dist/cjs/players/DashJsPlayer.js.map +1 -0
- package/dist/cjs/players/HlsJsPlayer.js +482 -0
- package/dist/cjs/players/HlsJsPlayer.js.map +1 -0
- package/dist/cjs/players/MewsWsPlayer/SourceBufferManager.js +522 -0
- package/dist/cjs/players/MewsWsPlayer/SourceBufferManager.js.map +1 -0
- package/dist/cjs/players/MewsWsPlayer/WebSocketManager.js +215 -0
- package/dist/cjs/players/MewsWsPlayer/WebSocketManager.js.map +1 -0
- package/dist/cjs/players/MewsWsPlayer/index.js +987 -0
- package/dist/cjs/players/MewsWsPlayer/index.js.map +1 -0
- package/dist/cjs/players/MistPlayer.js +185 -0
- package/dist/cjs/players/MistPlayer.js.map +1 -0
- package/dist/cjs/players/MistWebRTCPlayer/index.js +635 -0
- package/dist/cjs/players/MistWebRTCPlayer/index.js.map +1 -0
- package/dist/cjs/players/NativePlayer.js +762 -0
- package/dist/cjs/players/NativePlayer.js.map +1 -0
- package/dist/cjs/players/VideoJsPlayer.js +585 -0
- package/dist/cjs/players/VideoJsPlayer.js.map +1 -0
- package/dist/cjs/players/WebCodecsPlayer/JitterBuffer.js +236 -0
- package/dist/cjs/players/WebCodecsPlayer/JitterBuffer.js.map +1 -0
- package/dist/cjs/players/WebCodecsPlayer/LatencyProfiles.js +143 -0
- package/dist/cjs/players/WebCodecsPlayer/LatencyProfiles.js.map +1 -0
- package/dist/cjs/players/WebCodecsPlayer/RawChunkParser.js +96 -0
- package/dist/cjs/players/WebCodecsPlayer/RawChunkParser.js.map +1 -0
- package/dist/cjs/players/WebCodecsPlayer/SyncController.js +359 -0
- package/dist/cjs/players/WebCodecsPlayer/SyncController.js.map +1 -0
- package/dist/cjs/players/WebCodecsPlayer/WebSocketController.js +460 -0
- package/dist/cjs/players/WebCodecsPlayer/WebSocketController.js.map +1 -0
- package/dist/cjs/players/WebCodecsPlayer/index.js +1467 -0
- package/dist/cjs/players/WebCodecsPlayer/index.js.map +1 -0
- package/dist/cjs/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js +320 -0
- package/dist/cjs/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js.map +1 -0
- package/dist/cjs/styles/index.js +57 -0
- package/dist/cjs/styles/index.js.map +1 -0
- package/dist/cjs/vanilla/FrameWorksPlayer.js +269 -0
- package/dist/cjs/vanilla/FrameWorksPlayer.js.map +1 -0
- package/dist/cjs/vanilla.js +11 -0
- package/dist/cjs/vanilla.js.map +1 -0
- package/dist/esm/core/ABRController.js +454 -0
- package/dist/esm/core/ABRController.js.map +1 -0
- package/dist/esm/core/CodecUtils.js +193 -0
- package/dist/esm/core/CodecUtils.js.map +1 -0
- package/dist/esm/core/ErrorClassifier.js +408 -0
- package/dist/esm/core/ErrorClassifier.js.map +1 -0
- package/dist/esm/core/EventEmitter.js +106 -0
- package/dist/esm/core/EventEmitter.js.map +1 -0
- package/dist/esm/core/GatewayClient.js +340 -0
- package/dist/esm/core/GatewayClient.js.map +1 -0
- package/dist/esm/core/InteractionController.js +604 -0
- package/dist/esm/core/InteractionController.js.map +1 -0
- package/dist/esm/core/LiveDurationProxy.js +184 -0
- package/dist/esm/core/LiveDurationProxy.js.map +1 -0
- package/dist/esm/core/MetaTrackManager.js +622 -0
- package/dist/esm/core/MetaTrackManager.js.map +1 -0
- package/dist/esm/core/MistReporter.js +447 -0
- package/dist/esm/core/MistReporter.js.map +1 -0
- package/dist/esm/core/MistSignaling.js +262 -0
- package/dist/esm/core/MistSignaling.js.map +1 -0
- package/dist/esm/core/PlayerController.js +2651 -0
- package/dist/esm/core/PlayerController.js.map +1 -0
- package/dist/esm/core/PlayerInterface.js +267 -0
- package/dist/esm/core/PlayerInterface.js.map +1 -0
- package/dist/esm/core/PlayerManager.js +804 -0
- package/dist/esm/core/PlayerManager.js.map +1 -0
- package/dist/esm/core/PlayerRegistry.js +264 -0
- package/dist/esm/core/PlayerRegistry.js.map +1 -0
- package/dist/esm/core/QualityMonitor.js +471 -0
- package/dist/esm/core/QualityMonitor.js.map +1 -0
- package/dist/esm/core/SeekingUtils.js +280 -0
- package/dist/esm/core/SeekingUtils.js.map +1 -0
- package/dist/esm/core/StreamStateClient.js +379 -0
- package/dist/esm/core/StreamStateClient.js.map +1 -0
- package/dist/esm/core/SubtitleManager.js +225 -0
- package/dist/esm/core/SubtitleManager.js.map +1 -0
- package/dist/esm/core/TelemetryReporter.js +256 -0
- package/dist/esm/core/TelemetryReporter.js.map +1 -0
- package/dist/esm/core/TimeFormat.js +169 -0
- package/dist/esm/core/TimeFormat.js.map +1 -0
- package/dist/esm/core/TimerManager.js +174 -0
- package/dist/esm/core/TimerManager.js.map +1 -0
- package/dist/esm/core/UrlUtils.js +151 -0
- package/dist/esm/core/UrlUtils.js.map +1 -0
- package/dist/esm/core/detector.js +279 -0
- package/dist/esm/core/detector.js.map +1 -0
- package/dist/esm/core/scorer.js +422 -0
- package/dist/esm/core/scorer.js.map +1 -0
- package/dist/esm/index.js +26 -20043
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/utils.js +9 -0
- package/dist/esm/lib/utils.js.map +1 -0
- package/dist/esm/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js +4 -0
- package/dist/esm/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/esm/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js +3036 -0
- package/dist/esm/node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/dist/esm/players/DashJsPlayer.js +636 -0
- package/dist/esm/players/DashJsPlayer.js.map +1 -0
- package/dist/esm/players/HlsJsPlayer.js +480 -0
- package/dist/esm/players/HlsJsPlayer.js.map +1 -0
- package/dist/esm/players/MewsWsPlayer/SourceBufferManager.js +520 -0
- package/dist/esm/players/MewsWsPlayer/SourceBufferManager.js.map +1 -0
- package/dist/esm/players/MewsWsPlayer/WebSocketManager.js +213 -0
- package/dist/esm/players/MewsWsPlayer/WebSocketManager.js.map +1 -0
- package/dist/esm/players/MewsWsPlayer/index.js +985 -0
- package/dist/esm/players/MewsWsPlayer/index.js.map +1 -0
- package/dist/esm/players/MistPlayer.js +183 -0
- package/dist/esm/players/MistPlayer.js.map +1 -0
- package/dist/esm/players/MistWebRTCPlayer/index.js +633 -0
- package/dist/esm/players/MistWebRTCPlayer/index.js.map +1 -0
- package/dist/esm/players/NativePlayer.js +759 -0
- package/dist/esm/players/NativePlayer.js.map +1 -0
- package/dist/esm/players/VideoJsPlayer.js +583 -0
- package/dist/esm/players/VideoJsPlayer.js.map +1 -0
- package/dist/esm/players/WebCodecsPlayer/JitterBuffer.js +233 -0
- package/dist/esm/players/WebCodecsPlayer/JitterBuffer.js.map +1 -0
- package/dist/esm/players/WebCodecsPlayer/LatencyProfiles.js +134 -0
- package/dist/esm/players/WebCodecsPlayer/LatencyProfiles.js.map +1 -0
- package/dist/esm/players/WebCodecsPlayer/RawChunkParser.js +91 -0
- package/dist/esm/players/WebCodecsPlayer/RawChunkParser.js.map +1 -0
- package/dist/esm/players/WebCodecsPlayer/SyncController.js +357 -0
- package/dist/esm/players/WebCodecsPlayer/SyncController.js.map +1 -0
- package/dist/esm/players/WebCodecsPlayer/WebSocketController.js +458 -0
- package/dist/esm/players/WebCodecsPlayer/WebSocketController.js.map +1 -0
- package/dist/esm/players/WebCodecsPlayer/index.js +1458 -0
- package/dist/esm/players/WebCodecsPlayer/index.js.map +1 -0
- package/dist/esm/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js +315 -0
- package/dist/esm/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.js.map +1 -0
- package/dist/esm/styles/index.js +54 -0
- package/dist/esm/styles/index.js.map +1 -0
- package/dist/esm/vanilla/FrameWorksPlayer.js +264 -0
- package/dist/esm/vanilla/FrameWorksPlayer.js.map +1 -0
- package/dist/esm/vanilla.js +2 -0
- package/dist/esm/vanilla.js.map +1 -0
- package/dist/player.css +185 -42
- package/dist/types/core/ABRController.d.ts +4 -4
- package/dist/types/core/CodecUtils.d.ts +1 -1
- package/dist/types/core/ErrorClassifier.d.ts +77 -0
- package/dist/types/core/GatewayClient.d.ts +4 -4
- package/dist/types/core/MetaTrackManager.d.ts +2 -2
- package/dist/types/core/MistReporter.d.ts +3 -3
- package/dist/types/core/MistSignaling.d.ts +12 -12
- package/dist/types/core/PlayerController.d.ts +19 -14
- package/dist/types/core/PlayerInterface.d.ts +100 -2
- package/dist/types/core/PlayerManager.d.ts +36 -9
- package/dist/types/core/PlayerRegistry.d.ts +11 -11
- package/dist/types/core/QualityMonitor.d.ts +2 -2
- package/dist/types/core/SeekingUtils.d.ts +2 -2
- package/dist/types/core/StreamStateClient.d.ts +2 -2
- package/dist/types/core/TelemetryReporter.d.ts +1 -1
- package/dist/types/core/TimerManager.d.ts +1 -1
- package/dist/types/core/detector.d.ts +1 -1
- package/dist/types/core/index.d.ts +44 -44
- package/dist/types/core/scorer.d.ts +1 -1
- package/dist/types/core/selector.d.ts +2 -2
- package/dist/types/index.d.ts +35 -34
- package/dist/types/players/DashJsPlayer.d.ts +3 -3
- package/dist/types/players/HlsJsPlayer.d.ts +3 -3
- package/dist/types/players/MewsWsPlayer/SourceBufferManager.d.ts +1 -1
- package/dist/types/players/MewsWsPlayer/WebSocketManager.d.ts +1 -1
- package/dist/types/players/MewsWsPlayer/index.d.ts +2 -2
- package/dist/types/players/MewsWsPlayer/types.d.ts +15 -15
- package/dist/types/players/MistPlayer.d.ts +2 -2
- package/dist/types/players/MistWebRTCPlayer/index.d.ts +3 -3
- package/dist/types/players/NativePlayer.d.ts +3 -3
- package/dist/types/players/VideoJsPlayer.d.ts +3 -3
- package/dist/types/players/WebCodecsPlayer/JitterBuffer.d.ts +3 -3
- package/dist/types/players/WebCodecsPlayer/LatencyProfiles.d.ts +1 -1
- package/dist/types/players/WebCodecsPlayer/RawChunkParser.d.ts +2 -2
- package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +2 -2
- package/dist/types/players/WebCodecsPlayer/WebSocketController.d.ts +3 -3
- package/dist/types/players/WebCodecsPlayer/index.d.ts +9 -9
- package/dist/types/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.d.ts +1 -1
- package/dist/types/players/WebCodecsPlayer/types.d.ts +49 -49
- package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +31 -31
- package/dist/types/players/index.d.ts +5 -8
- package/dist/types/types.d.ts +15 -15
- package/dist/types/vanilla/FrameWorksPlayer.d.ts +2 -2
- package/dist/types/vanilla/index.d.ts +4 -4
- package/dist/workers/decoder.worker.js +129 -122
- package/dist/workers/decoder.worker.js.map +1 -1
- package/package.json +31 -15
- package/src/core/ABRController.ts +38 -36
- package/src/core/CodecUtils.ts +49 -46
- package/src/core/Disposable.ts +4 -4
- package/src/core/ErrorClassifier.ts +499 -0
- package/src/core/EventEmitter.ts +1 -1
- package/src/core/GatewayClient.ts +41 -39
- package/src/core/InteractionController.ts +89 -82
- package/src/core/LiveDurationProxy.ts +14 -15
- package/src/core/MetaTrackManager.ts +73 -65
- package/src/core/MistReporter.ts +72 -45
- package/src/core/MistSignaling.ts +59 -56
- package/src/core/PlayerController.ts +542 -384
- package/src/core/PlayerInterface.ts +192 -59
- package/src/core/PlayerManager.ts +354 -164
- package/src/core/PlayerRegistry.ts +238 -87
- package/src/core/QualityMonitor.ts +38 -31
- package/src/core/ScreenWakeLockManager.ts +8 -9
- package/src/core/SeekingUtils.ts +31 -22
- package/src/core/StreamStateClient.ts +74 -68
- package/src/core/SubtitleManager.ts +24 -22
- package/src/core/TelemetryReporter.ts +38 -32
- package/src/core/TimeFormat.ts +13 -17
- package/src/core/TimerManager.ts +24 -8
- package/src/core/UrlUtils.ts +20 -17
- package/src/core/detector.ts +44 -44
- package/src/core/index.ts +57 -48
- package/src/core/scorer.ts +136 -141
- package/src/core/selector.ts +2 -6
- package/src/global.d.ts +1 -1
- package/src/index.ts +56 -36
- package/src/players/DashJsPlayer.ts +164 -115
- package/src/players/HlsJsPlayer.ts +132 -78
- package/src/players/MewsWsPlayer/SourceBufferManager.ts +41 -36
- package/src/players/MewsWsPlayer/WebSocketManager.ts +9 -9
- package/src/players/MewsWsPlayer/index.ts +192 -152
- package/src/players/MewsWsPlayer/types.ts +21 -21
- package/src/players/MistPlayer.ts +45 -26
- package/src/players/MistWebRTCPlayer/index.ts +175 -129
- package/src/players/NativePlayer.ts +203 -143
- package/src/players/VideoJsPlayer.ts +170 -118
- package/src/players/WebCodecsPlayer/JitterBuffer.ts +6 -7
- package/src/players/WebCodecsPlayer/LatencyProfiles.ts +43 -43
- package/src/players/WebCodecsPlayer/RawChunkParser.ts +10 -10
- package/src/players/WebCodecsPlayer/SyncController.ts +45 -53
- package/src/players/WebCodecsPlayer/WebSocketController.ts +66 -68
- package/src/players/WebCodecsPlayer/index.ts +265 -223
- package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +12 -17
- package/src/players/WebCodecsPlayer/types.ts +56 -56
- package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +238 -182
- package/src/players/WebCodecsPlayer/worker/types.ts +31 -31
- package/src/players/index.ts +5 -16
- package/src/styles/animations.css +2 -1
- package/src/styles/player.css +185 -42
- package/src/styles/tailwind.css +473 -159
- package/src/types.ts +43 -43
- package/src/vanilla/FrameWorksPlayer.ts +26 -14
- package/src/vanilla/index.ts +4 -4
|
@@ -1,110 +1,262 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Player Registry
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Lazy registration of player implementations. Capabilities are declared
|
|
5
|
+
* statically so MIME-based filtering happens without importing any player
|
|
6
|
+
* modules. Only the players matching the stream's source types are loaded.
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
|
-
import { PlayerManager } from
|
|
8
|
-
import type { IPlayer } from
|
|
9
|
+
import { PlayerManager } from "./PlayerManager";
|
|
10
|
+
import type { IPlayer, PlayerCapability } from "./PlayerInterface";
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Lazy Player Entry
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
interface LazyPlayerEntry {
|
|
17
|
+
capability: PlayerCapability;
|
|
18
|
+
load: () => Promise<IPlayer>;
|
|
19
|
+
}
|
|
9
20
|
|
|
10
21
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
22
|
+
* Static capability registry. Each entry declares its capabilities (MIME types,
|
|
23
|
+
* priority) and a lazy loader that dynamically imports the implementation.
|
|
24
|
+
* No player code is loaded until `load()` is called.
|
|
13
25
|
*/
|
|
14
|
-
const
|
|
26
|
+
const PLAYER_ENTRIES: LazyPlayerEntry[] = [
|
|
27
|
+
{
|
|
28
|
+
capability: {
|
|
29
|
+
name: "Native Player",
|
|
30
|
+
shortname: "native",
|
|
31
|
+
priority: 1,
|
|
32
|
+
mimes: [
|
|
33
|
+
"html5/video/mp4",
|
|
34
|
+
"html5/video/webm",
|
|
35
|
+
"html5/video/ogg",
|
|
36
|
+
"html5/audio/mp3",
|
|
37
|
+
"html5/audio/webm",
|
|
38
|
+
"html5/audio/ogg",
|
|
39
|
+
"html5/audio/wav",
|
|
40
|
+
"html5/application/vnd.apple.mpegurl",
|
|
41
|
+
"html5/application/vnd.apple.mpegurl;version=7",
|
|
42
|
+
"whep",
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
load: () => import("../players/NativePlayer").then((m) => new m.NativePlayerImpl()),
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
capability: {
|
|
49
|
+
name: "WebCodecs Player",
|
|
50
|
+
shortname: "webcodecs",
|
|
51
|
+
priority: 0,
|
|
52
|
+
mimes: ["ws/video/raw", "wss/video/raw", "ws/video/h264", "wss/video/h264"],
|
|
53
|
+
},
|
|
54
|
+
load: () => import("../players/WebCodecsPlayer").then((m) => new m.WebCodecsPlayerImpl()),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
capability: {
|
|
58
|
+
name: "MistServer WebRTC",
|
|
59
|
+
shortname: "mist-webrtc",
|
|
60
|
+
priority: 2,
|
|
61
|
+
mimes: ["webrtc", "mist/webrtc"],
|
|
62
|
+
},
|
|
63
|
+
load: () => import("../players/MistWebRTCPlayer").then((m) => new m.MistWebRTCPlayerImpl()),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
capability: {
|
|
67
|
+
name: "Video.js Player",
|
|
68
|
+
shortname: "videojs",
|
|
69
|
+
priority: 2,
|
|
70
|
+
mimes: [
|
|
71
|
+
"html5/application/vnd.apple.mpegurl",
|
|
72
|
+
"html5/application/vnd.apple.mpegurl;version=7",
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
load: () => import("../players/VideoJsPlayer").then((m) => new m.VideoJsPlayerImpl()),
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
capability: {
|
|
79
|
+
name: "HLS.js Player",
|
|
80
|
+
shortname: "hlsjs",
|
|
81
|
+
priority: 3,
|
|
82
|
+
mimes: [
|
|
83
|
+
"html5/application/vnd.apple.mpegurl",
|
|
84
|
+
"html5/application/vnd.apple.mpegurl;version=7",
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
load: () => import("../players/HlsJsPlayer").then((m) => new m.HlsJsPlayerImpl()),
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
capability: {
|
|
91
|
+
name: "Dash.js Player",
|
|
92
|
+
shortname: "dashjs",
|
|
93
|
+
priority: 100,
|
|
94
|
+
mimes: ["dash/video/mp4"],
|
|
95
|
+
},
|
|
96
|
+
load: () => import("../players/DashJsPlayer").then((m) => new m.DashJsPlayerImpl()),
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
capability: {
|
|
100
|
+
name: "Legacy",
|
|
101
|
+
shortname: "mist-legacy",
|
|
102
|
+
priority: 99,
|
|
103
|
+
mimes: ["mist/legacy"],
|
|
104
|
+
},
|
|
105
|
+
load: () => import("../players/MistPlayer").then((m) => new m.MistPlayerImpl()),
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
capability: {
|
|
109
|
+
name: "MEWS WebSocket Player",
|
|
110
|
+
shortname: "mews",
|
|
111
|
+
priority: 2,
|
|
112
|
+
mimes: ["ws/video/mp4", "wss/video/mp4", "ws/video/webm", "wss/video/webm"],
|
|
113
|
+
},
|
|
114
|
+
load: () => import("../players/MewsWsPlayer").then((m) => new m.MewsWsPlayerImpl()),
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
// ============================================================================
|
|
119
|
+
// Loading State
|
|
120
|
+
// ============================================================================
|
|
121
|
+
|
|
122
|
+
/** Track which players have been loaded per manager */
|
|
123
|
+
const loadedPlayersMap = new WeakMap<PlayerManager, Set<string>>();
|
|
15
124
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
125
|
+
function getLoadedSet(manager: PlayerManager): Set<string> {
|
|
126
|
+
let set = loadedPlayersMap.get(manager);
|
|
127
|
+
if (!set) {
|
|
128
|
+
set = new Set();
|
|
129
|
+
loadedPlayersMap.set(manager, set);
|
|
21
130
|
}
|
|
131
|
+
return set;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Load only players whose capabilities match the given source MIME types.
|
|
136
|
+
* Already-loaded players are skipped. Safe to call multiple times with
|
|
137
|
+
* different MIME types — new players are added incrementally.
|
|
138
|
+
*/
|
|
139
|
+
async function loadMatchingPlayers(manager: PlayerManager, sourceMimes: string[]): Promise<void> {
|
|
140
|
+
const loaded = getLoadedSet(manager);
|
|
141
|
+
|
|
142
|
+
const toLoad = PLAYER_ENTRIES.filter((entry) => {
|
|
143
|
+
if (loaded.has(entry.capability.shortname)) return false;
|
|
144
|
+
return entry.capability.mimes.some((m) => sourceMimes.includes(m));
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (toLoad.length === 0) return;
|
|
22
148
|
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
videoModule,
|
|
27
|
-
hlsModule,
|
|
28
|
-
dashModule,
|
|
29
|
-
mistModule,
|
|
30
|
-
mewsModule,
|
|
31
|
-
mistWebRTCModule,
|
|
32
|
-
webCodecsModule
|
|
33
|
-
] = await Promise.all([
|
|
34
|
-
import('../players/NativePlayer'),
|
|
35
|
-
import('../players/VideoJsPlayer'),
|
|
36
|
-
import('../players/HlsJsPlayer'),
|
|
37
|
-
import('../players/DashJsPlayer'),
|
|
38
|
-
import('../players/MistPlayer'),
|
|
39
|
-
import('../players/MewsWsPlayer'),
|
|
40
|
-
import('../players/MistWebRTCPlayer'),
|
|
41
|
-
import('../players/WebCodecsPlayer')
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
console.log('[PlayerRegistry] All player modules imported, instantiating...');
|
|
45
|
-
const instantiatedPlayers: IPlayer[] = [
|
|
46
|
-
new nativeModule.NativePlayerImpl(),
|
|
47
|
-
new webCodecsModule.WebCodecsPlayerImpl(), // Priority 1 - lowest latency
|
|
48
|
-
new mistWebRTCModule.MistWebRTCPlayerImpl(), // Priority 2
|
|
49
|
-
new videoModule.VideoJsPlayerImpl(),
|
|
50
|
-
new hlsModule.HlsJsPlayerImpl(),
|
|
51
|
-
new dashModule.DashJsPlayerImpl(),
|
|
52
|
-
new mistModule.MistPlayerImpl(),
|
|
53
|
-
new mewsModule.MewsWsPlayerImpl()
|
|
54
|
-
];
|
|
55
|
-
|
|
56
|
-
for (const player of instantiatedPlayers) {
|
|
149
|
+
const players = await Promise.all(toLoad.map((e) => e.load()));
|
|
150
|
+
for (const player of players) {
|
|
151
|
+
loaded.add(player.capability.shortname);
|
|
57
152
|
const alreadyRegistered = manager
|
|
58
153
|
.getRegisteredPlayers()
|
|
59
|
-
.some(
|
|
60
|
-
|
|
154
|
+
.some((p) => p.capability.shortname === player.capability.shortname);
|
|
61
155
|
if (!alreadyRegistered) {
|
|
62
156
|
manager.registerPlayer(player);
|
|
63
157
|
}
|
|
64
158
|
}
|
|
65
|
-
console.log(`[PlayerRegistry] Registration complete. ${manager.getRegisteredPlayers().length} players registered.`);
|
|
66
159
|
}
|
|
67
160
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Load a specific player by shortname. Used for forcePlayer support.
|
|
163
|
+
*/
|
|
164
|
+
async function loadPlayerByShortname(manager: PlayerManager, shortname: string): Promise<void> {
|
|
165
|
+
const loaded = getLoadedSet(manager);
|
|
166
|
+
if (loaded.has(shortname)) return;
|
|
167
|
+
|
|
168
|
+
const entry = PLAYER_ENTRIES.find((e) => e.capability.shortname === shortname);
|
|
169
|
+
if (!entry) return;
|
|
170
|
+
|
|
171
|
+
const player = await entry.load();
|
|
172
|
+
loaded.add(player.capability.shortname);
|
|
173
|
+
const alreadyRegistered = manager
|
|
174
|
+
.getRegisteredPlayers()
|
|
175
|
+
.some((p) => p.capability.shortname === player.capability.shortname);
|
|
176
|
+
if (!alreadyRegistered) {
|
|
177
|
+
manager.registerPlayer(player);
|
|
73
178
|
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Load all players. Used for backwards compatibility (createPlayerManager,
|
|
183
|
+
* registerAllPlayers) and when no MIME filter is available.
|
|
184
|
+
*/
|
|
185
|
+
async function loadAllPlayers(manager: PlayerManager): Promise<void> {
|
|
186
|
+
const allMimes = PLAYER_ENTRIES.flatMap((e) => e.capability.mimes);
|
|
187
|
+
return loadMatchingPlayers(manager, allMimes);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ============================================================================
|
|
191
|
+
// Public API
|
|
192
|
+
// ============================================================================
|
|
193
|
+
|
|
194
|
+
/** Deduplication promises for full registration (loadAllPlayers) */
|
|
195
|
+
const fullRegistrationPromises = new WeakMap<PlayerManager, Promise<void>>();
|
|
74
196
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Ensure all players are registered. Backwards-compatible API that loads
|
|
199
|
+
* every player module. Prefer the MIME-filtered path via initializePlayer.
|
|
200
|
+
*/
|
|
201
|
+
export function ensurePlayersRegistered(
|
|
202
|
+
manager: PlayerManager = globalPlayerManager
|
|
203
|
+
): Promise<void> {
|
|
204
|
+
const loaded = getLoadedSet(manager);
|
|
205
|
+
if (loaded.size === PLAYER_ENTRIES.length) {
|
|
206
|
+
return Promise.resolve();
|
|
79
207
|
}
|
|
80
208
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
209
|
+
const existing = fullRegistrationPromises.get(manager);
|
|
210
|
+
if (existing) return existing;
|
|
211
|
+
|
|
212
|
+
const promise = loadAllPlayers(manager).catch((error) => {
|
|
213
|
+
console.error("[PlayerRegistry] Registration failed:", error);
|
|
214
|
+
fullRegistrationPromises.delete(manager);
|
|
85
215
|
throw error;
|
|
86
216
|
});
|
|
87
217
|
|
|
88
|
-
|
|
89
|
-
return
|
|
218
|
+
fullRegistrationPromises.set(manager, promise);
|
|
219
|
+
return promise;
|
|
90
220
|
}
|
|
91
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Monkey-patch initializePlayer to lazily load only matching players.
|
|
224
|
+
* Extracts source MIME types from streamInfo and loads the subset of
|
|
225
|
+
* player modules that can handle those types.
|
|
226
|
+
*/
|
|
92
227
|
const originalInitialize = PlayerManager.prototype.initializePlayer;
|
|
93
|
-
PlayerManager.prototype.initializePlayer = async function (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
228
|
+
PlayerManager.prototype.initializePlayer = async function (
|
|
229
|
+
...args: Parameters<PlayerManager["initializePlayer"]>
|
|
230
|
+
) {
|
|
231
|
+
const [_container, streamInfo, _playerOptions, managerOptions] = args;
|
|
232
|
+
const sourceMimes = streamInfo?.source?.map((s) => s.type) ?? [];
|
|
233
|
+
|
|
234
|
+
if (sourceMimes.length > 0) {
|
|
235
|
+
// Load only players matching the stream's source types
|
|
236
|
+
await loadMatchingPlayers(this, sourceMimes);
|
|
237
|
+
|
|
238
|
+
// Also load a forced player if specified
|
|
239
|
+
if (managerOptions?.forcePlayer) {
|
|
240
|
+
await loadPlayerByShortname(this, managerOptions.forcePlayer);
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
// No source info — fall back to loading all
|
|
244
|
+
await ensurePlayersRegistered(this);
|
|
245
|
+
}
|
|
246
|
+
|
|
97
247
|
return originalInitialize.apply(this, args);
|
|
98
248
|
};
|
|
99
249
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
250
|
+
// ============================================================================
|
|
251
|
+
// Global Instance
|
|
252
|
+
// ============================================================================
|
|
253
|
+
|
|
103
254
|
const isDev = (() => {
|
|
104
255
|
try {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
256
|
+
const g = globalThis as Record<string, unknown>;
|
|
257
|
+
const p = g.process as Record<string, unknown> | undefined;
|
|
258
|
+
const env = p?.env as Record<string, unknown> | undefined;
|
|
259
|
+
return env?.NODE_ENV === "development";
|
|
108
260
|
} catch {
|
|
109
261
|
return false;
|
|
110
262
|
}
|
|
@@ -113,37 +265,36 @@ const isDev = (() => {
|
|
|
113
265
|
export const globalPlayerManager = new PlayerManager({
|
|
114
266
|
debug: isDev,
|
|
115
267
|
autoFallback: true,
|
|
116
|
-
maxFallbackAttempts: 3
|
|
268
|
+
maxFallbackAttempts: 3,
|
|
117
269
|
});
|
|
118
270
|
|
|
119
271
|
/**
|
|
120
272
|
* Register all available players (async for backwards compatibility)
|
|
121
273
|
*/
|
|
122
|
-
export async function registerAllPlayers(
|
|
274
|
+
export async function registerAllPlayers(
|
|
275
|
+
manager: PlayerManager = globalPlayerManager
|
|
276
|
+
): Promise<void> {
|
|
123
277
|
await ensurePlayersRegistered(manager);
|
|
124
278
|
}
|
|
125
279
|
|
|
126
280
|
/**
|
|
127
281
|
* Create a new PlayerManager instance with all players registered
|
|
128
282
|
*/
|
|
129
|
-
export function createPlayerManager(
|
|
283
|
+
export function createPlayerManager(
|
|
284
|
+
options?: ConstructorParameters<typeof PlayerManager>[0]
|
|
285
|
+
): PlayerManager {
|
|
130
286
|
const manager = new PlayerManager(options);
|
|
131
|
-
ensurePlayersRegistered(manager).catch(error => {
|
|
287
|
+
ensurePlayersRegistered(manager).catch((error) => {
|
|
132
288
|
if (isDev) {
|
|
133
|
-
console.warn(
|
|
289
|
+
console.warn("Player registration failed:", error);
|
|
134
290
|
}
|
|
135
291
|
});
|
|
136
292
|
return manager;
|
|
137
293
|
}
|
|
138
294
|
|
|
139
295
|
/**
|
|
140
|
-
*
|
|
296
|
+
* Get the static capability registry (for UI display without loading modules)
|
|
141
297
|
*/
|
|
142
|
-
export
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
export { VideoJsPlayerImpl } from '../players/VideoJsPlayer';
|
|
146
|
-
export { MistPlayerImpl } from '../players/MistPlayer';
|
|
147
|
-
export { MewsWsPlayerImpl } from '../players/MewsWsPlayer';
|
|
148
|
-
export { MistWebRTCPlayerImpl } from '../players/MistWebRTCPlayer';
|
|
149
|
-
export { WebCodecsPlayerImpl } from '../players/WebCodecsPlayer';
|
|
298
|
+
export function getAvailablePlayerCapabilities(): PlayerCapability[] {
|
|
299
|
+
return PLAYER_ENTRIES.map((e) => e.capability);
|
|
300
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { PlaybackQuality, QualityThresholds } from
|
|
2
|
-
import { TimerManager } from
|
|
1
|
+
import type { PlaybackQuality, QualityThresholds } from "../types";
|
|
2
|
+
import { TimerManager } from "./TimerManager";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Default quality thresholds
|
|
@@ -19,21 +19,21 @@ const ROLLING_WINDOW_SIZE = 20;
|
|
|
19
19
|
* Playback score history entry (for MistPlayer-style 0-2.0 score)
|
|
20
20
|
*/
|
|
21
21
|
interface PlaybackScoreEntry {
|
|
22
|
-
clock: number;
|
|
23
|
-
video: number;
|
|
24
|
-
score: number;
|
|
22
|
+
clock: number; // Wall clock time in seconds
|
|
23
|
+
video: number; // Video currentTime
|
|
24
|
+
score: number; // Calculated score for this sample
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/** Protocol type for threshold selection */
|
|
28
|
-
export type PlayerProtocol =
|
|
28
|
+
export type PlayerProtocol = "webrtc" | "hls" | "dash" | "html5" | "unknown";
|
|
29
29
|
|
|
30
30
|
/** Protocol-specific playback score thresholds (MistMetaPlayer reference) */
|
|
31
31
|
export const PROTOCOL_THRESHOLDS: Record<PlayerProtocol, number> = {
|
|
32
|
-
webrtc: 0.95,
|
|
33
|
-
hls: 0.75,
|
|
34
|
-
dash: 0.75,
|
|
35
|
-
html5: 0.75,
|
|
36
|
-
unknown: 0.75,
|
|
32
|
+
webrtc: 0.95, // Very strict for low-latency
|
|
33
|
+
hls: 0.75, // More lenient for adaptive streaming
|
|
34
|
+
dash: 0.75, // More lenient for adaptive streaming
|
|
35
|
+
html5: 0.75, // Standard threshold
|
|
36
|
+
unknown: 0.75, // Default
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
export interface QualityMonitorOptions {
|
|
@@ -82,7 +82,7 @@ export interface QualityMonitorState {
|
|
|
82
82
|
*/
|
|
83
83
|
export class QualityMonitor {
|
|
84
84
|
private videoElement: HTMLVideoElement | null = null;
|
|
85
|
-
private options: Required<Omit<QualityMonitorOptions,
|
|
85
|
+
private options: Required<Omit<QualityMonitorOptions, "protocol" | "playbackScoreThreshold">> & {
|
|
86
86
|
protocol: PlayerProtocol;
|
|
87
87
|
playbackScoreThreshold: number | null;
|
|
88
88
|
};
|
|
@@ -112,7 +112,7 @@ export class QualityMonitor {
|
|
|
112
112
|
thresholds: options.thresholds ?? {},
|
|
113
113
|
onQualityDegraded: options.onQualityDegraded ?? (() => {}),
|
|
114
114
|
onSample: options.onSample ?? (() => {}),
|
|
115
|
-
protocol: options.protocol ??
|
|
115
|
+
protocol: options.protocol ?? "unknown",
|
|
116
116
|
playbackScoreThreshold: options.playbackScoreThreshold ?? null,
|
|
117
117
|
onFallbackRequest: options.onFallbackRequest ?? (() => {}),
|
|
118
118
|
poorSamplesBeforeFallback: options.poorSamplesBeforeFallback ?? 5,
|
|
@@ -190,18 +190,18 @@ export class QualityMonitor {
|
|
|
190
190
|
}
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
-
videoElement.addEventListener(
|
|
194
|
-
videoElement.addEventListener(
|
|
195
|
-
videoElement.addEventListener(
|
|
193
|
+
videoElement.addEventListener("waiting", onWaiting);
|
|
194
|
+
videoElement.addEventListener("playing", onPlaying);
|
|
195
|
+
videoElement.addEventListener("canplay", onCanPlay);
|
|
196
196
|
|
|
197
197
|
this.listeners = [
|
|
198
|
-
() => videoElement.removeEventListener(
|
|
199
|
-
() => videoElement.removeEventListener(
|
|
200
|
-
() => videoElement.removeEventListener(
|
|
198
|
+
() => videoElement.removeEventListener("waiting", onWaiting),
|
|
199
|
+
() => videoElement.removeEventListener("playing", onPlaying),
|
|
200
|
+
() => videoElement.removeEventListener("canplay", onCanPlay),
|
|
201
201
|
];
|
|
202
202
|
|
|
203
203
|
// Start sampling interval
|
|
204
|
-
this.timers.startInterval(() => this.sample(), this.options.sampleInterval,
|
|
204
|
+
this.timers.startInterval(() => this.sample(), this.options.sampleInterval, "sampling");
|
|
205
205
|
|
|
206
206
|
// Take initial sample
|
|
207
207
|
this.sample();
|
|
@@ -213,7 +213,7 @@ export class QualityMonitor {
|
|
|
213
213
|
stop(): void {
|
|
214
214
|
this.timers.destroy();
|
|
215
215
|
|
|
216
|
-
this.listeners.forEach(cleanup => cleanup());
|
|
216
|
+
this.listeners.forEach((cleanup) => cleanup());
|
|
217
217
|
this.listeners = [];
|
|
218
218
|
|
|
219
219
|
this.videoElement = null;
|
|
@@ -241,9 +241,11 @@ export class QualityMonitor {
|
|
|
241
241
|
this.options.onSample(quality);
|
|
242
242
|
|
|
243
243
|
// Check for quality degradation
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
244
|
+
if (
|
|
245
|
+
quality.score < this.thresholds.minScore ||
|
|
246
|
+
quality.stallCount > this.thresholds.maxStalls ||
|
|
247
|
+
quality.bufferedAhead < this.thresholds.minBuffer
|
|
248
|
+
) {
|
|
247
249
|
this.options.onQualityDegraded(quality);
|
|
248
250
|
}
|
|
249
251
|
|
|
@@ -254,13 +256,15 @@ export class QualityMonitor {
|
|
|
254
256
|
|
|
255
257
|
// Trigger fallback after sustained poor quality
|
|
256
258
|
// Only trigger once until quality improves or reset
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
+
if (
|
|
260
|
+
!this.fallbackTriggered &&
|
|
261
|
+
this.consecutivePoorSamples >= this.options.poorSamplesBeforeFallback
|
|
262
|
+
) {
|
|
259
263
|
this.fallbackTriggered = true;
|
|
260
264
|
console.warn(
|
|
261
265
|
`[QualityMonitor] Poor playback detected: ${Math.round(this.playbackScore * 100)}% ` +
|
|
262
|
-
|
|
263
|
-
|
|
266
|
+
`(threshold: ${Math.round(this.getPlaybackScoreThreshold() * 100)}%, ` +
|
|
267
|
+
`protocol: ${this.options.protocol})`
|
|
264
268
|
);
|
|
265
269
|
this.options.onFallbackRequest({
|
|
266
270
|
score: this.playbackScore,
|
|
@@ -284,7 +288,10 @@ export class QualityMonitor {
|
|
|
284
288
|
let bufferedAhead = 0;
|
|
285
289
|
if (video.buffered.length > 0) {
|
|
286
290
|
for (let i = 0; i < video.buffered.length; i++) {
|
|
287
|
-
if (
|
|
291
|
+
if (
|
|
292
|
+
video.buffered.start(i) <= video.currentTime &&
|
|
293
|
+
video.buffered.end(i) > video.currentTime
|
|
294
|
+
) {
|
|
288
295
|
bufferedAhead = video.buffered.end(i) - video.currentTime;
|
|
289
296
|
break;
|
|
290
297
|
}
|
|
@@ -296,7 +303,7 @@ export class QualityMonitor {
|
|
|
296
303
|
let framesDropped = 0;
|
|
297
304
|
let frameDropRate = 0;
|
|
298
305
|
|
|
299
|
-
if (
|
|
306
|
+
if ("getVideoPlaybackQuality" in video) {
|
|
300
307
|
const stats = video.getVideoPlaybackQuality();
|
|
301
308
|
framesDecoded = stats.totalVideoFrames;
|
|
302
309
|
framesDropped = stats.droppedVideoFrames;
|
|
@@ -505,7 +512,7 @@ export class QualityMonitor {
|
|
|
505
512
|
|
|
506
513
|
if (clockDelta <= 0) return 1.0;
|
|
507
514
|
|
|
508
|
-
return
|
|
515
|
+
return videoDelta / clockDelta / rate;
|
|
509
516
|
}
|
|
510
517
|
|
|
511
518
|
/**
|
|
@@ -32,13 +32,13 @@ export class ScreenWakeLockManager {
|
|
|
32
32
|
|
|
33
33
|
constructor(config: ScreenWakeLockConfig = {}) {
|
|
34
34
|
this.config = config;
|
|
35
|
-
this.isSupported =
|
|
35
|
+
this.isSupported = "wakeLock" in navigator;
|
|
36
36
|
|
|
37
37
|
this.boundVisibilityChange = this.handleVisibilityChange.bind(this);
|
|
38
38
|
|
|
39
39
|
// Re-acquire wake lock when page becomes visible again
|
|
40
40
|
if (this.isSupported) {
|
|
41
|
-
document.addEventListener(
|
|
41
|
+
document.addEventListener("visibilitychange", this.boundVisibilityChange);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -46,7 +46,7 @@ export class ScreenWakeLockManager {
|
|
|
46
46
|
* Check if Screen Wake Lock API is supported
|
|
47
47
|
*/
|
|
48
48
|
static isSupported(): boolean {
|
|
49
|
-
return
|
|
49
|
+
return "wakeLock" in navigator;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -85,8 +85,8 @@ export class ScreenWakeLockManager {
|
|
|
85
85
|
if (this.wakeLock) return;
|
|
86
86
|
|
|
87
87
|
try {
|
|
88
|
-
this.wakeLock = await navigator.wakeLock.request(
|
|
89
|
-
this.wakeLock.addEventListener(
|
|
88
|
+
this.wakeLock = await navigator.wakeLock.request("screen");
|
|
89
|
+
this.wakeLock.addEventListener("release", this.handleRelease.bind(this));
|
|
90
90
|
this.config.onAcquire?.();
|
|
91
91
|
} catch (err) {
|
|
92
92
|
// Wake lock request can fail if:
|
|
@@ -119,7 +119,7 @@ export class ScreenWakeLockManager {
|
|
|
119
119
|
this.release();
|
|
120
120
|
|
|
121
121
|
if (this.isSupported) {
|
|
122
|
-
document.removeEventListener(
|
|
122
|
+
document.removeEventListener("visibilitychange", this.boundVisibilityChange);
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -127,8 +127,7 @@ export class ScreenWakeLockManager {
|
|
|
127
127
|
* Update wake lock based on current state
|
|
128
128
|
*/
|
|
129
129
|
private updateWakeLock(): void {
|
|
130
|
-
const shouldHold =
|
|
131
|
-
this.isPlaying && (this.isFullscreen || this.config.acquireOnPlay);
|
|
130
|
+
const shouldHold = this.isPlaying && (this.isFullscreen || this.config.acquireOnPlay);
|
|
132
131
|
|
|
133
132
|
if (shouldHold && !this.wakeLock) {
|
|
134
133
|
this.acquire();
|
|
@@ -154,7 +153,7 @@ export class ScreenWakeLockManager {
|
|
|
154
153
|
* Handle visibility change - re-acquire if page becomes visible
|
|
155
154
|
*/
|
|
156
155
|
private handleVisibilityChange(): void {
|
|
157
|
-
if (document.visibilityState ===
|
|
156
|
+
if (document.visibilityState === "visible" && !this.wakeLock) {
|
|
158
157
|
this.updateWakeLock();
|
|
159
158
|
}
|
|
160
159
|
}
|