@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
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Common Player Interface
|
|
5
|
+
*
|
|
6
|
+
* All player implementations must implement this interface to ensure
|
|
7
|
+
* consistent behavior and enable the PlayerManager selection system
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Error severity levels for the tiered error handling system.
|
|
11
|
+
*
|
|
12
|
+
* Tier 1 (TRANSIENT): Silent retry, no UI - network timeouts, brief stalls
|
|
13
|
+
* Tier 2 (RECOVERABLE): Protocol swap with toast - alternatives exist
|
|
14
|
+
* Tier 3 (DEGRADED): Quality drop with toast - playback continues at lower quality
|
|
15
|
+
* Tier 4 (FATAL): Blocking modal - all options exhausted
|
|
16
|
+
*/
|
|
17
|
+
exports.ErrorSeverity = void 0;
|
|
18
|
+
(function (ErrorSeverity) {
|
|
19
|
+
/** Transient issues that self-resolve. User never sees UI. */
|
|
20
|
+
ErrorSeverity[ErrorSeverity["TRANSIENT"] = 1] = "TRANSIENT";
|
|
21
|
+
/** Current protocol failed but alternatives exist. Shows toast on swap. */
|
|
22
|
+
ErrorSeverity[ErrorSeverity["RECOVERABLE"] = 2] = "RECOVERABLE";
|
|
23
|
+
/** Quality degraded but playback continues. Shows informational toast. */
|
|
24
|
+
ErrorSeverity[ErrorSeverity["DEGRADED"] = 3] = "DEGRADED";
|
|
25
|
+
/** Cannot continue playback. Shows blocking error modal. */
|
|
26
|
+
ErrorSeverity[ErrorSeverity["FATAL"] = 4] = "FATAL";
|
|
27
|
+
})(exports.ErrorSeverity || (exports.ErrorSeverity = {}));
|
|
28
|
+
/**
|
|
29
|
+
* Error codes for classification. Maps to specific recovery strategies.
|
|
30
|
+
*/
|
|
31
|
+
exports.ErrorCode = void 0;
|
|
32
|
+
(function (ErrorCode) {
|
|
33
|
+
// Tier 1: Silent recovery
|
|
34
|
+
ErrorCode["NETWORK_TIMEOUT"] = "NETWORK_TIMEOUT";
|
|
35
|
+
ErrorCode["WEBSOCKET_DISCONNECT"] = "WEBSOCKET_DISCONNECT";
|
|
36
|
+
ErrorCode["SEGMENT_LOAD_ERROR"] = "SEGMENT_LOAD_ERROR";
|
|
37
|
+
ErrorCode["ICE_DISCONNECTED"] = "ICE_DISCONNECTED";
|
|
38
|
+
ErrorCode["BUFFER_UNDERRUN"] = "BUFFER_UNDERRUN";
|
|
39
|
+
ErrorCode["CODEC_DECODE_ERROR"] = "CODEC_DECODE_ERROR";
|
|
40
|
+
// Tier 2: Protocol swap
|
|
41
|
+
ErrorCode["PROTOCOL_UNSUPPORTED"] = "PROTOCOL_UNSUPPORTED";
|
|
42
|
+
ErrorCode["CODEC_INCOMPATIBLE"] = "CODEC_INCOMPATIBLE";
|
|
43
|
+
ErrorCode["ICE_FAILED"] = "ICE_FAILED";
|
|
44
|
+
ErrorCode["MANIFEST_STALE"] = "MANIFEST_STALE";
|
|
45
|
+
ErrorCode["PLAYER_INIT_FAILED"] = "PLAYER_INIT_FAILED";
|
|
46
|
+
// Tier 3: Quality degraded
|
|
47
|
+
ErrorCode["QUALITY_DROPPED"] = "QUALITY_DROPPED";
|
|
48
|
+
ErrorCode["BANDWIDTH_LIMITED"] = "BANDWIDTH_LIMITED";
|
|
49
|
+
// Tier 4: Fatal
|
|
50
|
+
ErrorCode["ALL_PROTOCOLS_EXHAUSTED"] = "ALL_PROTOCOLS_EXHAUSTED";
|
|
51
|
+
ErrorCode["ALL_PROTOCOLS_BLACKLISTED"] = "ALL_PROTOCOLS_BLACKLISTED";
|
|
52
|
+
ErrorCode["STREAM_OFFLINE"] = "STREAM_OFFLINE";
|
|
53
|
+
ErrorCode["AUTH_REQUIRED"] = "AUTH_REQUIRED";
|
|
54
|
+
ErrorCode["GEO_BLOCKED"] = "GEO_BLOCKED";
|
|
55
|
+
ErrorCode["DRM_ERROR"] = "DRM_ERROR";
|
|
56
|
+
ErrorCode["CONTENT_UNAVAILABLE"] = "CONTENT_UNAVAILABLE";
|
|
57
|
+
ErrorCode["UNKNOWN"] = "UNKNOWN";
|
|
58
|
+
})(exports.ErrorCode || (exports.ErrorCode = {}));
|
|
59
|
+
/**
|
|
60
|
+
* Base class providing common functionality
|
|
61
|
+
*/
|
|
62
|
+
class BasePlayer {
|
|
63
|
+
constructor() {
|
|
64
|
+
this.listeners = new Map();
|
|
65
|
+
this.videoElement = null;
|
|
66
|
+
}
|
|
67
|
+
getVideoElement() {
|
|
68
|
+
return this.videoElement;
|
|
69
|
+
}
|
|
70
|
+
on(event, listener) {
|
|
71
|
+
if (!this.listeners.has(event)) {
|
|
72
|
+
this.listeners.set(event, new Set());
|
|
73
|
+
}
|
|
74
|
+
this.listeners.get(event).add(listener);
|
|
75
|
+
}
|
|
76
|
+
off(event, listener) {
|
|
77
|
+
const eventListeners = this.listeners.get(event);
|
|
78
|
+
if (eventListeners) {
|
|
79
|
+
eventListeners.delete(listener);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
emit(event, data) {
|
|
83
|
+
const eventListeners = this.listeners.get(event);
|
|
84
|
+
if (eventListeners) {
|
|
85
|
+
eventListeners.forEach((listener) => {
|
|
86
|
+
try {
|
|
87
|
+
listener(data);
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
console.error(`Error in ${event} listener:`, e);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
setupVideoEventListeners(video, options) {
|
|
96
|
+
const handleEvent = (eventName, handler) => {
|
|
97
|
+
const listener = () => {
|
|
98
|
+
handler();
|
|
99
|
+
this.emit(eventName, undefined);
|
|
100
|
+
};
|
|
101
|
+
video.addEventListener(eventName, listener);
|
|
102
|
+
};
|
|
103
|
+
// Core playback events
|
|
104
|
+
handleEvent("play", () => options.onPlay?.());
|
|
105
|
+
handleEvent("pause", () => options.onPause?.());
|
|
106
|
+
handleEvent("ended", () => options.onEnded?.());
|
|
107
|
+
// Buffering/state events (previously duplicated in Player.tsx onReady)
|
|
108
|
+
video.addEventListener("waiting", () => options.onWaiting?.());
|
|
109
|
+
video.addEventListener("playing", () => options.onPlaying?.());
|
|
110
|
+
video.addEventListener("canplay", () => options.onCanPlay?.());
|
|
111
|
+
video.addEventListener("durationchange", () => {
|
|
112
|
+
options.onDurationChange?.(video.duration);
|
|
113
|
+
});
|
|
114
|
+
video.addEventListener("timeupdate", () => {
|
|
115
|
+
const currentTime = video.currentTime;
|
|
116
|
+
options.onTimeUpdate?.(currentTime);
|
|
117
|
+
this.emit("timeupdate", currentTime);
|
|
118
|
+
});
|
|
119
|
+
video.addEventListener("error", () => {
|
|
120
|
+
const error = video.error ? `Video error: ${video.error.message}` : "Unknown video error";
|
|
121
|
+
options.onError?.(error);
|
|
122
|
+
this.emit("error", error);
|
|
123
|
+
});
|
|
124
|
+
// Call onReady LAST - after all listeners are attached
|
|
125
|
+
// This prevents race conditions where events fire before handlers exist
|
|
126
|
+
this.emit("ready", video);
|
|
127
|
+
if (options.onReady) {
|
|
128
|
+
options.onReady(video);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Default implementations for optional methods
|
|
132
|
+
getCurrentTime() {
|
|
133
|
+
return this.videoElement?.currentTime || 0;
|
|
134
|
+
}
|
|
135
|
+
getDuration() {
|
|
136
|
+
return this.videoElement?.duration || 0;
|
|
137
|
+
}
|
|
138
|
+
getSeekableRange() {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
getBufferedRanges() {
|
|
142
|
+
return this.videoElement?.buffered ?? null;
|
|
143
|
+
}
|
|
144
|
+
isPaused() {
|
|
145
|
+
return this.videoElement?.paused ?? true;
|
|
146
|
+
}
|
|
147
|
+
isMuted() {
|
|
148
|
+
return this.videoElement?.muted ?? false;
|
|
149
|
+
}
|
|
150
|
+
async play() {
|
|
151
|
+
if (this.videoElement) {
|
|
152
|
+
return this.videoElement.play();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
pause() {
|
|
156
|
+
this.videoElement?.pause();
|
|
157
|
+
}
|
|
158
|
+
seek(time) {
|
|
159
|
+
if (this.videoElement) {
|
|
160
|
+
this.videoElement.currentTime = time;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
setVolume(volume) {
|
|
164
|
+
if (this.videoElement) {
|
|
165
|
+
this.videoElement.volume = Math.max(0, Math.min(1, volume));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
setMuted(muted) {
|
|
169
|
+
if (this.videoElement) {
|
|
170
|
+
this.videoElement.muted = muted;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
setPlaybackRate(rate) {
|
|
174
|
+
if (this.videoElement) {
|
|
175
|
+
this.videoElement.playbackRate = rate;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Default captions/text tracks using native TextTrack API
|
|
179
|
+
getTextTracks() {
|
|
180
|
+
const video = this.videoElement;
|
|
181
|
+
if (!video || !video.textTracks)
|
|
182
|
+
return [];
|
|
183
|
+
const out = [];
|
|
184
|
+
const list = video.textTracks;
|
|
185
|
+
for (let i = 0; i < list.length; i++) {
|
|
186
|
+
const tt = list[i];
|
|
187
|
+
out.push({
|
|
188
|
+
id: String(i),
|
|
189
|
+
label: tt.label || `CC ${i + 1}`,
|
|
190
|
+
lang: tt.language,
|
|
191
|
+
active: tt.mode === "showing",
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return out;
|
|
195
|
+
}
|
|
196
|
+
selectTextTrack(id) {
|
|
197
|
+
const video = this.videoElement;
|
|
198
|
+
if (!video || !video.textTracks)
|
|
199
|
+
return;
|
|
200
|
+
const list = video.textTracks;
|
|
201
|
+
for (let i = 0; i < list.length; i++) {
|
|
202
|
+
const tt = list[i];
|
|
203
|
+
if (id !== null && String(i) === id) {
|
|
204
|
+
tt.mode = "showing";
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
tt.mode = "disabled";
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Default live helpers
|
|
212
|
+
isLive() {
|
|
213
|
+
const v = this.videoElement;
|
|
214
|
+
if (!v)
|
|
215
|
+
return false;
|
|
216
|
+
return !isFinite(v.duration) || v.duration === Infinity;
|
|
217
|
+
}
|
|
218
|
+
jumpToLive() {
|
|
219
|
+
const v = this.videoElement;
|
|
220
|
+
if (!v)
|
|
221
|
+
return;
|
|
222
|
+
const seekable = v.seekable;
|
|
223
|
+
if (seekable && seekable.length > 0) {
|
|
224
|
+
try {
|
|
225
|
+
v.currentTime = seekable.end(seekable.length - 1);
|
|
226
|
+
}
|
|
227
|
+
catch { }
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Default PiP helper
|
|
231
|
+
async requestPiP() {
|
|
232
|
+
const v = this.videoElement;
|
|
233
|
+
if (!v)
|
|
234
|
+
return;
|
|
235
|
+
// Exit if already in PiP
|
|
236
|
+
if (document.pictureInPictureElement === v) {
|
|
237
|
+
try {
|
|
238
|
+
await document.exitPictureInPicture?.();
|
|
239
|
+
}
|
|
240
|
+
catch { }
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
if (v.requestPictureInPicture) {
|
|
245
|
+
await v.requestPictureInPicture();
|
|
246
|
+
}
|
|
247
|
+
else if (v.webkitSetPresentationMode) {
|
|
248
|
+
v.webkitSetPresentationMode("picture-in-picture");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch { }
|
|
252
|
+
}
|
|
253
|
+
setSize(width, height) {
|
|
254
|
+
if (this.videoElement) {
|
|
255
|
+
this.videoElement.style.width = `${width}px`;
|
|
256
|
+
this.videoElement.style.height = `${height}px`;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Default optional stats methods
|
|
260
|
+
async getStats() {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
async getLatency() {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
exports.BasePlayer = BasePlayer;
|
|
269
|
+
//# sourceMappingURL=PlayerInterface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlayerInterface.js","sources":["../../../../src/core/PlayerInterface.ts"],"sourcesContent":["/**\n * Common Player Interface\n *\n * All player implementations must implement this interface to ensure\n * consistent behavior and enable the PlayerManager selection system\n */\n\nexport interface StreamSource {\n url: string;\n type: string;\n index?: number;\n streamName?: string;\n mistPlayerUrl?: string;\n}\n\nexport interface StreamTrack {\n type: \"video\" | \"audio\" | \"meta\";\n codec: string;\n codecstring?: string;\n init?: string;\n /** Track index from MistServer (used for binary chunk routing) */\n idx?: number;\n // Video-specific\n width?: number;\n height?: number;\n fpks?: number; // frames per kilosecond\n // Audio-specific\n channels?: number;\n rate?: number; // sample rate\n size?: number; // bits per sample\n}\n\nexport interface StreamInfo {\n source: StreamSource[];\n meta: {\n tracks: StreamTrack[];\n };\n type?: \"live\" | \"vod\";\n}\n\nexport interface PlayerOptions {\n autoplay?: boolean;\n muted?: boolean;\n controls?: boolean;\n loop?: boolean;\n poster?: string;\n width?: number;\n height?: number;\n /** Enable dev mode - for Legacy player, uses MistServer's dev skin with source selection */\n devMode?: boolean;\n /** Enable debug logging in player implementations */\n debug?: boolean;\n onReady?: (element: HTMLVideoElement) => void;\n onError?: (error: string | Error) => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onTimeUpdate?: (currentTime: number) => void;\n // New callbacks for buffering/state management\n onWaiting?: () => void;\n onPlaying?: () => void;\n onCanPlay?: () => void;\n onDurationChange?: (duration: number) => void;\n /** HLS.js configuration override (merged with defaults) */\n hlsConfig?: Record<string, unknown>;\n /** DASH.js configuration override (merged with defaults) */\n dashConfig?: Record<string, unknown>;\n /** Video.js VHS configuration override (merged with defaults) */\n vhsConfig?: Record<string, unknown>;\n}\n\nexport interface PlayerCapability {\n /** Player name for display */\n name: string;\n /** Unique identifier */\n shortname: string;\n /** Priority (lower number = higher priority) */\n priority: number;\n /** MIME types this player can handle */\n mimes: string[];\n}\n\nexport interface PlayerEvents {\n ready: HTMLVideoElement;\n error: string | Error;\n play: void;\n pause: void;\n ended: void;\n timeupdate: number;\n /** Request to reload the player (e.g., Firefox segment error recovery) */\n reloadrequested: { reason: string };\n /** Seekable range changed */\n seekablechange: { start: number; end: number; bufferWindow: number };\n}\n\n/**\n * Error severity levels for the tiered error handling system.\n *\n * Tier 1 (TRANSIENT): Silent retry, no UI - network timeouts, brief stalls\n * Tier 2 (RECOVERABLE): Protocol swap with toast - alternatives exist\n * Tier 3 (DEGRADED): Quality drop with toast - playback continues at lower quality\n * Tier 4 (FATAL): Blocking modal - all options exhausted\n */\nexport enum ErrorSeverity {\n /** Transient issues that self-resolve. User never sees UI. */\n TRANSIENT = 1,\n /** Current protocol failed but alternatives exist. Shows toast on swap. */\n RECOVERABLE = 2,\n /** Quality degraded but playback continues. Shows informational toast. */\n DEGRADED = 3,\n /** Cannot continue playback. Shows blocking error modal. */\n FATAL = 4,\n}\n\n/**\n * Error codes for classification. Maps to specific recovery strategies.\n */\nexport enum ErrorCode {\n // Tier 1: Silent recovery\n NETWORK_TIMEOUT = \"NETWORK_TIMEOUT\",\n WEBSOCKET_DISCONNECT = \"WEBSOCKET_DISCONNECT\",\n SEGMENT_LOAD_ERROR = \"SEGMENT_LOAD_ERROR\",\n ICE_DISCONNECTED = \"ICE_DISCONNECTED\",\n BUFFER_UNDERRUN = \"BUFFER_UNDERRUN\",\n CODEC_DECODE_ERROR = \"CODEC_DECODE_ERROR\",\n\n // Tier 2: Protocol swap\n PROTOCOL_UNSUPPORTED = \"PROTOCOL_UNSUPPORTED\",\n CODEC_INCOMPATIBLE = \"CODEC_INCOMPATIBLE\",\n ICE_FAILED = \"ICE_FAILED\",\n MANIFEST_STALE = \"MANIFEST_STALE\",\n PLAYER_INIT_FAILED = \"PLAYER_INIT_FAILED\",\n\n // Tier 3: Quality degraded\n QUALITY_DROPPED = \"QUALITY_DROPPED\",\n BANDWIDTH_LIMITED = \"BANDWIDTH_LIMITED\",\n\n // Tier 4: Fatal\n ALL_PROTOCOLS_EXHAUSTED = \"ALL_PROTOCOLS_EXHAUSTED\",\n ALL_PROTOCOLS_BLACKLISTED = \"ALL_PROTOCOLS_BLACKLISTED\",\n STREAM_OFFLINE = \"STREAM_OFFLINE\",\n AUTH_REQUIRED = \"AUTH_REQUIRED\",\n GEO_BLOCKED = \"GEO_BLOCKED\",\n DRM_ERROR = \"DRM_ERROR\",\n CONTENT_UNAVAILABLE = \"CONTENT_UNAVAILABLE\",\n UNKNOWN = \"UNKNOWN\",\n}\n\n/**\n * Classified error with severity and recovery metadata.\n * Used by ErrorClassifier to track retry state and decide next action.\n */\nexport interface ClassifiedError {\n /** Severity tier determining UI behavior */\n severity: ErrorSeverity;\n /** Specific error code for recovery strategy lookup */\n code: ErrorCode;\n /** Human-readable error message */\n message: string;\n /** Number of retries remaining for this error type */\n retriesRemaining: number;\n /** Number of alternative protocols/players remaining */\n alternativesRemaining: number;\n /** Original error if available */\n originalError?: Error | string;\n /** Timestamp when error occurred */\n timestamp: number;\n /** Diagnostic details for operators/debugging */\n details?: {\n incompatibilityReasons?: string[];\n blacklistedProtocols?: string[];\n originalCode?: ErrorCode;\n originalMessage?: string;\n };\n}\n\n/**\n * Events emitted by the error handling system.\n * UI layers listen to these for toast/modal display.\n */\nexport interface ErrorHandlingEvents {\n /** Silent recovery attempted (Tier 1) - for telemetry only */\n recoveryAttempted: {\n code: ErrorCode;\n attempt: number;\n maxAttempts: number;\n };\n /** Protocol or player swapped (Tier 2) - shows toast */\n protocolSwapped: {\n fromPlayer: string;\n toPlayer: string;\n fromProtocol: string;\n toProtocol: string;\n reason: string;\n };\n /** Quality changed (Tier 3) - shows toast */\n qualityChanged: {\n direction: \"up\" | \"down\";\n reason: string;\n };\n /** All recovery options exhausted (Tier 4) - shows modal */\n playbackFailed: ClassifiedError;\n}\n\n/**\n * Base interface all players must implement\n */\nexport interface IPlayer {\n /** Player metadata */\n readonly capability: PlayerCapability;\n\n /**\n * Check if this player supports the given MIME type\n */\n isMimeSupported(mimetype: string): boolean;\n\n /**\n * Check if this player can play in the current browser environment\n * @param mimetype - MIME type to test\n * @param source - Source information\n * @param streamInfo - Stream metadata\n * @returns false if not supported, true if supported (no track info),\n * or array of supported track types\n */\n isBrowserSupported(\n mimetype: string,\n source: StreamSource,\n streamInfo: StreamInfo\n ): boolean | string[];\n\n /**\n * Initialize the player with given source and options\n * @param container - Container element to render in\n * @param source - Source to play\n * @param options - Player options\n * @param streamInfo - Full stream metadata (optional, for players that need track details)\n * @returns Promise resolving to video element\n */\n initialize(\n container: HTMLElement,\n source: StreamSource,\n options: PlayerOptions,\n streamInfo?: StreamInfo\n ): Promise<HTMLVideoElement>;\n\n /**\n * Clean up and destroy the player.\n * May be async if cleanup requires network requests (e.g., WHEP session DELETE).\n */\n destroy(): void | Promise<void>;\n\n /**\n * Get the underlying video element (if available)\n */\n getVideoElement(): HTMLVideoElement | null;\n\n /**\n * Set video size\n */\n setSize?(width: number, height: number): void;\n\n /**\n * Add event listener\n */\n on<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void;\n\n /**\n * Remove event listener\n */\n off<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void;\n\n /**\n * Get current playback state\n */\n getCurrentTime?(): number;\n getDuration?(): number;\n isPaused?(): boolean;\n isMuted?(): boolean;\n /** Optional: provide an override seekable range (seconds) */\n getSeekableRange?(): { start: number; end: number } | null;\n /** Optional: provide buffered ranges override */\n getBufferedRanges?(): TimeRanges | null;\n\n /**\n * Control playback\n */\n play?(): Promise<void>;\n pause?(): void;\n seek?(time: number): void;\n setVolume?(volume: number): void;\n setMuted?(muted: boolean): void;\n setPlaybackRate?(rate: number): void;\n\n // Optional: captions/text tracks\n getTextTracks?(): Array<{ id: string; label: string; lang?: string; active: boolean }>;\n selectTextTrack?(id: string | null): void;\n\n // Optional: quality/level selection\n getQualities?(): Array<{\n id: string;\n label: string;\n bitrate?: number;\n width?: number;\n height?: number;\n isAuto?: boolean;\n active?: boolean;\n }>;\n selectQuality?(id: string): void; // use 'auto' to enable ABR\n getCurrentQuality?(): string | null;\n\n // Optional: live edge helpers\n isLive?(): boolean;\n jumpToLive?(): void;\n /** Optional: frame step (direction -1/1, optional step seconds) */\n frameStep?(direction: -1 | 1, seconds?: number): void;\n\n // Optional: PiP\n requestPiP?(): Promise<void>;\n\n /**\n * Optional: Retrieve player-specific stats (e.g., WebRTC inbound-rtp)\n */\n getStats?(): Promise<any>;\n\n /**\n * Optional: Retrieve approximate playback latency stats\n */\n getLatency?(): Promise<any>;\n}\n\n/**\n * Base class providing common functionality\n */\nexport abstract class BasePlayer implements IPlayer {\n abstract readonly capability: PlayerCapability;\n\n protected listeners: Map<string, Set<Function>> = new Map();\n protected videoElement: HTMLVideoElement | null = null;\n\n abstract isMimeSupported(mimetype: string): boolean;\n abstract isBrowserSupported(\n mimetype: string,\n source: StreamSource,\n streamInfo: StreamInfo\n ): boolean | string[];\n abstract initialize(\n container: HTMLElement,\n source: StreamSource,\n options: PlayerOptions,\n streamInfo?: StreamInfo\n ): Promise<HTMLVideoElement>;\n abstract destroy(): void | Promise<void>;\n\n getVideoElement(): HTMLVideoElement | null {\n return this.videoElement;\n }\n\n on<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n off<K extends keyof PlayerEvents>(event: K, listener: (data: PlayerEvents[K]) => void): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.delete(listener);\n }\n }\n\n protected emit<K extends keyof PlayerEvents>(event: K, data: PlayerEvents[K]): void {\n const eventListeners = this.listeners.get(event);\n if (eventListeners) {\n eventListeners.forEach((listener) => {\n try {\n listener(data);\n } catch (e) {\n console.error(`Error in ${event} listener:`, e);\n }\n });\n }\n }\n\n protected setupVideoEventListeners(video: HTMLVideoElement, options: PlayerOptions): void {\n const handleEvent = (eventName: keyof PlayerEvents, handler: () => void) => {\n const listener = () => {\n handler();\n this.emit(eventName as any, undefined as any);\n };\n video.addEventListener(eventName, listener);\n };\n\n // Core playback events\n handleEvent(\"play\", () => options.onPlay?.());\n handleEvent(\"pause\", () => options.onPause?.());\n handleEvent(\"ended\", () => options.onEnded?.());\n\n // Buffering/state events (previously duplicated in Player.tsx onReady)\n video.addEventListener(\"waiting\", () => options.onWaiting?.());\n video.addEventListener(\"playing\", () => options.onPlaying?.());\n video.addEventListener(\"canplay\", () => options.onCanPlay?.());\n\n video.addEventListener(\"durationchange\", () => {\n options.onDurationChange?.(video.duration);\n });\n\n video.addEventListener(\"timeupdate\", () => {\n const currentTime = video.currentTime;\n options.onTimeUpdate?.(currentTime);\n this.emit(\"timeupdate\", currentTime);\n });\n\n video.addEventListener(\"error\", () => {\n const error = video.error ? `Video error: ${video.error.message}` : \"Unknown video error\";\n options.onError?.(error);\n this.emit(\"error\", error);\n });\n\n // Call onReady LAST - after all listeners are attached\n // This prevents race conditions where events fire before handlers exist\n this.emit(\"ready\", video);\n if (options.onReady) {\n options.onReady(video);\n }\n }\n\n // Default implementations for optional methods\n getCurrentTime(): number {\n return this.videoElement?.currentTime || 0;\n }\n\n getDuration(): number {\n return this.videoElement?.duration || 0;\n }\n\n getSeekableRange(): { start: number; end: number } | null {\n return null;\n }\n\n getBufferedRanges(): TimeRanges | null {\n return this.videoElement?.buffered ?? null;\n }\n\n isPaused(): boolean {\n return this.videoElement?.paused ?? true;\n }\n\n isMuted(): boolean {\n return this.videoElement?.muted ?? false;\n }\n\n async play(): Promise<void> {\n if (this.videoElement) {\n return this.videoElement.play();\n }\n }\n\n pause(): void {\n this.videoElement?.pause();\n }\n\n seek(time: number): void {\n if (this.videoElement) {\n this.videoElement.currentTime = time;\n }\n }\n\n setVolume(volume: number): void {\n if (this.videoElement) {\n this.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n }\n\n setMuted(muted: boolean): void {\n if (this.videoElement) {\n this.videoElement.muted = muted;\n }\n }\n setPlaybackRate(rate: number): void {\n if (this.videoElement) {\n this.videoElement.playbackRate = rate;\n }\n }\n\n // Default captions/text tracks using native TextTrack API\n getTextTracks(): Array<{ id: string; label: string; lang?: string; active: boolean }> {\n const video = this.videoElement;\n if (!video || !video.textTracks) return [];\n const out: Array<{ id: string; label: string; lang?: string; active: boolean }> = [];\n const list = video.textTracks as any as TextTrackList;\n for (let i = 0; i < list.length; i++) {\n const tt = list[i];\n out.push({\n id: String(i),\n label: tt.label || `CC ${i + 1}`,\n lang: (tt as any).language,\n active: tt.mode === \"showing\",\n });\n }\n return out;\n }\n\n selectTextTrack(id: string | null): void {\n const video = this.videoElement;\n if (!video || !video.textTracks) return;\n const list = video.textTracks as any as TextTrackList;\n for (let i = 0; i < list.length; i++) {\n const tt = list[i];\n if (id !== null && String(i) === id) {\n tt.mode = \"showing\";\n } else {\n tt.mode = \"disabled\";\n }\n }\n }\n\n // Default live helpers\n isLive(): boolean {\n const v = this.videoElement;\n if (!v) return false;\n return !isFinite(v.duration) || v.duration === Infinity;\n }\n\n jumpToLive(): void {\n const v = this.videoElement;\n if (!v) return;\n const seekable = v.seekable;\n if (seekable && seekable.length > 0) {\n try {\n v.currentTime = seekable.end(seekable.length - 1);\n } catch {}\n }\n }\n\n // Default PiP helper\n async requestPiP(): Promise<void> {\n const v: any = this.videoElement as any;\n if (!v) return;\n // Exit if already in PiP\n if (document.pictureInPictureElement === v) {\n try {\n await (document as any).exitPictureInPicture?.();\n } catch {}\n return;\n }\n try {\n if (v.requestPictureInPicture) {\n await v.requestPictureInPicture();\n } else if (v.webkitSetPresentationMode) {\n v.webkitSetPresentationMode(\"picture-in-picture\");\n }\n } catch {}\n }\n\n setSize(width: number, height: number): void {\n if (this.videoElement) {\n this.videoElement.style.width = `${width}px`;\n this.videoElement.style.height = `${height}px`;\n }\n }\n\n // Default optional stats methods\n async getStats(): Promise<any> {\n return undefined;\n }\n\n async getLatency(): Promise<any> {\n return undefined;\n }\n}\n"],"names":["ErrorSeverity","ErrorCode"],"mappings":"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"}
|