@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 @@
|
|
|
1
|
+
{"version":3,"file":"InteractionController.js","sources":["../../../../src/core/InteractionController.ts"],"sourcesContent":["/**\n * InteractionController - Unified keyboard and gesture handling for video players\n *\n * Features:\n * - Hold space for 2x speed (VOD/clips only, tap = play/pause)\n * - Click/touch and hold for 2x speed\n * - Comprehensive keyboard shortcuts\n * - Double-tap to skip on mobile\n * - All interactions disabled for live streams (where applicable)\n */\n\nexport interface InteractionControllerConfig {\n container: HTMLElement;\n videoElement: HTMLVideoElement;\n isLive: boolean;\n isPaused?: () => boolean;\n onPlayPause: () => void;\n onSeek: (delta: number) => void;\n onVolumeChange: (delta: number) => void;\n onMuteToggle: () => void;\n onFullscreenToggle: () => void;\n onCaptionsToggle?: () => void;\n onLoopToggle?: () => void;\n onSpeedChange: (speed: number, isHolding: boolean) => void;\n onSeekPercent?: (percent: number) => void;\n /** Optional: player-specific frame stepping (return true if handled) */\n onFrameStep?: (direction: -1 | 1, seconds: number) => boolean | void;\n speedHoldValue?: number;\n /** Frame step duration in seconds (for prev/next frame shortcuts) */\n frameStepSeconds?: number;\n /** Idle timeout in ms (default 5000). Set to 0 to disable. */\n idleTimeout?: number;\n /** Callback fired when user becomes idle */\n onIdle?: () => void;\n /** Callback fired when user becomes active after being idle */\n onActive?: () => void;\n}\n\nexport interface InteractionState {\n isHoldingSpeed: boolean;\n previousSpeed: number;\n holdSpeed: number;\n /** Whether the user is currently idle (no interaction for idleTimeout) */\n isIdle: boolean;\n}\n\n// Timing constants\nconst HOLD_THRESHOLD_MS = 200; // Time before keydown becomes \"hold\" vs \"tap\"\nconst LONG_PRESS_THRESHOLD_MS = 300; // Time for touch/click to become \"hold\"\nconst DOUBLE_TAP_WINDOW_MS = 300; // Window for detecting double-tap\nconst SKIP_AMOUNT_SECONDS = 10; // Skip forward/backward amount\nconst VOLUME_STEP = 0.1; // Volume change per arrow press (10%)\nconst DEFAULT_IDLE_TIMEOUT_MS = 5000; // Default idle timeout (5 seconds)\n\nexport class InteractionController {\n private config: InteractionControllerConfig;\n private state: InteractionState;\n private isAttached = false;\n\n // Keyboard tracking\n private spaceKeyDownTime = 0;\n private spaceIsHeld = false;\n private holdCheckTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Touch/click tracking\n private pointerDownTime = 0;\n private pointerIsHeld = false;\n private pointerHoldTimeout: ReturnType<typeof setTimeout> | null = null;\n private lastTapTime = 0;\n private lastTapX = 0;\n private pendingTapTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Idle tracking\n private idleTimeout: ReturnType<typeof setTimeout> | null = null;\n private lastInteractionTime = 0;\n\n // Bound event handlers\n private boundKeyDown: (e: KeyboardEvent) => void;\n private boundKeyUp: (e: KeyboardEvent) => void;\n private boundPointerDown: (e: PointerEvent) => void;\n private boundPointerUp: (e: PointerEvent) => void;\n private boundPointerCancel: (e: PointerEvent) => void;\n private boundContextMenu: (e: Event) => void;\n private boundMouseMove: (e: MouseEvent) => void;\n private boundDoubleClick: (e: MouseEvent) => void;\n private boundDocumentKeyDown: (e: KeyboardEvent) => void;\n private boundDocumentKeyUp: (e: KeyboardEvent) => void;\n\n constructor(config: InteractionControllerConfig) {\n this.config = config;\n this.state = {\n isHoldingSpeed: false,\n previousSpeed: 1,\n holdSpeed: config.speedHoldValue ?? 2,\n isIdle: false,\n };\n\n // Bind handlers\n this.boundKeyDown = this.handleKeyDown.bind(this);\n this.boundKeyUp = this.handleKeyUp.bind(this);\n this.boundPointerDown = this.handlePointerDown.bind(this);\n this.boundPointerUp = this.handlePointerUp.bind(this);\n this.boundPointerCancel = this.handlePointerCancel.bind(this);\n this.boundContextMenu = this.handleContextMenu.bind(this);\n this.boundMouseMove = this.handleMouseMove.bind(this);\n this.boundDoubleClick = this.handleDoubleClick.bind(this);\n this.boundDocumentKeyDown = this.handleKeyDown.bind(this);\n this.boundDocumentKeyUp = this.handleKeyUp.bind(this);\n }\n\n /**\n * Attach event listeners to container\n */\n attach(): void {\n if (this.isAttached) return;\n\n const { container } = this.config;\n\n // Make container focusable for keyboard events\n if (!container.hasAttribute(\"tabindex\")) {\n container.setAttribute(\"tabindex\", \"0\");\n }\n\n // Keyboard events\n container.addEventListener(\"keydown\", this.boundKeyDown);\n container.addEventListener(\"keyup\", this.boundKeyUp);\n document.addEventListener(\"keydown\", this.boundDocumentKeyDown);\n document.addEventListener(\"keyup\", this.boundDocumentKeyUp);\n\n // Pointer events (unified mouse + touch)\n container.addEventListener(\"pointerdown\", this.boundPointerDown);\n container.addEventListener(\"pointerup\", this.boundPointerUp);\n container.addEventListener(\"pointercancel\", this.boundPointerCancel);\n container.addEventListener(\"pointerleave\", this.boundPointerCancel);\n\n // Mouse move for idle detection\n container.addEventListener(\"mousemove\", this.boundMouseMove);\n\n // Double click for fullscreen (desktop)\n container.addEventListener(\"dblclick\", this.boundDoubleClick);\n\n // Prevent context menu on long press\n container.addEventListener(\"contextmenu\", this.boundContextMenu);\n\n // Start idle tracking\n this.resetIdleTimer();\n\n this.isAttached = true;\n }\n\n /**\n * Detach event listeners and cleanup\n */\n detach(): void {\n if (!this.isAttached) return;\n\n const { container } = this.config;\n\n container.removeEventListener(\"keydown\", this.boundKeyDown);\n container.removeEventListener(\"keyup\", this.boundKeyUp);\n document.removeEventListener(\"keydown\", this.boundDocumentKeyDown);\n document.removeEventListener(\"keyup\", this.boundDocumentKeyUp);\n container.removeEventListener(\"pointerdown\", this.boundPointerDown);\n container.removeEventListener(\"pointerup\", this.boundPointerUp);\n container.removeEventListener(\"pointercancel\", this.boundPointerCancel);\n container.removeEventListener(\"pointerleave\", this.boundPointerCancel);\n container.removeEventListener(\"mousemove\", this.boundMouseMove);\n container.removeEventListener(\"dblclick\", this.boundDoubleClick);\n container.removeEventListener(\"contextmenu\", this.boundContextMenu);\n\n // Clear any pending timeouts\n if (this.holdCheckTimeout) {\n clearTimeout(this.holdCheckTimeout);\n this.holdCheckTimeout = null;\n }\n if (this.pointerHoldTimeout) {\n clearTimeout(this.pointerHoldTimeout);\n this.pointerHoldTimeout = null;\n }\n if (this.pendingTapTimeout) {\n clearTimeout(this.pendingTapTimeout);\n this.pendingTapTimeout = null;\n }\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n this.idleTimeout = null;\n }\n\n // Restore speed if holding\n if (this.state.isHoldingSpeed) {\n this.releaseSpeedHold();\n }\n\n this.isAttached = false;\n }\n\n /**\n * Check if currently holding for speed boost\n */\n isHoldingSpeed(): boolean {\n return this.state.isHoldingSpeed;\n }\n\n /**\n * Check if user is currently idle (no interaction for idleTimeout)\n */\n isIdle(): boolean {\n return this.state.isIdle;\n }\n\n /**\n * Get current interaction state\n */\n getState(): InteractionState {\n return { ...this.state };\n }\n\n /**\n * Update config (e.g., when isLive changes)\n */\n updateConfig(updates: Partial<InteractionControllerConfig>): void {\n this.config = { ...this.config, ...updates };\n\n // If we switched to live mode while holding, release\n if (updates.isLive && this.state.isHoldingSpeed) {\n this.releaseSpeedHold();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────\n // Keyboard Handling\n // ─────────────────────────────────────────────────────────────────\n\n private handleKeyDown(e: KeyboardEvent): void {\n // Ignore if focus is on an input element\n if (this.isInputElement(e.target)) return;\n if (e.defaultPrevented) return;\n if (!this.shouldHandleKeyboard(e)) return;\n\n // Record interaction for idle detection\n this.recordInteraction();\n\n const { isLive } = this.config;\n const isPaused = this.config.isPaused?.() ?? this.config.videoElement?.paused ?? false;\n\n switch (e.key) {\n case \" \":\n case \"Spacebar\":\n e.preventDefault();\n this.handleSpaceDown();\n break;\n\n case \"ArrowLeft\":\n case \"j\":\n case \"J\":\n e.preventDefault();\n if (!isLive) {\n this.config.onSeek(-SKIP_AMOUNT_SECONDS);\n }\n break;\n\n case \"ArrowRight\":\n case \"l\":\n case \"L\":\n e.preventDefault();\n if (!isLive) {\n this.config.onSeek(SKIP_AMOUNT_SECONDS);\n }\n break;\n\n case \"ArrowUp\":\n e.preventDefault();\n this.config.onVolumeChange(VOLUME_STEP);\n break;\n\n case \"ArrowDown\":\n e.preventDefault();\n this.config.onVolumeChange(-VOLUME_STEP);\n break;\n\n case \"m\":\n case \"M\":\n e.preventDefault();\n this.config.onMuteToggle();\n break;\n\n case \"f\":\n case \"F\":\n e.preventDefault();\n this.config.onFullscreenToggle();\n break;\n\n case \"c\":\n case \"C\":\n e.preventDefault();\n this.config.onCaptionsToggle?.();\n break;\n\n case \"k\":\n case \"K\":\n // YouTube-style: K = play/pause (no hold behavior)\n e.preventDefault();\n this.config.onPlayPause();\n break;\n\n case \"<\":\n // Decrease speed (shift+, = <)\n e.preventDefault();\n if (!isLive) {\n this.adjustPlaybackSpeed(-0.25);\n }\n break;\n\n case \">\":\n // Increase speed (shift+. = >)\n e.preventDefault();\n if (!isLive) {\n this.adjustPlaybackSpeed(0.25);\n }\n break;\n\n case \",\":\n // Previous frame when paused\n if (this.config.onFrameStep || (!isLive && isPaused)) {\n e.preventDefault();\n this.stepFrame(-1);\n }\n break;\n\n case \".\":\n // Next frame when paused\n if (this.config.onFrameStep || (!isLive && isPaused)) {\n e.preventDefault();\n this.stepFrame(1);\n }\n break;\n\n // Number keys for seeking to percentage\n case \"0\":\n case \"1\":\n case \"2\":\n case \"3\":\n case \"4\":\n case \"5\":\n case \"6\":\n case \"7\":\n case \"8\":\n case \"9\":\n e.preventDefault();\n if (!isLive && this.config.onSeekPercent) {\n const percent = parseInt(e.key, 10) / 10;\n this.config.onSeekPercent(percent);\n }\n break;\n }\n }\n\n private handleKeyUp(e: KeyboardEvent): void {\n if (this.isInputElement(e.target)) return;\n if (e.defaultPrevented) return;\n if (!this.shouldHandleKeyboard(e)) return;\n\n if (e.key === \" \" || e.key === \"Spacebar\") {\n e.preventDefault();\n this.handleSpaceUp();\n }\n }\n\n private shouldHandleKeyboard(e: KeyboardEvent): boolean {\n if (this.spaceKeyDownTime > 0) return true;\n const target = e.target as HTMLElement | null;\n if (target && this.config.container.contains(target)) return true;\n const active = document.activeElement as HTMLElement | null;\n if (active && this.config.container.contains(active)) return true;\n try {\n if (this.config.container.matches(\":focus-within\")) return true;\n if (this.config.container.matches(\":hover\")) return true;\n } catch {}\n const now = Date.now();\n if (now - this.lastInteractionTime < DEFAULT_IDLE_TIMEOUT_MS) return true;\n return false;\n }\n\n private handleSpaceDown(): void {\n if (this.spaceKeyDownTime > 0) return; // Already tracking\n\n this.spaceKeyDownTime = Date.now();\n this.spaceIsHeld = false;\n\n // Only enable hold-for-speed on VOD/clips\n if (!this.config.isLive) {\n this.holdCheckTimeout = setTimeout(() => {\n this.spaceIsHeld = true;\n this.engageSpeedHold();\n }, HOLD_THRESHOLD_MS);\n }\n }\n\n private handleSpaceUp(): void {\n const downTime = this.spaceKeyDownTime;\n this.spaceKeyDownTime = 0;\n\n if (this.holdCheckTimeout) {\n clearTimeout(this.holdCheckTimeout);\n this.holdCheckTimeout = null;\n }\n\n if (this.spaceIsHeld) {\n // Was holding - release speed boost\n this.releaseSpeedHold();\n this.spaceIsHeld = false;\n } else {\n // Was a quick tap - toggle play/pause\n const elapsed = Date.now() - downTime;\n if (elapsed < HOLD_THRESHOLD_MS || this.config.isLive) {\n this.config.onPlayPause();\n }\n }\n }\n\n private handleDoubleClick(e: MouseEvent): void {\n if (this.isControlElement(e.target)) return;\n this.recordInteraction();\n e.preventDefault();\n this.config.onFullscreenToggle();\n }\n\n private stepFrame(direction: -1 | 1): void {\n const step = this.getFrameStepSeconds();\n if (!Number.isFinite(step) || step <= 0) return;\n if (this.config.onFrameStep?.(direction, step)) return;\n const video = this.config.videoElement;\n if (!video) return;\n\n const target = video.currentTime + direction * step;\n if (!Number.isFinite(target)) return;\n\n // Only step within already-buffered ranges to avoid network seeks\n const buffered = video.buffered;\n if (buffered && buffered.length > 0) {\n for (let i = 0; i < buffered.length; i++) {\n const start = buffered.start(i);\n const end = buffered.end(i);\n if (target >= start && target <= end) {\n try {\n video.currentTime = target;\n } catch {}\n return;\n }\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────────────\n // Pointer (Mouse/Touch) Handling\n // ─────────────────────────────────────────────────────────────────\n\n private handlePointerDown(e: PointerEvent): void {\n // Only handle primary button / single touch on the video area\n if (e.button !== 0) return;\n if (this.isControlElement(e.target)) return;\n\n // Record interaction for idle detection\n this.recordInteraction();\n\n // Ensure container has focus for keyboard events\n this.config.container.focus();\n\n const now = Date.now();\n const rect = this.config.container.getBoundingClientRect();\n const relativeX = (e.clientX - rect.left) / rect.width;\n const isMouse = e.pointerType === \"mouse\";\n\n // Check for double-tap\n if (now - this.lastTapTime < DOUBLE_TAP_WINDOW_MS) {\n // Clear pending single-tap\n if (this.pendingTapTimeout) {\n clearTimeout(this.pendingTapTimeout);\n this.pendingTapTimeout = null;\n }\n\n // Mouse double-click handled via dblclick event (fullscreen)\n if (!isMouse) {\n // Handle double-tap to skip (mobile-style)\n if (!this.config.isLive) {\n if (relativeX < 0.33) {\n // Left third - skip back\n this.config.onSeek(-SKIP_AMOUNT_SECONDS);\n } else if (relativeX > 0.67) {\n // Right third - skip forward\n this.config.onSeek(SKIP_AMOUNT_SECONDS);\n } else {\n // Center - treat as play/pause\n this.config.onPlayPause();\n }\n }\n }\n\n this.lastTapTime = 0;\n return;\n }\n\n this.lastTapTime = now;\n this.lastTapX = relativeX;\n this.pointerDownTime = now;\n this.pointerIsHeld = false;\n\n // Start long-press detection for 2x speed (VOD only)\n if (!this.config.isLive) {\n this.pointerHoldTimeout = setTimeout(() => {\n this.pointerIsHeld = true;\n this.engageSpeedHold();\n }, LONG_PRESS_THRESHOLD_MS);\n }\n }\n\n private handlePointerUp(e: PointerEvent): void {\n if (e.button !== 0) return;\n\n const wasHeld = this.pointerIsHeld;\n this.cancelPointerHold();\n\n if (wasHeld) {\n // Was long-pressing - just release speed\n this.releaseSpeedHold();\n } else if (this.pointerDownTime > 0) {\n // Was a quick tap - delay to check for double-tap\n this.pendingTapTimeout = setTimeout(() => {\n this.pendingTapTimeout = null;\n this.config.onPlayPause();\n }, DOUBLE_TAP_WINDOW_MS);\n }\n\n this.pointerDownTime = 0;\n }\n\n private handlePointerCancel(_e: PointerEvent): void {\n if (this.pointerIsHeld) {\n this.releaseSpeedHold();\n }\n this.cancelPointerHold();\n this.pointerDownTime = 0;\n }\n\n private cancelPointerHold(): void {\n if (this.pointerHoldTimeout) {\n clearTimeout(this.pointerHoldTimeout);\n this.pointerHoldTimeout = null;\n }\n this.pointerIsHeld = false;\n }\n\n private handleContextMenu(e: Event): void {\n // Prevent context menu during long-press\n if (this.pointerIsHeld || this.pointerDownTime > 0) {\n e.preventDefault();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────\n // Speed Hold Logic\n // ─────────────────────────────────────────────────────────────────\n\n private engageSpeedHold(): void {\n if (this.state.isHoldingSpeed) return;\n if (this.config.isLive) return;\n\n // Save current speed\n this.state.previousSpeed = this.config.videoElement.playbackRate;\n this.state.isHoldingSpeed = true;\n\n // Apply hold speed\n this.config.onSpeedChange(this.state.holdSpeed, true);\n }\n\n private releaseSpeedHold(): void {\n if (!this.state.isHoldingSpeed) return;\n\n this.state.isHoldingSpeed = false;\n\n // Restore previous speed\n this.config.onSpeedChange(this.state.previousSpeed, false);\n }\n\n private adjustPlaybackSpeed(delta: number): void {\n if (this.state.isHoldingSpeed) return;\n\n const currentSpeed = this.config.videoElement.playbackRate;\n const newSpeed = Math.max(0.25, Math.min(4, currentSpeed + delta));\n\n // Round to avoid floating point issues\n const roundedSpeed = Math.round(newSpeed * 100) / 100;\n\n this.config.onSpeedChange(roundedSpeed, false);\n }\n\n // ─────────────────────────────────────────────────────────────────\n // Idle Detection\n // ─────────────────────────────────────────────────────────────────\n\n private handleMouseMove(_e: MouseEvent): void {\n this.recordInteraction();\n }\n\n /**\n * Record that an interaction occurred and reset idle timer\n */\n recordInteraction(): void {\n this.lastInteractionTime = Date.now();\n\n // If was idle, become active\n if (this.state.isIdle) {\n this.state.isIdle = false;\n this.config.onActive?.();\n }\n\n // Reset idle timer\n this.resetIdleTimer();\n }\n\n /**\n * Reset the idle timer\n */\n private resetIdleTimer(): void {\n // Clear existing timer\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n this.idleTimeout = null;\n }\n\n // Get timeout value (0 means disabled)\n const timeout = this.config.idleTimeout ?? DEFAULT_IDLE_TIMEOUT_MS;\n if (timeout <= 0) return;\n\n // Set new timer\n this.idleTimeout = setTimeout(() => {\n this.idleTimeout = null;\n if (!this.state.isIdle) {\n this.state.isIdle = true;\n this.config.onIdle?.();\n }\n }, timeout);\n }\n\n /**\n * Manually mark as active (e.g., when controls become visible)\n */\n markActive(): void {\n this.recordInteraction();\n }\n\n /**\n * Pause idle tracking (e.g., when controls are visible)\n */\n pauseIdleTracking(): void {\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n this.idleTimeout = null;\n }\n }\n\n /**\n * Resume idle tracking\n */\n resumeIdleTracking(): void {\n if (this.isAttached) {\n this.resetIdleTimer();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────\n // Utilities\n // ─────────────────────────────────────────────────────────────────\n\n private isInputElement(target: EventTarget | null): boolean {\n if (!target || !(target instanceof HTMLElement)) return false;\n const tagName = target.tagName.toLowerCase();\n return (\n tagName === \"input\" ||\n tagName === \"textarea\" ||\n tagName === \"select\" ||\n target.isContentEditable\n );\n }\n\n private isControlElement(target: EventTarget | null): boolean {\n if (!target || !(target instanceof HTMLElement)) return false;\n\n // Check if clicking on player controls (buttons, sliders, etc.)\n const controlSelectors = [\n \"button\",\n '[role=\"button\"]',\n '[role=\"slider\"]',\n \"input\",\n \"select\",\n \".fw-player-controls\",\n \"[data-player-controls]\",\n \".fw-controls-wrapper\",\n \".fw-control-bar\",\n \".fw-settings-menu\",\n \".fw-context-menu\",\n \".fw-stats-panel\",\n \".fw-dev-panel\",\n \".fw-error-overlay\",\n \".fw-error-popup\",\n \".fw-player-error\",\n ];\n\n return controlSelectors.some((selector) => {\n return target.matches(selector) || target.closest(selector) !== null;\n });\n }\n\n private getFrameStepSeconds(): number {\n const step = this.config.frameStepSeconds;\n if (Number.isFinite(step) && (step as number) > 0) return step as number;\n return 1 / 30;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiveDurationProxy - Wraps video element to provide meaningful duration for live streams
|
|
3
|
+
*
|
|
4
|
+
* Live streams report `Infinity` or `NaN` for duration, breaking seek bars and time display.
|
|
5
|
+
* This proxy intercepts the duration getter and returns a calculated value based on:
|
|
6
|
+
* - Buffer end position
|
|
7
|
+
* - Elapsed time since last progress event
|
|
8
|
+
*
|
|
9
|
+
* Based on MistMetaPlayer reference implementation (wrappers/html5.js, dashjs.js)
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Creates a proxy wrapper around a video element that provides meaningful
|
|
13
|
+
* duration values for live streams.
|
|
14
|
+
*/
|
|
15
|
+
class LiveDurationProxy {
|
|
16
|
+
constructor(video, options = {}) {
|
|
17
|
+
this.lastProgressTime = 0;
|
|
18
|
+
this.lastBufferEnd = 0;
|
|
19
|
+
this.listeners = [];
|
|
20
|
+
this._calculatedDuration = 0;
|
|
21
|
+
this.video = video;
|
|
22
|
+
this.options = {
|
|
23
|
+
constrainSeek: options.constrainSeek ?? true,
|
|
24
|
+
liveOffset: options.liveOffset ?? 0,
|
|
25
|
+
onDurationChange: options.onDurationChange ?? (() => { }),
|
|
26
|
+
};
|
|
27
|
+
this.setupListeners();
|
|
28
|
+
this.updateDuration();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if the stream is live
|
|
32
|
+
*/
|
|
33
|
+
isLive() {
|
|
34
|
+
const nativeDuration = this.video.duration;
|
|
35
|
+
return !isFinite(nativeDuration) || nativeDuration === Infinity;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get the calculated duration
|
|
39
|
+
* For live: bufferEnd + elapsedSinceLastProgress
|
|
40
|
+
* For VOD: native duration
|
|
41
|
+
*/
|
|
42
|
+
getDuration() {
|
|
43
|
+
if (!this.isLive()) {
|
|
44
|
+
return this.video.duration;
|
|
45
|
+
}
|
|
46
|
+
return this._calculatedDuration;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the current buffer end position
|
|
50
|
+
*/
|
|
51
|
+
getBufferEnd() {
|
|
52
|
+
const buffered = this.video.buffered;
|
|
53
|
+
if (buffered.length === 0)
|
|
54
|
+
return 0;
|
|
55
|
+
// Find the buffer range containing current time, or the last one
|
|
56
|
+
for (let i = 0; i < buffered.length; i++) {
|
|
57
|
+
if (buffered.start(i) <= this.video.currentTime && buffered.end(i) > this.video.currentTime) {
|
|
58
|
+
return buffered.end(i);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Return the end of the last buffer range
|
|
62
|
+
return buffered.end(buffered.length - 1);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the live edge position (where live is)
|
|
66
|
+
*/
|
|
67
|
+
getLiveEdge() {
|
|
68
|
+
return this.getBufferEnd() - this.options.liveOffset;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the current latency (distance from live edge)
|
|
72
|
+
*/
|
|
73
|
+
getLatency() {
|
|
74
|
+
if (!this.isLive())
|
|
75
|
+
return 0;
|
|
76
|
+
return Math.max(0, this.getLiveEdge() - this.video.currentTime);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Seek to a position, respecting live constraints
|
|
80
|
+
*/
|
|
81
|
+
seek(time) {
|
|
82
|
+
if (!this.isLive() || !this.options.constrainSeek) {
|
|
83
|
+
this.video.currentTime = time;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Constrain to buffered range for live
|
|
87
|
+
const buffered = this.video.buffered;
|
|
88
|
+
if (buffered.length === 0) {
|
|
89
|
+
this.video.currentTime = time;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Find valid seek range
|
|
93
|
+
const bufferStart = buffered.start(0);
|
|
94
|
+
const liveEdge = this.getLiveEdge();
|
|
95
|
+
// Clamp to valid range
|
|
96
|
+
const clampedTime = Math.max(bufferStart, Math.min(time, liveEdge));
|
|
97
|
+
this.video.currentTime = clampedTime;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Jump to live edge
|
|
101
|
+
*/
|
|
102
|
+
jumpToLive() {
|
|
103
|
+
if (!this.isLive())
|
|
104
|
+
return;
|
|
105
|
+
this.video.currentTime = this.getLiveEdge();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if currently at live edge (within threshold)
|
|
109
|
+
*/
|
|
110
|
+
isAtLiveEdge(threshold = 2) {
|
|
111
|
+
if (!this.isLive())
|
|
112
|
+
return false;
|
|
113
|
+
return this.getLatency() <= threshold;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get current state
|
|
117
|
+
*/
|
|
118
|
+
getState() {
|
|
119
|
+
return {
|
|
120
|
+
duration: this.getDuration(),
|
|
121
|
+
isLive: this.isLive(),
|
|
122
|
+
bufferEnd: this.getBufferEnd(),
|
|
123
|
+
elapsed: this.lastProgressTime > 0 ? (Date.now() - this.lastProgressTime) / 1000 : 0,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Update the calculated duration
|
|
128
|
+
*/
|
|
129
|
+
updateDuration() {
|
|
130
|
+
if (!this.isLive()) {
|
|
131
|
+
this._calculatedDuration = this.video.duration;
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const bufferEnd = this.getBufferEnd();
|
|
135
|
+
const now = Date.now();
|
|
136
|
+
const elapsedSinceProgress = this.lastProgressTime > 0 ? (now - this.lastProgressTime) / 1000 : 0;
|
|
137
|
+
// MistPlayer formula: buffer_end + elapsed_since_last_progress
|
|
138
|
+
const newDuration = bufferEnd + elapsedSinceProgress;
|
|
139
|
+
// Only update if changed significantly (avoid constant updates)
|
|
140
|
+
if (Math.abs(newDuration - this._calculatedDuration) > 0.1) {
|
|
141
|
+
this._calculatedDuration = newDuration;
|
|
142
|
+
this.options.onDurationChange(newDuration);
|
|
143
|
+
}
|
|
144
|
+
this.lastBufferEnd = bufferEnd;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Setup event listeners for tracking
|
|
148
|
+
*/
|
|
149
|
+
setupListeners() {
|
|
150
|
+
const onProgress = () => {
|
|
151
|
+
this.lastProgressTime = Date.now();
|
|
152
|
+
this.updateDuration();
|
|
153
|
+
};
|
|
154
|
+
const onTimeUpdate = () => {
|
|
155
|
+
this.updateDuration();
|
|
156
|
+
};
|
|
157
|
+
const onDurationChange = () => {
|
|
158
|
+
this.updateDuration();
|
|
159
|
+
};
|
|
160
|
+
const onLoadedMetadata = () => {
|
|
161
|
+
this.updateDuration();
|
|
162
|
+
};
|
|
163
|
+
this.video.addEventListener("progress", onProgress);
|
|
164
|
+
this.video.addEventListener("timeupdate", onTimeUpdate);
|
|
165
|
+
this.video.addEventListener("durationchange", onDurationChange);
|
|
166
|
+
this.video.addEventListener("loadedmetadata", onLoadedMetadata);
|
|
167
|
+
this.listeners = [
|
|
168
|
+
() => this.video.removeEventListener("progress", onProgress),
|
|
169
|
+
() => this.video.removeEventListener("timeupdate", onTimeUpdate),
|
|
170
|
+
() => this.video.removeEventListener("durationchange", onDurationChange),
|
|
171
|
+
() => this.video.removeEventListener("loadedmetadata", onLoadedMetadata),
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Cleanup
|
|
176
|
+
*/
|
|
177
|
+
destroy() {
|
|
178
|
+
this.listeners.forEach((cleanup) => cleanup());
|
|
179
|
+
this.listeners = [];
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export { LiveDurationProxy };
|
|
184
|
+
//# sourceMappingURL=LiveDurationProxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiveDurationProxy.js","sources":["../../../../src/core/LiveDurationProxy.ts"],"sourcesContent":["/**\n * LiveDurationProxy - Wraps video element to provide meaningful duration for live streams\n *\n * Live streams report `Infinity` or `NaN` for duration, breaking seek bars and time display.\n * This proxy intercepts the duration getter and returns a calculated value based on:\n * - Buffer end position\n * - Elapsed time since last progress event\n *\n * Based on MistMetaPlayer reference implementation (wrappers/html5.js, dashjs.js)\n */\n\nexport interface LiveDurationProxyOptions {\n /** Whether to constrain seeking to buffered range (default: true) */\n constrainSeek?: boolean;\n /** Live offset from buffer end in seconds (default: 0) */\n liveOffset?: number;\n /** Callback when duration changes */\n onDurationChange?: (duration: number) => void;\n}\n\nexport interface LiveDurationState {\n /** Calculated duration */\n duration: number;\n /** Whether stream is live */\n isLive: boolean;\n /** Buffer end position */\n bufferEnd: number;\n /** Time since last progress */\n elapsed: number;\n}\n\n/**\n * Creates a proxy wrapper around a video element that provides meaningful\n * duration values for live streams.\n */\nexport class LiveDurationProxy {\n private video: HTMLVideoElement;\n private options: Required<LiveDurationProxyOptions>;\n private lastProgressTime: number = 0;\n private lastBufferEnd: number = 0;\n private listeners: Array<() => void> = [];\n private _calculatedDuration: number = 0;\n\n constructor(video: HTMLVideoElement, options: LiveDurationProxyOptions = {}) {\n this.video = video;\n this.options = {\n constrainSeek: options.constrainSeek ?? true,\n liveOffset: options.liveOffset ?? 0,\n onDurationChange: options.onDurationChange ?? (() => {}),\n };\n\n this.setupListeners();\n this.updateDuration();\n }\n\n /**\n * Check if the stream is live\n */\n isLive(): boolean {\n const nativeDuration = this.video.duration;\n return !isFinite(nativeDuration) || nativeDuration === Infinity;\n }\n\n /**\n * Get the calculated duration\n * For live: bufferEnd + elapsedSinceLastProgress\n * For VOD: native duration\n */\n getDuration(): number {\n if (!this.isLive()) {\n return this.video.duration;\n }\n return this._calculatedDuration;\n }\n\n /**\n * Get the current buffer end position\n */\n getBufferEnd(): number {\n const buffered = this.video.buffered;\n if (buffered.length === 0) return 0;\n\n // Find the buffer range containing current time, or the last one\n for (let i = 0; i < buffered.length; i++) {\n if (buffered.start(i) <= this.video.currentTime && buffered.end(i) > this.video.currentTime) {\n return buffered.end(i);\n }\n }\n\n // Return the end of the last buffer range\n return buffered.end(buffered.length - 1);\n }\n\n /**\n * Get the live edge position (where live is)\n */\n getLiveEdge(): number {\n return this.getBufferEnd() - this.options.liveOffset;\n }\n\n /**\n * Get the current latency (distance from live edge)\n */\n getLatency(): number {\n if (!this.isLive()) return 0;\n return Math.max(0, this.getLiveEdge() - this.video.currentTime);\n }\n\n /**\n * Seek to a position, respecting live constraints\n */\n seek(time: number): void {\n if (!this.isLive() || !this.options.constrainSeek) {\n this.video.currentTime = time;\n return;\n }\n\n // Constrain to buffered range for live\n const buffered = this.video.buffered;\n if (buffered.length === 0) {\n this.video.currentTime = time;\n return;\n }\n\n // Find valid seek range\n const bufferStart = buffered.start(0);\n const liveEdge = this.getLiveEdge();\n\n // Clamp to valid range\n const clampedTime = Math.max(bufferStart, Math.min(time, liveEdge));\n this.video.currentTime = clampedTime;\n }\n\n /**\n * Jump to live edge\n */\n jumpToLive(): void {\n if (!this.isLive()) return;\n this.video.currentTime = this.getLiveEdge();\n }\n\n /**\n * Check if currently at live edge (within threshold)\n */\n isAtLiveEdge(threshold: number = 2): boolean {\n if (!this.isLive()) return false;\n return this.getLatency() <= threshold;\n }\n\n /**\n * Get current state\n */\n getState(): LiveDurationState {\n return {\n duration: this.getDuration(),\n isLive: this.isLive(),\n bufferEnd: this.getBufferEnd(),\n elapsed: this.lastProgressTime > 0 ? (Date.now() - this.lastProgressTime) / 1000 : 0,\n };\n }\n\n /**\n * Update the calculated duration\n */\n private updateDuration(): void {\n if (!this.isLive()) {\n this._calculatedDuration = this.video.duration;\n return;\n }\n\n const bufferEnd = this.getBufferEnd();\n const now = Date.now();\n const elapsedSinceProgress =\n this.lastProgressTime > 0 ? (now - this.lastProgressTime) / 1000 : 0;\n\n // MistPlayer formula: buffer_end + elapsed_since_last_progress\n const newDuration = bufferEnd + elapsedSinceProgress;\n\n // Only update if changed significantly (avoid constant updates)\n if (Math.abs(newDuration - this._calculatedDuration) > 0.1) {\n this._calculatedDuration = newDuration;\n this.options.onDurationChange(newDuration);\n }\n\n this.lastBufferEnd = bufferEnd;\n }\n\n /**\n * Setup event listeners for tracking\n */\n private setupListeners(): void {\n const onProgress = () => {\n this.lastProgressTime = Date.now();\n this.updateDuration();\n };\n\n const onTimeUpdate = () => {\n this.updateDuration();\n };\n\n const onDurationChange = () => {\n this.updateDuration();\n };\n\n const onLoadedMetadata = () => {\n this.updateDuration();\n };\n\n this.video.addEventListener(\"progress\", onProgress);\n this.video.addEventListener(\"timeupdate\", onTimeUpdate);\n this.video.addEventListener(\"durationchange\", onDurationChange);\n this.video.addEventListener(\"loadedmetadata\", onLoadedMetadata);\n\n this.listeners = [\n () => this.video.removeEventListener(\"progress\", onProgress),\n () => this.video.removeEventListener(\"timeupdate\", onTimeUpdate),\n () => this.video.removeEventListener(\"durationchange\", onDurationChange),\n () => this.video.removeEventListener(\"loadedmetadata\", onLoadedMetadata),\n ];\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n this.listeners.forEach((cleanup) => cleanup());\n this.listeners = [];\n }\n}\n\n/**\n * Create a Proxy wrapper for a video element that intercepts duration/currentTime\n * This allows existing code to work transparently with live streams.\n *\n * Note: This is an advanced feature - for most cases, use LiveDurationProxy directly.\n */\nexport function createLiveVideoProxy(\n video: HTMLVideoElement,\n options: LiveDurationProxyOptions = {}\n): { proxy: HTMLVideoElement; controller: LiveDurationProxy } {\n const controller = new LiveDurationProxy(video, options);\n\n const proxy = new Proxy(video, {\n get(target, prop, receiver) {\n if (prop === \"duration\") {\n return controller.getDuration();\n }\n\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") {\n return value.bind(target);\n }\n return value;\n },\n\n set(target, prop, value, receiver) {\n if (prop === \"currentTime\" && controller.isLive()) {\n controller.seek(value as number);\n return true;\n }\n return Reflect.set(target, prop, value, receiver);\n },\n });\n\n return { proxy: proxy as HTMLVideoElement, controller };\n}\n\nexport default LiveDurationProxy;\n"],"names":[],"mappings":"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"}
|