@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,102 @@
|
|
|
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
|
+
export interface LiveDurationProxyOptions {
|
|
12
|
+
/** Whether to constrain seeking to buffered range (default: true) */
|
|
13
|
+
constrainSeek?: boolean;
|
|
14
|
+
/** Live offset from buffer end in seconds (default: 0) */
|
|
15
|
+
liveOffset?: number;
|
|
16
|
+
/** Callback when duration changes */
|
|
17
|
+
onDurationChange?: (duration: number) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface LiveDurationState {
|
|
20
|
+
/** Calculated duration */
|
|
21
|
+
duration: number;
|
|
22
|
+
/** Whether stream is live */
|
|
23
|
+
isLive: boolean;
|
|
24
|
+
/** Buffer end position */
|
|
25
|
+
bufferEnd: number;
|
|
26
|
+
/** Time since last progress */
|
|
27
|
+
elapsed: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a proxy wrapper around a video element that provides meaningful
|
|
31
|
+
* duration values for live streams.
|
|
32
|
+
*/
|
|
33
|
+
export declare class LiveDurationProxy {
|
|
34
|
+
private video;
|
|
35
|
+
private options;
|
|
36
|
+
private lastProgressTime;
|
|
37
|
+
private lastBufferEnd;
|
|
38
|
+
private listeners;
|
|
39
|
+
private _calculatedDuration;
|
|
40
|
+
constructor(video: HTMLVideoElement, options?: LiveDurationProxyOptions);
|
|
41
|
+
/**
|
|
42
|
+
* Check if the stream is live
|
|
43
|
+
*/
|
|
44
|
+
isLive(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get the calculated duration
|
|
47
|
+
* For live: bufferEnd + elapsedSinceLastProgress
|
|
48
|
+
* For VOD: native duration
|
|
49
|
+
*/
|
|
50
|
+
getDuration(): number;
|
|
51
|
+
/**
|
|
52
|
+
* Get the current buffer end position
|
|
53
|
+
*/
|
|
54
|
+
getBufferEnd(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Get the live edge position (where live is)
|
|
57
|
+
*/
|
|
58
|
+
getLiveEdge(): number;
|
|
59
|
+
/**
|
|
60
|
+
* Get the current latency (distance from live edge)
|
|
61
|
+
*/
|
|
62
|
+
getLatency(): number;
|
|
63
|
+
/**
|
|
64
|
+
* Seek to a position, respecting live constraints
|
|
65
|
+
*/
|
|
66
|
+
seek(time: number): void;
|
|
67
|
+
/**
|
|
68
|
+
* Jump to live edge
|
|
69
|
+
*/
|
|
70
|
+
jumpToLive(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Check if currently at live edge (within threshold)
|
|
73
|
+
*/
|
|
74
|
+
isAtLiveEdge(threshold?: number): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Get current state
|
|
77
|
+
*/
|
|
78
|
+
getState(): LiveDurationState;
|
|
79
|
+
/**
|
|
80
|
+
* Update the calculated duration
|
|
81
|
+
*/
|
|
82
|
+
private updateDuration;
|
|
83
|
+
/**
|
|
84
|
+
* Setup event listeners for tracking
|
|
85
|
+
*/
|
|
86
|
+
private setupListeners;
|
|
87
|
+
/**
|
|
88
|
+
* Cleanup
|
|
89
|
+
*/
|
|
90
|
+
destroy(): void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create a Proxy wrapper for a video element that intercepts duration/currentTime
|
|
94
|
+
* This allows existing code to work transparently with live streams.
|
|
95
|
+
*
|
|
96
|
+
* Note: This is an advanced feature - for most cases, use LiveDurationProxy directly.
|
|
97
|
+
*/
|
|
98
|
+
export declare function createLiveVideoProxy(video: HTMLVideoElement, options?: LiveDurationProxyOptions): {
|
|
99
|
+
proxy: HTMLVideoElement;
|
|
100
|
+
controller: LiveDurationProxy;
|
|
101
|
+
};
|
|
102
|
+
export default LiveDurationProxy;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import type { MetaTrackEvent } from '../types';
|
|
2
|
+
export interface MetaTrackSubscription {
|
|
3
|
+
trackId: string;
|
|
4
|
+
callback: (event: MetaTrackEvent) => void;
|
|
5
|
+
}
|
|
6
|
+
export interface MetaTrackManagerConfig {
|
|
7
|
+
/** MistServer base URL */
|
|
8
|
+
mistBaseUrl: string;
|
|
9
|
+
/** Stream name */
|
|
10
|
+
streamName: string;
|
|
11
|
+
/** Initial subscriptions */
|
|
12
|
+
subscriptions?: MetaTrackSubscription[];
|
|
13
|
+
/** Debug logging */
|
|
14
|
+
debug?: boolean;
|
|
15
|
+
/** Buffer ahead duration in seconds (default: 5) */
|
|
16
|
+
bufferAhead?: number;
|
|
17
|
+
/** Max age for messages in seconds before filtering (default: 5) */
|
|
18
|
+
maxMessageAge?: number;
|
|
19
|
+
/** Fast-forward interval in seconds for catching up (default: 5) */
|
|
20
|
+
fastForwardInterval?: number;
|
|
21
|
+
}
|
|
22
|
+
type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
|
|
23
|
+
/**
|
|
24
|
+
* MetaTrackManager - Handles real-time metadata subscriptions via MistServer WebSocket
|
|
25
|
+
*
|
|
26
|
+
* Uses native MistServer WebSocket protocol (from embed/player.js):
|
|
27
|
+
* - Connect: ws://{baseUrl}/json_{streamName}.js?rate=1
|
|
28
|
+
* - Set tracks: {type:"tracks", meta:"1,2,3"} (comma-separated indices)
|
|
29
|
+
* - Seek: {type:"seek", seek_time:<ms>, ff_to:<ms>}
|
|
30
|
+
* - Receive: {time:<ms>, track:<index>, data:{...}}
|
|
31
|
+
* - Control: {type:"hold"}, {type:"play"}, {type:"fast_forward", ff_to:<ms>}
|
|
32
|
+
*
|
|
33
|
+
* Features:
|
|
34
|
+
* - Automatic reconnection with exponential backoff
|
|
35
|
+
* - Message buffering during reconnection
|
|
36
|
+
* - Type detection for subtitle/score/event/chapter data
|
|
37
|
+
* - Stay-ahead buffering for smooth playback
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* const manager = new MetaTrackManager({
|
|
42
|
+
* mistBaseUrl: 'https://mist.example.com',
|
|
43
|
+
* streamName: 'my-stream',
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* manager.subscribe('1', (event) => {
|
|
47
|
+
* if (event.type === 'subtitle') {
|
|
48
|
+
* console.log('Subtitle:', event.data);
|
|
49
|
+
* }
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* manager.connect();
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare class MetaTrackManager {
|
|
56
|
+
private config;
|
|
57
|
+
private ws;
|
|
58
|
+
private state;
|
|
59
|
+
private subscriptions;
|
|
60
|
+
private pendingSubscriptions;
|
|
61
|
+
private reconnectAttempt;
|
|
62
|
+
private timers;
|
|
63
|
+
private messageBuffer;
|
|
64
|
+
private debug;
|
|
65
|
+
private connectionId;
|
|
66
|
+
private static readonly CONNECTION_DEBOUNCE_MS;
|
|
67
|
+
private static readonly MAX_RECONNECT_ATTEMPTS;
|
|
68
|
+
private static readonly INITIAL_RECONNECT_DELAY;
|
|
69
|
+
private static readonly MAX_RECONNECT_DELAY;
|
|
70
|
+
private static readonly MESSAGE_BUFFER_SIZE;
|
|
71
|
+
private currentPlaybackTime;
|
|
72
|
+
private bufferAhead;
|
|
73
|
+
private maxMessageAge;
|
|
74
|
+
private fastForwardInterval;
|
|
75
|
+
private lastFastForwardTime;
|
|
76
|
+
private timedEventBuffer;
|
|
77
|
+
constructor(config: MetaTrackManagerConfig);
|
|
78
|
+
/**
|
|
79
|
+
* Connect to MistServer WebSocket
|
|
80
|
+
* Debounced to prevent orphaned connections during rapid mount/unmount cycles.
|
|
81
|
+
*/
|
|
82
|
+
connect(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Internal method to create WebSocket after debounce
|
|
85
|
+
*/
|
|
86
|
+
private createWebSocket;
|
|
87
|
+
/**
|
|
88
|
+
* Disconnect from MistServer
|
|
89
|
+
*/
|
|
90
|
+
disconnect(): void;
|
|
91
|
+
/**
|
|
92
|
+
* Subscribe to a meta track
|
|
93
|
+
* @param trackId Track index (number as string) or "all" for all meta tracks
|
|
94
|
+
*/
|
|
95
|
+
subscribe(trackId: string, callback: (event: MetaTrackEvent) => void): () => void;
|
|
96
|
+
/**
|
|
97
|
+
* Unsubscribe from a meta track
|
|
98
|
+
*/
|
|
99
|
+
unsubscribe(trackId: string, callback: (event: MetaTrackEvent) => void): void;
|
|
100
|
+
/**
|
|
101
|
+
* Get list of subscribed track IDs
|
|
102
|
+
*/
|
|
103
|
+
getSubscribedTracks(): string[];
|
|
104
|
+
/**
|
|
105
|
+
* Get connection state
|
|
106
|
+
*/
|
|
107
|
+
getState(): ConnectionState;
|
|
108
|
+
/**
|
|
109
|
+
* Check if connected
|
|
110
|
+
*/
|
|
111
|
+
isConnected(): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Update current playback time
|
|
114
|
+
* Call this on video timeupdate events to keep buffer in sync
|
|
115
|
+
*/
|
|
116
|
+
setPlaybackTime(timeInSeconds: number): void;
|
|
117
|
+
/**
|
|
118
|
+
* Get current playback time
|
|
119
|
+
*/
|
|
120
|
+
getPlaybackTime(): number;
|
|
121
|
+
/**
|
|
122
|
+
* Handle seek event - clears buffer and sends seek command to MistServer
|
|
123
|
+
* Call this when video seeks to a new position
|
|
124
|
+
*/
|
|
125
|
+
onSeek(newTimeInSeconds: number): void;
|
|
126
|
+
/**
|
|
127
|
+
* Process buffered events up to current playback time
|
|
128
|
+
* Dispatches events that are ready to be shown
|
|
129
|
+
*/
|
|
130
|
+
private processTimedEvents;
|
|
131
|
+
/**
|
|
132
|
+
* Add event to timed buffer (sorted by timestamp)
|
|
133
|
+
* Used for events that should be dispatched at specific playback times
|
|
134
|
+
*/
|
|
135
|
+
private addToTimedBuffer;
|
|
136
|
+
/**
|
|
137
|
+
* Check if we need to request more data (stay bufferAhead seconds ahead)
|
|
138
|
+
* Returns true if buffer is running low
|
|
139
|
+
*/
|
|
140
|
+
needsMoreData(trackId: string): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Fast-forward through buffered events (rate-limited)
|
|
143
|
+
* Used when playback jumps ahead and needs to catch up
|
|
144
|
+
* Also notifies MistServer to fast-forward its metadata stream
|
|
145
|
+
*/
|
|
146
|
+
fastForward(): void;
|
|
147
|
+
/**
|
|
148
|
+
* Get buffer status for debugging
|
|
149
|
+
*/
|
|
150
|
+
getBufferStatus(): Record<string, {
|
|
151
|
+
count: number;
|
|
152
|
+
oldestMs: number;
|
|
153
|
+
newestMs: number;
|
|
154
|
+
}>;
|
|
155
|
+
/**
|
|
156
|
+
* Build WebSocket URL for MistServer meta track subscription
|
|
157
|
+
* Uses the same endpoint as JSON info polling, just over WebSocket
|
|
158
|
+
*/
|
|
159
|
+
private buildWsUrl;
|
|
160
|
+
/**
|
|
161
|
+
* Send tracks update to MistServer
|
|
162
|
+
* MistServer protocol: {type:"tracks", meta:"1,2,3"} (comma-separated track indices)
|
|
163
|
+
*/
|
|
164
|
+
private sendTracksUpdate;
|
|
165
|
+
/**
|
|
166
|
+
* Send seek command to MistServer
|
|
167
|
+
* MistServer protocol: {type:"seek", seek_time:<ms>, ff_to:<ms>}
|
|
168
|
+
*/
|
|
169
|
+
private sendSeek;
|
|
170
|
+
/**
|
|
171
|
+
* Send hold command (pause metadata delivery)
|
|
172
|
+
*/
|
|
173
|
+
private sendHold;
|
|
174
|
+
/**
|
|
175
|
+
* Send play command (resume metadata delivery)
|
|
176
|
+
*/
|
|
177
|
+
private sendPlay;
|
|
178
|
+
/**
|
|
179
|
+
* Send fast-forward command
|
|
180
|
+
*/
|
|
181
|
+
private sendFastForward;
|
|
182
|
+
/**
|
|
183
|
+
* Handle incoming WebSocket message
|
|
184
|
+
* MistServer format:
|
|
185
|
+
* - Metadata: {time:<ms>, track:<index>, data:{...}}
|
|
186
|
+
* - Status: {type:"on_time", data:{current:<ms>}}
|
|
187
|
+
* - Seek complete: {type:"seek", ...}
|
|
188
|
+
*/
|
|
189
|
+
private handleMessage;
|
|
190
|
+
/**
|
|
191
|
+
* Parse meta track event from MistServer message
|
|
192
|
+
* MistServer format: {time:<ms>, track:<index>, data:{...}}
|
|
193
|
+
*/
|
|
194
|
+
private parseMetaTrackEvent;
|
|
195
|
+
/**
|
|
196
|
+
* Detect event type from data shape
|
|
197
|
+
*/
|
|
198
|
+
private detectEventType;
|
|
199
|
+
/**
|
|
200
|
+
* Dispatch event to subscribers
|
|
201
|
+
*/
|
|
202
|
+
private dispatchEvent;
|
|
203
|
+
/**
|
|
204
|
+
* Schedule reconnection attempt
|
|
205
|
+
*/
|
|
206
|
+
private scheduleReconnect;
|
|
207
|
+
/**
|
|
208
|
+
* Buffer message for later delivery
|
|
209
|
+
*/
|
|
210
|
+
private bufferMessage;
|
|
211
|
+
/**
|
|
212
|
+
* Flush buffered messages to subscribers
|
|
213
|
+
*/
|
|
214
|
+
private flushMessageBuffer;
|
|
215
|
+
/**
|
|
216
|
+
* Debug logging
|
|
217
|
+
*/
|
|
218
|
+
private log;
|
|
219
|
+
}
|
|
220
|
+
export default MetaTrackManager;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MistReporter - Reports playback stats to MistServer
|
|
3
|
+
*
|
|
4
|
+
* Implements the same reporting protocol as MistPlayer reference:
|
|
5
|
+
* - Sends initial report on player selection (player, sourceType, sourceUrl, pageUrl)
|
|
6
|
+
* - Reports deltas every 5 seconds
|
|
7
|
+
* - Tracks waiting/stalled events and durations
|
|
8
|
+
* - Integrates with QualityMonitor for playbackScore
|
|
9
|
+
* - Sends final report on unload
|
|
10
|
+
*
|
|
11
|
+
* Reports are sent over the same WebSocket used for stream state.
|
|
12
|
+
*/
|
|
13
|
+
export interface MistReporterStats {
|
|
14
|
+
nWaiting: number;
|
|
15
|
+
timeWaiting: number;
|
|
16
|
+
nStalled: number;
|
|
17
|
+
timeStalled: number;
|
|
18
|
+
timeUnpaused: number;
|
|
19
|
+
nError: number;
|
|
20
|
+
lastError: string | null;
|
|
21
|
+
firstPlayback: number | null;
|
|
22
|
+
playbackScore: number;
|
|
23
|
+
autoplay: 'success' | 'muted' | 'failed' | null;
|
|
24
|
+
videoHeight: number | null;
|
|
25
|
+
videoWidth: number | null;
|
|
26
|
+
playerHeight: number | null;
|
|
27
|
+
playerWidth: number | null;
|
|
28
|
+
tracks: string | null;
|
|
29
|
+
nLog: number;
|
|
30
|
+
}
|
|
31
|
+
export interface MistReporterInitialReport {
|
|
32
|
+
player: string;
|
|
33
|
+
sourceType: string;
|
|
34
|
+
sourceUrl: string;
|
|
35
|
+
pageUrl: string;
|
|
36
|
+
}
|
|
37
|
+
export interface MistReporterOptions {
|
|
38
|
+
/** WebSocket to send reports through (shared with stream state) */
|
|
39
|
+
socket?: WebSocket | null;
|
|
40
|
+
/** Report interval in ms (default: 5000) */
|
|
41
|
+
reportInterval?: number;
|
|
42
|
+
/** E2: Batch flush interval in ms (default: 1000) - max rate for non-critical reports */
|
|
43
|
+
batchFlushInterval?: number;
|
|
44
|
+
/** Boot timestamp for firstPlayback calculation */
|
|
45
|
+
bootMs?: number;
|
|
46
|
+
/** Log array reference for including logs in reports */
|
|
47
|
+
logs?: string[];
|
|
48
|
+
}
|
|
49
|
+
type StatsKey = keyof MistReporterStats;
|
|
50
|
+
/**
|
|
51
|
+
* MistReporter - Playback telemetry to MistServer
|
|
52
|
+
*/
|
|
53
|
+
export declare class MistReporter {
|
|
54
|
+
private socket;
|
|
55
|
+
private videoElement;
|
|
56
|
+
private containerElement;
|
|
57
|
+
private reportInterval;
|
|
58
|
+
private batchFlushInterval;
|
|
59
|
+
private bootMs;
|
|
60
|
+
private logs;
|
|
61
|
+
private _stats;
|
|
62
|
+
private waitingSince;
|
|
63
|
+
private stalledSince;
|
|
64
|
+
private unpausedSince;
|
|
65
|
+
private timeWaitingAccum;
|
|
66
|
+
private timeStalledAccum;
|
|
67
|
+
private timeUnpausedAccum;
|
|
68
|
+
private lastReported;
|
|
69
|
+
private timers;
|
|
70
|
+
private listeners;
|
|
71
|
+
private firstPlaybackRecorded;
|
|
72
|
+
private pendingBatch;
|
|
73
|
+
private hasPendingBatch;
|
|
74
|
+
private lastFlushTime;
|
|
75
|
+
private batchFlushTimerId;
|
|
76
|
+
private offlineQueue;
|
|
77
|
+
private static readonly MAX_OFFLINE_QUEUE_SIZE;
|
|
78
|
+
constructor(options?: MistReporterOptions);
|
|
79
|
+
/**
|
|
80
|
+
* Set the WebSocket to use for reporting
|
|
81
|
+
* E3: Flushes offline queue when socket becomes available
|
|
82
|
+
*/
|
|
83
|
+
setSocket(socket: WebSocket | null): void;
|
|
84
|
+
/**
|
|
85
|
+
* E3: Flush queued reports that were collected while offline
|
|
86
|
+
*/
|
|
87
|
+
private flushOfflineQueue;
|
|
88
|
+
/**
|
|
89
|
+
* Get current stats object with computed getters
|
|
90
|
+
* E1: Uses performance.now() for sub-millisecond precision in duration tracking
|
|
91
|
+
*/
|
|
92
|
+
getStats(): MistReporterStats;
|
|
93
|
+
/**
|
|
94
|
+
* Set a stat value
|
|
95
|
+
*/
|
|
96
|
+
set<K extends StatsKey>(key: K, value: MistReporterStats[K]): void;
|
|
97
|
+
/**
|
|
98
|
+
* Increment a counter stat
|
|
99
|
+
*/
|
|
100
|
+
add(key: 'nWaiting' | 'nStalled' | 'nError', amount?: number): void;
|
|
101
|
+
/**
|
|
102
|
+
* Initialize reporting for a video element
|
|
103
|
+
*/
|
|
104
|
+
init(videoElement: HTMLVideoElement, containerElement?: HTMLElement): void;
|
|
105
|
+
/**
|
|
106
|
+
* Send initial report when player is selected
|
|
107
|
+
*/
|
|
108
|
+
sendInitialReport(info: MistReporterInitialReport): void;
|
|
109
|
+
/**
|
|
110
|
+
* Update playback score (call from QualityMonitor)
|
|
111
|
+
*/
|
|
112
|
+
setPlaybackScore(score: number): void;
|
|
113
|
+
/**
|
|
114
|
+
* Update autoplay status
|
|
115
|
+
*/
|
|
116
|
+
setAutoplayStatus(status: 'success' | 'muted' | 'failed'): void;
|
|
117
|
+
/**
|
|
118
|
+
* Update current tracks
|
|
119
|
+
*/
|
|
120
|
+
setTracks(tracks: string[]): void;
|
|
121
|
+
/**
|
|
122
|
+
* Send a report over WebSocket immediately
|
|
123
|
+
* E3: Queues reports when socket is unavailable (up to MAX_OFFLINE_QUEUE_SIZE)
|
|
124
|
+
*/
|
|
125
|
+
private sendReport;
|
|
126
|
+
/**
|
|
127
|
+
* E2: Queue data for batched reporting
|
|
128
|
+
* Merges with pending batch, schedules flush if not already pending
|
|
129
|
+
*/
|
|
130
|
+
private report;
|
|
131
|
+
/**
|
|
132
|
+
* E2: Flush pending batch immediately
|
|
133
|
+
* Used for critical events (error, first play, unload)
|
|
134
|
+
*/
|
|
135
|
+
flushBatch(): void;
|
|
136
|
+
/**
|
|
137
|
+
* Report stats delta (only changed values)
|
|
138
|
+
* E2: Now queues to batch instead of sending immediately
|
|
139
|
+
*/
|
|
140
|
+
reportStats(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Start periodic reporting
|
|
143
|
+
*/
|
|
144
|
+
private startReporting;
|
|
145
|
+
/**
|
|
146
|
+
* Schedule the next report
|
|
147
|
+
*/
|
|
148
|
+
private scheduleNextReport;
|
|
149
|
+
/**
|
|
150
|
+
* Send final report and cleanup
|
|
151
|
+
* E2: Flushes immediately since this is a critical event
|
|
152
|
+
*/
|
|
153
|
+
sendFinalReport(reason?: string): void;
|
|
154
|
+
/**
|
|
155
|
+
* Stop reporting and cleanup
|
|
156
|
+
*/
|
|
157
|
+
destroy(): void;
|
|
158
|
+
/**
|
|
159
|
+
* Add a log entry
|
|
160
|
+
*/
|
|
161
|
+
log(message: string): void;
|
|
162
|
+
}
|
|
163
|
+
export default MistReporter;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MistSignaling - WebSocket signaling for MistServer's native WebRTC protocol
|
|
3
|
+
*
|
|
4
|
+
* Protocol messages (from MistServer):
|
|
5
|
+
* - on_connected: WebSocket opened successfully
|
|
6
|
+
* - on_disconnected: WebSocket closed
|
|
7
|
+
* - on_answer_sdp: SDP answer received, { result: boolean, answer_sdp: string }
|
|
8
|
+
* - on_time: Time update { current: ms, end: ms, begin: ms, tracks: string[] }
|
|
9
|
+
* - on_stop: Stream ended
|
|
10
|
+
* - on_error: Error occurred { message: string }
|
|
11
|
+
*
|
|
12
|
+
* Protocol messages (to MistServer):
|
|
13
|
+
* - offer_sdp: SDP offer { offer_sdp: string }
|
|
14
|
+
* - seek: Seek to position { seek_time: number | "live" }
|
|
15
|
+
* - hold: Pause playback
|
|
16
|
+
* - stop: Stop playback
|
|
17
|
+
* - tracks: Select tracks { video: string, audio: string }
|
|
18
|
+
* - set_speed: Set playback rate { play_rate: number | "auto" }
|
|
19
|
+
*/
|
|
20
|
+
import { TypedEventEmitter } from './EventEmitter';
|
|
21
|
+
export interface MistSignalingConfig {
|
|
22
|
+
/** WebSocket URL (will convert http to ws) */
|
|
23
|
+
url: string;
|
|
24
|
+
/** Connection timeout in ms (default: 5000) */
|
|
25
|
+
timeout?: number;
|
|
26
|
+
/** Callback for debug logging */
|
|
27
|
+
onLog?: (message: string) => void;
|
|
28
|
+
}
|
|
29
|
+
export interface MistTimeUpdate {
|
|
30
|
+
/** Current playback position in ms */
|
|
31
|
+
current: number;
|
|
32
|
+
/** End position in ms (0 for live) */
|
|
33
|
+
end: number;
|
|
34
|
+
/** Begin position in ms (buffer start) */
|
|
35
|
+
begin: number;
|
|
36
|
+
/** Currently active track IDs */
|
|
37
|
+
tracks?: string[];
|
|
38
|
+
/** Whether playback is paused */
|
|
39
|
+
paused?: boolean;
|
|
40
|
+
/** Whether at live point */
|
|
41
|
+
live_point?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface MistSignalingEvents {
|
|
44
|
+
/** Connection established */
|
|
45
|
+
'connected': void;
|
|
46
|
+
/** Connection closed */
|
|
47
|
+
'disconnected': {
|
|
48
|
+
code: number;
|
|
49
|
+
};
|
|
50
|
+
/** SDP answer received */
|
|
51
|
+
'answer_sdp': {
|
|
52
|
+
result: boolean;
|
|
53
|
+
answer_sdp: string;
|
|
54
|
+
};
|
|
55
|
+
/** Time/track update */
|
|
56
|
+
'time_update': MistTimeUpdate;
|
|
57
|
+
/** Seek completed */
|
|
58
|
+
'seeked': {
|
|
59
|
+
live_point?: boolean;
|
|
60
|
+
};
|
|
61
|
+
/** Playback speed changed */
|
|
62
|
+
'speed_changed': {
|
|
63
|
+
play_rate: number;
|
|
64
|
+
play_rate_curr: number;
|
|
65
|
+
};
|
|
66
|
+
/** Stream ended */
|
|
67
|
+
'stopped': void;
|
|
68
|
+
/** Error occurred */
|
|
69
|
+
'error': {
|
|
70
|
+
message: string;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export type MistSignalingState = 'connecting' | 'connected' | 'disconnected' | 'closed';
|
|
74
|
+
/**
|
|
75
|
+
* MistSignaling handles WebSocket communication with MistServer for WebRTC
|
|
76
|
+
*/
|
|
77
|
+
export declare class MistSignaling extends TypedEventEmitter<MistSignalingEvents> {
|
|
78
|
+
private ws;
|
|
79
|
+
private url;
|
|
80
|
+
private timeout;
|
|
81
|
+
private timeoutId;
|
|
82
|
+
private onLog;
|
|
83
|
+
private _state;
|
|
84
|
+
seekPromise: {
|
|
85
|
+
resolve: (msg: string) => void;
|
|
86
|
+
reject: (msg: string) => void;
|
|
87
|
+
} | null;
|
|
88
|
+
constructor(config: MistSignalingConfig);
|
|
89
|
+
/**
|
|
90
|
+
* Get current connection state
|
|
91
|
+
*/
|
|
92
|
+
get state(): MistSignalingState;
|
|
93
|
+
/**
|
|
94
|
+
* Check if connected
|
|
95
|
+
*/
|
|
96
|
+
get isConnected(): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Connect to MistServer WebSocket
|
|
99
|
+
*/
|
|
100
|
+
connect(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Handle incoming message from MistServer
|
|
103
|
+
*/
|
|
104
|
+
private handleMessage;
|
|
105
|
+
/**
|
|
106
|
+
* Send a message to MistServer
|
|
107
|
+
*/
|
|
108
|
+
send(cmd: Record<string, unknown>): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Send SDP offer to MistServer
|
|
111
|
+
*/
|
|
112
|
+
sendOfferSDP(sdp: string): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Seek to position (in seconds or "live")
|
|
115
|
+
*/
|
|
116
|
+
seek(time: number | 'live'): Promise<string>;
|
|
117
|
+
/**
|
|
118
|
+
* Pause playback (hold)
|
|
119
|
+
*/
|
|
120
|
+
pause(): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Stop playback
|
|
123
|
+
*/
|
|
124
|
+
stop(): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Set track selection
|
|
127
|
+
* @param video - Video track selection (e.g., "~1080x720", "|500000", "none")
|
|
128
|
+
* @param audio - Audio track selection (e.g., "eng", "none")
|
|
129
|
+
*/
|
|
130
|
+
setTracks(options: {
|
|
131
|
+
video?: string;
|
|
132
|
+
audio?: string;
|
|
133
|
+
}): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Set playback speed
|
|
136
|
+
* @param rate - Playback rate (1.0 normal, "auto" for live catch-up)
|
|
137
|
+
*/
|
|
138
|
+
setSpeed(rate: number | 'auto'): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Close the connection
|
|
141
|
+
*/
|
|
142
|
+
close(): void;
|
|
143
|
+
/**
|
|
144
|
+
* Destroy and cleanup
|
|
145
|
+
*/
|
|
146
|
+
destroy(): void;
|
|
147
|
+
}
|
|
148
|
+
export default MistSignaling;
|