@livepeer-frameworks/player-core 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +19493 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.js +19398 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/player.css +2140 -0
- package/dist/types/core/ABRController.d.ts +164 -0
- package/dist/types/core/CodecUtils.d.ts +54 -0
- package/dist/types/core/Disposable.d.ts +61 -0
- package/dist/types/core/EventEmitter.d.ts +73 -0
- package/dist/types/core/GatewayClient.d.ts +144 -0
- package/dist/types/core/InteractionController.d.ts +121 -0
- package/dist/types/core/LiveDurationProxy.d.ts +102 -0
- package/dist/types/core/MetaTrackManager.d.ts +220 -0
- package/dist/types/core/MistReporter.d.ts +163 -0
- package/dist/types/core/MistSignaling.d.ts +148 -0
- package/dist/types/core/PlayerController.d.ts +665 -0
- package/dist/types/core/PlayerInterface.d.ts +230 -0
- package/dist/types/core/PlayerManager.d.ts +182 -0
- package/dist/types/core/PlayerRegistry.d.ts +27 -0
- package/dist/types/core/QualityMonitor.d.ts +184 -0
- package/dist/types/core/ScreenWakeLockManager.d.ts +70 -0
- package/dist/types/core/SeekingUtils.d.ts +142 -0
- package/dist/types/core/StreamStateClient.d.ts +108 -0
- package/dist/types/core/SubtitleManager.d.ts +111 -0
- package/dist/types/core/TelemetryReporter.d.ts +79 -0
- package/dist/types/core/TimeFormat.d.ts +97 -0
- package/dist/types/core/TimerManager.d.ts +83 -0
- package/dist/types/core/UrlUtils.d.ts +81 -0
- package/dist/types/core/detector.d.ts +149 -0
- package/dist/types/core/index.d.ts +49 -0
- package/dist/types/core/scorer.d.ts +167 -0
- package/dist/types/core/selector.d.ts +9 -0
- package/dist/types/index.d.ts +45 -0
- package/dist/types/lib/utils.d.ts +2 -0
- package/dist/types/players/DashJsPlayer.d.ts +102 -0
- package/dist/types/players/HlsJsPlayer.d.ts +70 -0
- package/dist/types/players/MewsWsPlayer/SourceBufferManager.d.ts +119 -0
- package/dist/types/players/MewsWsPlayer/WebSocketManager.d.ts +60 -0
- package/dist/types/players/MewsWsPlayer/index.d.ts +220 -0
- package/dist/types/players/MewsWsPlayer/types.d.ts +89 -0
- package/dist/types/players/MistPlayer.d.ts +25 -0
- package/dist/types/players/MistWebRTCPlayer/index.d.ts +133 -0
- package/dist/types/players/NativePlayer.d.ts +143 -0
- package/dist/types/players/VideoJsPlayer.d.ts +59 -0
- package/dist/types/players/WebCodecsPlayer/JitterBuffer.d.ts +118 -0
- package/dist/types/players/WebCodecsPlayer/LatencyProfiles.d.ts +64 -0
- package/dist/types/players/WebCodecsPlayer/RawChunkParser.d.ts +63 -0
- package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +174 -0
- package/dist/types/players/WebCodecsPlayer/WebSocketController.d.ts +164 -0
- package/dist/types/players/WebCodecsPlayer/index.d.ts +149 -0
- package/dist/types/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.d.ts +105 -0
- package/dist/types/players/WebCodecsPlayer/types.d.ts +395 -0
- package/dist/types/players/WebCodecsPlayer/worker/decoder.worker.d.ts +13 -0
- package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +197 -0
- package/dist/types/players/index.d.ts +14 -0
- package/dist/types/styles/index.d.ts +11 -0
- package/dist/types/types.d.ts +363 -0
- package/dist/types/vanilla/FrameWorksPlayer.d.ts +143 -0
- package/dist/types/vanilla/index.d.ts +19 -0
- package/dist/workers/decoder.worker.js +989 -0
- package/dist/workers/decoder.worker.js.map +1 -0
- package/package.json +80 -0
- package/src/core/ABRController.ts +550 -0
- package/src/core/CodecUtils.ts +257 -0
- package/src/core/Disposable.ts +120 -0
- package/src/core/EventEmitter.ts +113 -0
- package/src/core/GatewayClient.ts +439 -0
- package/src/core/InteractionController.ts +712 -0
- package/src/core/LiveDurationProxy.ts +270 -0
- package/src/core/MetaTrackManager.ts +753 -0
- package/src/core/MistReporter.ts +543 -0
- package/src/core/MistSignaling.ts +346 -0
- package/src/core/PlayerController.ts +2829 -0
- package/src/core/PlayerInterface.ts +432 -0
- package/src/core/PlayerManager.ts +900 -0
- package/src/core/PlayerRegistry.ts +149 -0
- package/src/core/QualityMonitor.ts +597 -0
- package/src/core/ScreenWakeLockManager.ts +163 -0
- package/src/core/SeekingUtils.ts +364 -0
- package/src/core/StreamStateClient.ts +457 -0
- package/src/core/SubtitleManager.ts +297 -0
- package/src/core/TelemetryReporter.ts +308 -0
- package/src/core/TimeFormat.ts +205 -0
- package/src/core/TimerManager.ts +209 -0
- package/src/core/UrlUtils.ts +179 -0
- package/src/core/detector.ts +382 -0
- package/src/core/index.ts +140 -0
- package/src/core/scorer.ts +553 -0
- package/src/core/selector.ts +16 -0
- package/src/global.d.ts +11 -0
- package/src/index.ts +75 -0
- package/src/lib/utils.ts +6 -0
- package/src/players/DashJsPlayer.ts +642 -0
- package/src/players/HlsJsPlayer.ts +483 -0
- package/src/players/MewsWsPlayer/SourceBufferManager.ts +572 -0
- package/src/players/MewsWsPlayer/WebSocketManager.ts +241 -0
- package/src/players/MewsWsPlayer/index.ts +1065 -0
- package/src/players/MewsWsPlayer/types.ts +106 -0
- package/src/players/MistPlayer.ts +188 -0
- package/src/players/MistWebRTCPlayer/index.ts +703 -0
- package/src/players/NativePlayer.ts +820 -0
- package/src/players/VideoJsPlayer.ts +643 -0
- package/src/players/WebCodecsPlayer/JitterBuffer.ts +299 -0
- package/src/players/WebCodecsPlayer/LatencyProfiles.ts +151 -0
- package/src/players/WebCodecsPlayer/RawChunkParser.ts +151 -0
- package/src/players/WebCodecsPlayer/SyncController.ts +456 -0
- package/src/players/WebCodecsPlayer/WebSocketController.ts +564 -0
- package/src/players/WebCodecsPlayer/index.ts +1650 -0
- package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +379 -0
- package/src/players/WebCodecsPlayer/types.ts +542 -0
- package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +1360 -0
- package/src/players/WebCodecsPlayer/worker/types.ts +276 -0
- package/src/players/index.ts +22 -0
- package/src/styles/animations.css +21 -0
- package/src/styles/index.ts +52 -0
- package/src/styles/player.css +2126 -0
- package/src/styles/tailwind.css +1015 -0
- package/src/types.ts +421 -0
- package/src/vanilla/FrameWorksPlayer.ts +367 -0
- package/src/vanilla/index.ts +22 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SeekingUtils.ts
|
|
3
|
+
*
|
|
4
|
+
* Centralized seeking and live detection logic for player controls.
|
|
5
|
+
* Used by React, Svelte, and Vanilla wrappers to ensure consistent behavior.
|
|
6
|
+
*
|
|
7
|
+
* Key concepts:
|
|
8
|
+
* - Seekable range: The portion of the stream that can be seeked to
|
|
9
|
+
* - Live edge: The furthest point in time that can be played (live point)
|
|
10
|
+
* - Near live: Whether playback is close enough to live edge to show "LIVE" badge
|
|
11
|
+
* - Latency tier: Protocol-based classification affecting live detection thresholds
|
|
12
|
+
*/
|
|
13
|
+
import type { MistStreamInfo } from '../types';
|
|
14
|
+
export type LatencyTier = 'ultra-low' | 'low' | 'medium' | 'high';
|
|
15
|
+
export interface LiveThresholds {
|
|
16
|
+
/** Seconds behind live edge to exit "LIVE" state (become clickable) */
|
|
17
|
+
exitLive: number;
|
|
18
|
+
/** Seconds behind live edge to enter "LIVE" state (become non-clickable) */
|
|
19
|
+
enterLive: number;
|
|
20
|
+
}
|
|
21
|
+
export interface SeekableRange {
|
|
22
|
+
/** Start of seekable range in seconds */
|
|
23
|
+
seekableStart: number;
|
|
24
|
+
/** End of seekable range (live edge) in seconds */
|
|
25
|
+
liveEdge: number;
|
|
26
|
+
}
|
|
27
|
+
export interface SeekableRangeParams {
|
|
28
|
+
isLive: boolean;
|
|
29
|
+
video: HTMLVideoElement | null;
|
|
30
|
+
mistStreamInfo?: MistStreamInfo;
|
|
31
|
+
currentTime: number;
|
|
32
|
+
duration: number;
|
|
33
|
+
}
|
|
34
|
+
export interface CanSeekParams {
|
|
35
|
+
video: HTMLVideoElement | null;
|
|
36
|
+
isLive: boolean;
|
|
37
|
+
duration: number;
|
|
38
|
+
bufferWindowMs?: number;
|
|
39
|
+
playerCanSeek?: () => boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Latency tier thresholds for "near live" detection.
|
|
43
|
+
* Different protocols have vastly different latency expectations.
|
|
44
|
+
*
|
|
45
|
+
* exitLive: How far behind (seconds) before we show "behind live" indicator
|
|
46
|
+
* enterLive: How close to live (seconds) before we show "LIVE" badge again
|
|
47
|
+
*
|
|
48
|
+
* The gap between exitLive and enterLive creates hysteresis to prevent flicker.
|
|
49
|
+
*/
|
|
50
|
+
export declare const LATENCY_TIERS: Record<LatencyTier, LiveThresholds>;
|
|
51
|
+
/**
|
|
52
|
+
* Playback speed presets for UI controls.
|
|
53
|
+
*/
|
|
54
|
+
export declare const SPEED_PRESETS: readonly [0.5, 1, 1.5, 2];
|
|
55
|
+
/**
|
|
56
|
+
* Default fallback buffer window when no other info available (in seconds).
|
|
57
|
+
* Aligned with MistServer reference player's 60-second default.
|
|
58
|
+
*/
|
|
59
|
+
export declare const DEFAULT_BUFFER_WINDOW_SEC = 60;
|
|
60
|
+
/**
|
|
61
|
+
* Detect latency tier from source type string.
|
|
62
|
+
*
|
|
63
|
+
* @param sourceType - MIME type or protocol identifier (e.g., 'whep', 'ws/video/mp4')
|
|
64
|
+
* @returns Latency tier classification
|
|
65
|
+
*/
|
|
66
|
+
export declare function getLatencyTier(sourceType?: string): LatencyTier;
|
|
67
|
+
/**
|
|
68
|
+
* Check if video element is using WebRTC/MediaStream source.
|
|
69
|
+
* WebRTC streams have special constraints (no seeking, no playback rate changes).
|
|
70
|
+
*
|
|
71
|
+
* @param video - HTML video element
|
|
72
|
+
* @returns true if source is a MediaStream
|
|
73
|
+
*/
|
|
74
|
+
export declare function isMediaStreamSource(video: HTMLVideoElement | null): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Check if playback rate adjustment is supported.
|
|
77
|
+
* WebRTC/MediaStream sources don't support playback rate changes.
|
|
78
|
+
*
|
|
79
|
+
* @param video - HTML video element
|
|
80
|
+
* @returns true if playback rate can be changed
|
|
81
|
+
*/
|
|
82
|
+
export declare function supportsPlaybackRate(video: HTMLVideoElement | null): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Calculate seekable range for live or VOD streams.
|
|
85
|
+
*
|
|
86
|
+
* Priority order:
|
|
87
|
+
* 1. Browser's video.seekable ranges (most accurate for MSE-based players)
|
|
88
|
+
* 2. Track firstms/lastms from MistServer metadata
|
|
89
|
+
* 3. buffer_window from MistServer signaling
|
|
90
|
+
* 4. Fallback (only for non-WebRTC sources)
|
|
91
|
+
*
|
|
92
|
+
* @param params - Calculation parameters
|
|
93
|
+
* @returns Seekable range with start and live edge
|
|
94
|
+
*/
|
|
95
|
+
export declare function calculateSeekableRange(params: SeekableRangeParams): SeekableRange;
|
|
96
|
+
/**
|
|
97
|
+
* Determine if seeking is supported for the current stream.
|
|
98
|
+
*
|
|
99
|
+
* @param params - Check parameters
|
|
100
|
+
* @returns true if seeking is available
|
|
101
|
+
*/
|
|
102
|
+
export declare function canSeekStream(params: CanSeekParams): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Calculate live detection thresholds, optionally scaled by buffer_window.
|
|
105
|
+
*
|
|
106
|
+
* For medium/high latency tiers, scales thresholds based on the actual
|
|
107
|
+
* buffer window to provide more appropriate "near live" detection.
|
|
108
|
+
*
|
|
109
|
+
* @param sourceType - Protocol/MIME type for tier detection
|
|
110
|
+
* @param isWebRTC - Whether source is WebRTC (overrides tier to ultra-low)
|
|
111
|
+
* @param bufferWindowMs - Optional buffer window in milliseconds
|
|
112
|
+
* @returns Thresholds for entering/exiting "LIVE" state
|
|
113
|
+
*/
|
|
114
|
+
export declare function calculateLiveThresholds(sourceType?: string, isWebRTC?: boolean, bufferWindowMs?: number): LiveThresholds;
|
|
115
|
+
/**
|
|
116
|
+
* Calculate whether playback is "near live" using hysteresis.
|
|
117
|
+
*
|
|
118
|
+
* Hysteresis prevents flip-flopping when hovering near the threshold:
|
|
119
|
+
* - To EXIT "LIVE" state: must be > exitLive + margin behind
|
|
120
|
+
* - To ENTER "LIVE" state: must be < enterLive - margin behind
|
|
121
|
+
*
|
|
122
|
+
* @param currentTime - Current playback position in seconds
|
|
123
|
+
* @param liveEdge - Live edge position in seconds
|
|
124
|
+
* @param thresholds - Enter/exit thresholds
|
|
125
|
+
* @param currentState - Current isNearLive state
|
|
126
|
+
* @returns New isNearLive state
|
|
127
|
+
*/
|
|
128
|
+
export declare function calculateIsNearLive(currentTime: number, liveEdge: number, thresholds: LiveThresholds, currentState: boolean): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Determine if content is live based on available metadata.
|
|
131
|
+
*
|
|
132
|
+
* Priority:
|
|
133
|
+
* 1. Explicit isContentLive flag (highest priority)
|
|
134
|
+
* 2. MistServer stream type
|
|
135
|
+
* 3. Duration check (non-finite = live)
|
|
136
|
+
*
|
|
137
|
+
* @param isContentLive - Explicit live flag from content metadata
|
|
138
|
+
* @param mistStreamInfo - MistServer stream info
|
|
139
|
+
* @param duration - Video duration
|
|
140
|
+
* @returns true if content is live
|
|
141
|
+
*/
|
|
142
|
+
export declare function isLiveContent(isContentLive?: boolean, mistStreamInfo?: MistStreamInfo, duration?: number): boolean;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StreamStateClient.ts
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic client for polling MistServer stream status via WebSocket or HTTP.
|
|
5
|
+
* Extracted from useStreamState.ts for use in headless core.
|
|
6
|
+
*/
|
|
7
|
+
import { TypedEventEmitter } from './EventEmitter';
|
|
8
|
+
import type { StreamState } from '../types';
|
|
9
|
+
export interface StreamStateClientConfig {
|
|
10
|
+
/** MistServer base URL (e.g., https://mist.example.com) */
|
|
11
|
+
mistBaseUrl: string;
|
|
12
|
+
/** Stream name to poll */
|
|
13
|
+
streamName: string;
|
|
14
|
+
/** Poll interval in ms for HTTP fallback (default: 3000) */
|
|
15
|
+
pollInterval?: number;
|
|
16
|
+
/** Use WebSocket if available (default: true) */
|
|
17
|
+
useWebSocket?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface StreamStateClientEvents {
|
|
20
|
+
/** Emitted when stream state changes */
|
|
21
|
+
stateChange: {
|
|
22
|
+
state: StreamState;
|
|
23
|
+
};
|
|
24
|
+
/** Emitted when stream comes online */
|
|
25
|
+
online: void;
|
|
26
|
+
/** Emitted when stream goes offline */
|
|
27
|
+
offline: void;
|
|
28
|
+
/** Emitted on connection error */
|
|
29
|
+
error: {
|
|
30
|
+
error: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Client for polling MistServer stream status via WebSocket or HTTP.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const client = new StreamStateClient({
|
|
39
|
+
* mistBaseUrl: 'https://mist.example.com',
|
|
40
|
+
* streamName: 'my-stream',
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* client.on('stateChange', ({ state }) => console.log('State:', state));
|
|
44
|
+
* client.on('online', () => console.log('Stream is online!'));
|
|
45
|
+
* client.on('offline', () => console.log('Stream is offline'));
|
|
46
|
+
*
|
|
47
|
+
* client.start();
|
|
48
|
+
* // ...later
|
|
49
|
+
* client.stop();
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare class StreamStateClient extends TypedEventEmitter<StreamStateClientEvents> {
|
|
53
|
+
private config;
|
|
54
|
+
private state;
|
|
55
|
+
private ws;
|
|
56
|
+
private timers;
|
|
57
|
+
private isRunning;
|
|
58
|
+
private wasOnline;
|
|
59
|
+
private connectionId;
|
|
60
|
+
private static readonly CONNECTION_DEBOUNCE_MS;
|
|
61
|
+
constructor(config: StreamStateClientConfig);
|
|
62
|
+
/**
|
|
63
|
+
* Start polling/WebSocket connection.
|
|
64
|
+
* Always does initial HTTP poll to get full stream info (including sources),
|
|
65
|
+
* then connects WebSocket for real-time status updates.
|
|
66
|
+
*
|
|
67
|
+
* Debounced to prevent orphaned connections during rapid mount/unmount cycles.
|
|
68
|
+
*/
|
|
69
|
+
start(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Stop polling and close connections.
|
|
72
|
+
*/
|
|
73
|
+
stop(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Manual refresh - trigger an immediate poll.
|
|
76
|
+
*/
|
|
77
|
+
refresh(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Get the underlying WebSocket connection (for MistReporter integration).
|
|
80
|
+
* Returns null if WebSocket is not connected.
|
|
81
|
+
*/
|
|
82
|
+
getSocket(): WebSocket | null;
|
|
83
|
+
/**
|
|
84
|
+
* Check if the WebSocket is connected and ready.
|
|
85
|
+
*/
|
|
86
|
+
isSocketReady(): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Get current stream state.
|
|
89
|
+
*/
|
|
90
|
+
getState(): StreamState;
|
|
91
|
+
/**
|
|
92
|
+
* Check if stream is online.
|
|
93
|
+
*/
|
|
94
|
+
isOnline(): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Update configuration (stops and restarts if running).
|
|
97
|
+
*/
|
|
98
|
+
updateConfig(config: Partial<StreamStateClientConfig>): void;
|
|
99
|
+
/**
|
|
100
|
+
* Clean up resources.
|
|
101
|
+
*/
|
|
102
|
+
destroy(): void;
|
|
103
|
+
private connectWebSocket;
|
|
104
|
+
private pollHttp;
|
|
105
|
+
private processStreamInfo;
|
|
106
|
+
private setState;
|
|
107
|
+
}
|
|
108
|
+
export default StreamStateClient;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubtitleManager - WebVTT subtitle track management
|
|
3
|
+
*
|
|
4
|
+
* Based on MistMetaPlayer's subtitle handling (wrappers/html5.js, webrtc.js).
|
|
5
|
+
* Manages text tracks on video elements with support for:
|
|
6
|
+
* - Loading WebVTT from MistServer URLs
|
|
7
|
+
* - Multiple subtitle track selection
|
|
8
|
+
* - Sync correction for WebRTC seek offsets
|
|
9
|
+
*/
|
|
10
|
+
export interface SubtitleTrackInfo {
|
|
11
|
+
/** Track ID (from MistServer) */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Display label */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Language code (e.g., 'en', 'es') */
|
|
16
|
+
lang: string;
|
|
17
|
+
/** Source URL for WebVTT file */
|
|
18
|
+
src: string;
|
|
19
|
+
/** Whether this is the default track */
|
|
20
|
+
default?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface SubtitleManagerConfig {
|
|
23
|
+
/** Base URL for MistServer (for constructing track URLs) */
|
|
24
|
+
mistBaseUrl?: string;
|
|
25
|
+
/** Stream name */
|
|
26
|
+
streamName?: string;
|
|
27
|
+
/** URL append string (auth tokens, etc.) */
|
|
28
|
+
urlAppend?: string;
|
|
29
|
+
/** Debug logging */
|
|
30
|
+
debug?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* SubtitleManager handles text track lifecycle on a video element
|
|
34
|
+
*/
|
|
35
|
+
export declare class SubtitleManager {
|
|
36
|
+
private video;
|
|
37
|
+
private config;
|
|
38
|
+
private currentTrackId;
|
|
39
|
+
private seekOffset;
|
|
40
|
+
private debug;
|
|
41
|
+
private listeners;
|
|
42
|
+
constructor(config?: SubtitleManagerConfig);
|
|
43
|
+
/**
|
|
44
|
+
* Attach to a video element
|
|
45
|
+
*/
|
|
46
|
+
attach(video: HTMLVideoElement): void;
|
|
47
|
+
/**
|
|
48
|
+
* Detach from video element
|
|
49
|
+
*/
|
|
50
|
+
detach(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Get available text tracks from the video element
|
|
53
|
+
*/
|
|
54
|
+
getTextTracks(): TextTrack[];
|
|
55
|
+
/**
|
|
56
|
+
* Get all track elements from the video
|
|
57
|
+
*/
|
|
58
|
+
getTrackElements(): HTMLTrackElement[];
|
|
59
|
+
/**
|
|
60
|
+
* Set the active subtitle track
|
|
61
|
+
* Pass null to disable subtitles
|
|
62
|
+
*/
|
|
63
|
+
setSubtitle(track: SubtitleTrackInfo | null): void;
|
|
64
|
+
/**
|
|
65
|
+
* Build track URL with base URL and append params
|
|
66
|
+
*/
|
|
67
|
+
private buildTrackUrl;
|
|
68
|
+
/**
|
|
69
|
+
* Create subtitle track info from MistServer track metadata
|
|
70
|
+
*/
|
|
71
|
+
static createTrackInfo(trackId: string, label: string, lang: string, baseUrl: string, streamName: string): SubtitleTrackInfo;
|
|
72
|
+
/**
|
|
73
|
+
* Remove all track elements from video
|
|
74
|
+
*/
|
|
75
|
+
removeAllTracks(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Get currently active track ID
|
|
78
|
+
*/
|
|
79
|
+
getCurrentTrackId(): string | null;
|
|
80
|
+
/**
|
|
81
|
+
* Set seek offset for WebRTC sync correction
|
|
82
|
+
* WebRTC playback has a seek offset that needs to be applied to subtitle timing
|
|
83
|
+
*/
|
|
84
|
+
setSeekOffset(offset: number): void;
|
|
85
|
+
/**
|
|
86
|
+
* Correct subtitle timing based on seek offset
|
|
87
|
+
* This is needed for WebRTC where video.currentTime doesn't match actual playback position
|
|
88
|
+
*/
|
|
89
|
+
private correctSubtitleSync;
|
|
90
|
+
/**
|
|
91
|
+
* Parse subtitle tracks from MistServer stream info
|
|
92
|
+
*/
|
|
93
|
+
static parseTracksFromStreamInfo(streamInfo: {
|
|
94
|
+
meta?: {
|
|
95
|
+
tracks?: Record<string, {
|
|
96
|
+
type: string;
|
|
97
|
+
codec: string;
|
|
98
|
+
lang?: string;
|
|
99
|
+
}>;
|
|
100
|
+
};
|
|
101
|
+
}, baseUrl: string, streamName: string): SubtitleTrackInfo[];
|
|
102
|
+
/**
|
|
103
|
+
* Debug logging
|
|
104
|
+
*/
|
|
105
|
+
private log;
|
|
106
|
+
/**
|
|
107
|
+
* Cleanup
|
|
108
|
+
*/
|
|
109
|
+
destroy(): void;
|
|
110
|
+
}
|
|
111
|
+
export default SubtitleManager;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { PlaybackQuality, ContentType } from '../types';
|
|
2
|
+
export interface TelemetryReporterConfig {
|
|
3
|
+
/** Telemetry endpoint URL */
|
|
4
|
+
endpoint: string;
|
|
5
|
+
/** Auth token for endpoint */
|
|
6
|
+
authToken?: string;
|
|
7
|
+
/** Report interval in ms (default: 5000) */
|
|
8
|
+
interval?: number;
|
|
9
|
+
/** Batch size before flush (default: 1) */
|
|
10
|
+
batchSize?: number;
|
|
11
|
+
/** Content ID being played */
|
|
12
|
+
contentId: string;
|
|
13
|
+
/** Content type */
|
|
14
|
+
contentType: ContentType;
|
|
15
|
+
/** Player type name */
|
|
16
|
+
playerType: string;
|
|
17
|
+
/** Protocol being used */
|
|
18
|
+
protocol: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* TelemetryReporter - Sends playback metrics to server
|
|
22
|
+
*
|
|
23
|
+
* Features:
|
|
24
|
+
* - Batched reporting at configurable interval
|
|
25
|
+
* - Retry with exponential backoff on failure
|
|
26
|
+
* - Uses navigator.sendBeacon() for reliable page unload reporting
|
|
27
|
+
* - Tracks errors during playback
|
|
28
|
+
*/
|
|
29
|
+
export declare class TelemetryReporter {
|
|
30
|
+
private config;
|
|
31
|
+
private sessionId;
|
|
32
|
+
private intervalId;
|
|
33
|
+
private pendingPayloads;
|
|
34
|
+
private errors;
|
|
35
|
+
private stallCount;
|
|
36
|
+
private totalStallMs;
|
|
37
|
+
private lastStallStart;
|
|
38
|
+
private videoElement;
|
|
39
|
+
private qualityGetter;
|
|
40
|
+
private listeners;
|
|
41
|
+
constructor(config: TelemetryReporterConfig);
|
|
42
|
+
/**
|
|
43
|
+
* Start telemetry reporting
|
|
44
|
+
*/
|
|
45
|
+
start(videoElement: HTMLVideoElement, qualityGetter?: () => PlaybackQuality | null): void;
|
|
46
|
+
/**
|
|
47
|
+
* Stop telemetry reporting
|
|
48
|
+
*/
|
|
49
|
+
stop(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Record a custom error
|
|
52
|
+
*/
|
|
53
|
+
recordError(code: string, message: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Generate telemetry payload
|
|
56
|
+
*/
|
|
57
|
+
private generatePayload;
|
|
58
|
+
/**
|
|
59
|
+
* Send telemetry report
|
|
60
|
+
*/
|
|
61
|
+
private report;
|
|
62
|
+
/**
|
|
63
|
+
* Flush pending payloads (async)
|
|
64
|
+
*/
|
|
65
|
+
private flush;
|
|
66
|
+
/**
|
|
67
|
+
* Flush synchronously using sendBeacon (for page unload)
|
|
68
|
+
*/
|
|
69
|
+
private flushSync;
|
|
70
|
+
/**
|
|
71
|
+
* Get session ID
|
|
72
|
+
*/
|
|
73
|
+
getSessionId(): string;
|
|
74
|
+
/**
|
|
75
|
+
* Check if reporting is active
|
|
76
|
+
*/
|
|
77
|
+
isActive(): boolean;
|
|
78
|
+
}
|
|
79
|
+
export default TelemetryReporter;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TimeFormat.ts
|
|
3
|
+
*
|
|
4
|
+
* Time formatting utilities for player controls.
|
|
5
|
+
* Used by React, Svelte, and Vanilla wrappers.
|
|
6
|
+
*/
|
|
7
|
+
export interface TimeDisplayParams {
|
|
8
|
+
isLive: boolean;
|
|
9
|
+
currentTime: number;
|
|
10
|
+
duration: number;
|
|
11
|
+
liveEdge: number;
|
|
12
|
+
seekableStart: number;
|
|
13
|
+
/** Unix timestamp (ms) at stream time 0 - for wall-clock display */
|
|
14
|
+
unixoffset?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Format seconds as MM:SS or HH:MM:SS.
|
|
18
|
+
*
|
|
19
|
+
* @param seconds - Time in seconds
|
|
20
|
+
* @returns Formatted time string, or "LIVE" for invalid input
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* formatTime(65) // "01:05"
|
|
24
|
+
* formatTime(3665) // "1:01:05"
|
|
25
|
+
* formatTime(-1) // "LIVE"
|
|
26
|
+
* formatTime(NaN) // "LIVE"
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatTime(seconds: number): string;
|
|
29
|
+
/**
|
|
30
|
+
* Format a Date as wall-clock time (HH:MM:SS).
|
|
31
|
+
*
|
|
32
|
+
* @param date - Date object
|
|
33
|
+
* @returns Formatted time string in HH:MM:SS format
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* formatClockTime(new Date('2024-01-15T14:30:45')) // "14:30:45"
|
|
37
|
+
*/
|
|
38
|
+
export declare function formatClockTime(date: Date): string;
|
|
39
|
+
/**
|
|
40
|
+
* Format time display for player controls.
|
|
41
|
+
*
|
|
42
|
+
* For live streams:
|
|
43
|
+
* - With unixoffset: Shows actual wall-clock time (HH:MM:SS)
|
|
44
|
+
* - With seekable window: Shows time behind live (-MM:SS) or "LIVE"
|
|
45
|
+
* - Fallback: Shows elapsed time
|
|
46
|
+
*
|
|
47
|
+
* For VOD:
|
|
48
|
+
* - Shows "current / duration" (MM:SS / MM:SS)
|
|
49
|
+
*
|
|
50
|
+
* @param params - Display parameters
|
|
51
|
+
* @returns Formatted time display string
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // Live with unixoffset
|
|
55
|
+
* formatTimeDisplay({ isLive: true, currentTime: 60, unixoffset: 1705330245000, ... })
|
|
56
|
+
* // "14:30:45"
|
|
57
|
+
*
|
|
58
|
+
* // Live behind
|
|
59
|
+
* formatTimeDisplay({ isLive: true, currentTime: 50, liveEdge: 60, ... })
|
|
60
|
+
* // "-00:10"
|
|
61
|
+
*
|
|
62
|
+
* // VOD
|
|
63
|
+
* formatTimeDisplay({ isLive: false, currentTime: 65, duration: 300, ... })
|
|
64
|
+
* // "01:05 / 05:00"
|
|
65
|
+
*/
|
|
66
|
+
export declare function formatTimeDisplay(params: TimeDisplayParams): string;
|
|
67
|
+
/**
|
|
68
|
+
* Format time for seek bar tooltip.
|
|
69
|
+
* For live streams, can show time relative to live edge.
|
|
70
|
+
*
|
|
71
|
+
* @param time - Time position in seconds
|
|
72
|
+
* @param isLive - Whether stream is live
|
|
73
|
+
* @param liveEdge - Live edge position (for relative display)
|
|
74
|
+
* @returns Formatted tooltip time
|
|
75
|
+
*/
|
|
76
|
+
export declare function formatTooltipTime(time: number, isLive: boolean, liveEdge?: number): string;
|
|
77
|
+
/**
|
|
78
|
+
* Format duration for display (e.g., in stats panel).
|
|
79
|
+
* Handles edge cases like infinite duration for live streams.
|
|
80
|
+
*
|
|
81
|
+
* @param duration - Duration in seconds
|
|
82
|
+
* @param isLive - Whether content is live
|
|
83
|
+
* @returns Formatted duration string
|
|
84
|
+
*/
|
|
85
|
+
export declare function formatDuration(duration: number, isLive?: boolean): string;
|
|
86
|
+
/**
|
|
87
|
+
* Parse time string (HH:MM:SS or MM:SS) to seconds.
|
|
88
|
+
*
|
|
89
|
+
* @param timeStr - Time string to parse
|
|
90
|
+
* @returns Time in seconds, or NaN if invalid
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* parseTime("01:30") // 90
|
|
94
|
+
* parseTime("1:30:45") // 5445
|
|
95
|
+
* parseTime("invalid") // NaN
|
|
96
|
+
*/
|
|
97
|
+
export declare function parseTime(timeStr: string): number;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TimerManager - Centralized timer management for memory leak prevention
|
|
3
|
+
*
|
|
4
|
+
* Tracks all setTimeout/setInterval calls and provides bulk cleanup.
|
|
5
|
+
* Based on MistMetaPlayer's MistVideo.timers pattern.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```ts
|
|
9
|
+
* const timers = new TimerManager();
|
|
10
|
+
*
|
|
11
|
+
* // Start a timeout
|
|
12
|
+
* const id = timers.start(() => console.log('fired'), 1000);
|
|
13
|
+
*
|
|
14
|
+
* // Start an interval
|
|
15
|
+
* const intervalId = timers.startInterval(() => console.log('tick'), 500);
|
|
16
|
+
*
|
|
17
|
+
* // Stop a specific timer
|
|
18
|
+
* timers.stop(id);
|
|
19
|
+
*
|
|
20
|
+
* // Stop all timers (on cleanup/destroy)
|
|
21
|
+
* timers.stopAll();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class TimerManager {
|
|
25
|
+
private timers;
|
|
26
|
+
private nextId;
|
|
27
|
+
private debug;
|
|
28
|
+
constructor(options?: {
|
|
29
|
+
debug?: boolean;
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Start a timeout
|
|
33
|
+
* @param callback Function to call after delay
|
|
34
|
+
* @param delay Delay in milliseconds
|
|
35
|
+
* @param label Optional label for debugging
|
|
36
|
+
* @returns Timer ID (internal, not the native timeout ID)
|
|
37
|
+
*/
|
|
38
|
+
start(callback: () => void, delay: number, label?: string): number;
|
|
39
|
+
/**
|
|
40
|
+
* Start an interval
|
|
41
|
+
* @param callback Function to call repeatedly
|
|
42
|
+
* @param interval Interval in milliseconds
|
|
43
|
+
* @param label Optional label for debugging
|
|
44
|
+
* @returns Timer ID (internal, not the native interval ID)
|
|
45
|
+
*/
|
|
46
|
+
startInterval(callback: () => void, interval: number, label?: string): number;
|
|
47
|
+
/**
|
|
48
|
+
* Stop a specific timer
|
|
49
|
+
* @param internalId The timer ID returned by start() or startInterval()
|
|
50
|
+
*/
|
|
51
|
+
stop(internalId: number): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Stop all active timers
|
|
54
|
+
* Call this on component unmount/destroy to prevent memory leaks
|
|
55
|
+
*/
|
|
56
|
+
stopAll(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get count of active timers
|
|
59
|
+
*/
|
|
60
|
+
get activeCount(): number;
|
|
61
|
+
/**
|
|
62
|
+
* Check if a timer is active
|
|
63
|
+
*/
|
|
64
|
+
isActive(internalId: number): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Get remaining time for a timeout (0 for intervals or expired)
|
|
67
|
+
*/
|
|
68
|
+
getRemainingTime(internalId: number): number;
|
|
69
|
+
/**
|
|
70
|
+
* Get debug info about all active timers
|
|
71
|
+
*/
|
|
72
|
+
getDebugInfo(): Array<{
|
|
73
|
+
id: number;
|
|
74
|
+
type: 'timeout' | 'interval';
|
|
75
|
+
label?: string;
|
|
76
|
+
remainingMs?: number;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Cleanup - alias for stopAll()
|
|
80
|
+
*/
|
|
81
|
+
destroy(): void;
|
|
82
|
+
}
|
|
83
|
+
export default TimerManager;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UrlUtils - URL manipulation utilities
|
|
3
|
+
*
|
|
4
|
+
* Based on MistMetaPlayer's urlappend functionality.
|
|
5
|
+
* Provides helpers for appending query parameters to URLs.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Append query parameters to a URL
|
|
9
|
+
* Handles URLs that already have query parameters
|
|
10
|
+
*
|
|
11
|
+
* @param url - Base URL
|
|
12
|
+
* @param params - Parameters to append (string or object)
|
|
13
|
+
* @returns URL with appended parameters
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* appendUrlParams('https://example.com/video.m3u8', 'token=abc&session=123')
|
|
18
|
+
* // => 'https://example.com/video.m3u8?token=abc&session=123'
|
|
19
|
+
*
|
|
20
|
+
* appendUrlParams('https://example.com/video.m3u8?existing=param', 'token=abc')
|
|
21
|
+
* // => 'https://example.com/video.m3u8?existing=param&token=abc'
|
|
22
|
+
*
|
|
23
|
+
* appendUrlParams('https://example.com/video.m3u8', { token: 'abc', session: '123' })
|
|
24
|
+
* // => 'https://example.com/video.m3u8?token=abc&session=123'
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function appendUrlParams(url: string, params: string | Record<string, string | number | boolean | undefined | null>): string;
|
|
28
|
+
/**
|
|
29
|
+
* Parse query parameters from a URL
|
|
30
|
+
*
|
|
31
|
+
* @param url - URL to parse
|
|
32
|
+
* @returns Object with query parameters
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseUrlParams(url: string): Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* Remove query parameters from a URL
|
|
37
|
+
*
|
|
38
|
+
* @param url - URL to strip
|
|
39
|
+
* @returns URL without query parameters
|
|
40
|
+
*/
|
|
41
|
+
export declare function stripUrlParams(url: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Build a URL with query parameters
|
|
44
|
+
*
|
|
45
|
+
* @param baseUrl - Base URL
|
|
46
|
+
* @param params - Query parameters
|
|
47
|
+
* @returns Complete URL
|
|
48
|
+
*/
|
|
49
|
+
export declare function buildUrl(baseUrl: string, params: Record<string, string | number | boolean | undefined | null>): string;
|
|
50
|
+
/**
|
|
51
|
+
* Check if URL uses secure protocol (https/wss)
|
|
52
|
+
*/
|
|
53
|
+
export declare function isSecureUrl(url: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Convert HTTP URL to WebSocket URL
|
|
56
|
+
* http:// -> ws://
|
|
57
|
+
* https:// -> wss://
|
|
58
|
+
*/
|
|
59
|
+
export declare function httpToWs(url: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Convert WebSocket URL to HTTP URL
|
|
62
|
+
* ws:// -> http://
|
|
63
|
+
* wss:// -> https://
|
|
64
|
+
*/
|
|
65
|
+
export declare function wsToHttp(url: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* Ensure URL uses the same protocol as the current page
|
|
68
|
+
* Useful for avoiding mixed content issues
|
|
69
|
+
*/
|
|
70
|
+
export declare function matchPageProtocol(url: string): string;
|
|
71
|
+
declare const _default: {
|
|
72
|
+
appendUrlParams: typeof appendUrlParams;
|
|
73
|
+
parseUrlParams: typeof parseUrlParams;
|
|
74
|
+
stripUrlParams: typeof stripUrlParams;
|
|
75
|
+
buildUrl: typeof buildUrl;
|
|
76
|
+
isSecureUrl: typeof isSecureUrl;
|
|
77
|
+
httpToWs: typeof httpToWs;
|
|
78
|
+
wsToHttp: typeof wsToHttp;
|
|
79
|
+
matchPageProtocol: typeof matchPageProtocol;
|
|
80
|
+
};
|
|
81
|
+
export default _default;
|