@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.
Files changed (120) hide show
  1. package/dist/cjs/index.js +19493 -0
  2. package/dist/cjs/index.js.map +1 -0
  3. package/dist/esm/index.js +19398 -0
  4. package/dist/esm/index.js.map +1 -0
  5. package/dist/player.css +2140 -0
  6. package/dist/types/core/ABRController.d.ts +164 -0
  7. package/dist/types/core/CodecUtils.d.ts +54 -0
  8. package/dist/types/core/Disposable.d.ts +61 -0
  9. package/dist/types/core/EventEmitter.d.ts +73 -0
  10. package/dist/types/core/GatewayClient.d.ts +144 -0
  11. package/dist/types/core/InteractionController.d.ts +121 -0
  12. package/dist/types/core/LiveDurationProxy.d.ts +102 -0
  13. package/dist/types/core/MetaTrackManager.d.ts +220 -0
  14. package/dist/types/core/MistReporter.d.ts +163 -0
  15. package/dist/types/core/MistSignaling.d.ts +148 -0
  16. package/dist/types/core/PlayerController.d.ts +665 -0
  17. package/dist/types/core/PlayerInterface.d.ts +230 -0
  18. package/dist/types/core/PlayerManager.d.ts +182 -0
  19. package/dist/types/core/PlayerRegistry.d.ts +27 -0
  20. package/dist/types/core/QualityMonitor.d.ts +184 -0
  21. package/dist/types/core/ScreenWakeLockManager.d.ts +70 -0
  22. package/dist/types/core/SeekingUtils.d.ts +142 -0
  23. package/dist/types/core/StreamStateClient.d.ts +108 -0
  24. package/dist/types/core/SubtitleManager.d.ts +111 -0
  25. package/dist/types/core/TelemetryReporter.d.ts +79 -0
  26. package/dist/types/core/TimeFormat.d.ts +97 -0
  27. package/dist/types/core/TimerManager.d.ts +83 -0
  28. package/dist/types/core/UrlUtils.d.ts +81 -0
  29. package/dist/types/core/detector.d.ts +149 -0
  30. package/dist/types/core/index.d.ts +49 -0
  31. package/dist/types/core/scorer.d.ts +167 -0
  32. package/dist/types/core/selector.d.ts +9 -0
  33. package/dist/types/index.d.ts +45 -0
  34. package/dist/types/lib/utils.d.ts +2 -0
  35. package/dist/types/players/DashJsPlayer.d.ts +102 -0
  36. package/dist/types/players/HlsJsPlayer.d.ts +70 -0
  37. package/dist/types/players/MewsWsPlayer/SourceBufferManager.d.ts +119 -0
  38. package/dist/types/players/MewsWsPlayer/WebSocketManager.d.ts +60 -0
  39. package/dist/types/players/MewsWsPlayer/index.d.ts +220 -0
  40. package/dist/types/players/MewsWsPlayer/types.d.ts +89 -0
  41. package/dist/types/players/MistPlayer.d.ts +25 -0
  42. package/dist/types/players/MistWebRTCPlayer/index.d.ts +133 -0
  43. package/dist/types/players/NativePlayer.d.ts +143 -0
  44. package/dist/types/players/VideoJsPlayer.d.ts +59 -0
  45. package/dist/types/players/WebCodecsPlayer/JitterBuffer.d.ts +118 -0
  46. package/dist/types/players/WebCodecsPlayer/LatencyProfiles.d.ts +64 -0
  47. package/dist/types/players/WebCodecsPlayer/RawChunkParser.d.ts +63 -0
  48. package/dist/types/players/WebCodecsPlayer/SyncController.d.ts +174 -0
  49. package/dist/types/players/WebCodecsPlayer/WebSocketController.d.ts +164 -0
  50. package/dist/types/players/WebCodecsPlayer/index.d.ts +149 -0
  51. package/dist/types/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.d.ts +105 -0
  52. package/dist/types/players/WebCodecsPlayer/types.d.ts +395 -0
  53. package/dist/types/players/WebCodecsPlayer/worker/decoder.worker.d.ts +13 -0
  54. package/dist/types/players/WebCodecsPlayer/worker/types.d.ts +197 -0
  55. package/dist/types/players/index.d.ts +14 -0
  56. package/dist/types/styles/index.d.ts +11 -0
  57. package/dist/types/types.d.ts +363 -0
  58. package/dist/types/vanilla/FrameWorksPlayer.d.ts +143 -0
  59. package/dist/types/vanilla/index.d.ts +19 -0
  60. package/dist/workers/decoder.worker.js +989 -0
  61. package/dist/workers/decoder.worker.js.map +1 -0
  62. package/package.json +80 -0
  63. package/src/core/ABRController.ts +550 -0
  64. package/src/core/CodecUtils.ts +257 -0
  65. package/src/core/Disposable.ts +120 -0
  66. package/src/core/EventEmitter.ts +113 -0
  67. package/src/core/GatewayClient.ts +439 -0
  68. package/src/core/InteractionController.ts +712 -0
  69. package/src/core/LiveDurationProxy.ts +270 -0
  70. package/src/core/MetaTrackManager.ts +753 -0
  71. package/src/core/MistReporter.ts +543 -0
  72. package/src/core/MistSignaling.ts +346 -0
  73. package/src/core/PlayerController.ts +2829 -0
  74. package/src/core/PlayerInterface.ts +432 -0
  75. package/src/core/PlayerManager.ts +900 -0
  76. package/src/core/PlayerRegistry.ts +149 -0
  77. package/src/core/QualityMonitor.ts +597 -0
  78. package/src/core/ScreenWakeLockManager.ts +163 -0
  79. package/src/core/SeekingUtils.ts +364 -0
  80. package/src/core/StreamStateClient.ts +457 -0
  81. package/src/core/SubtitleManager.ts +297 -0
  82. package/src/core/TelemetryReporter.ts +308 -0
  83. package/src/core/TimeFormat.ts +205 -0
  84. package/src/core/TimerManager.ts +209 -0
  85. package/src/core/UrlUtils.ts +179 -0
  86. package/src/core/detector.ts +382 -0
  87. package/src/core/index.ts +140 -0
  88. package/src/core/scorer.ts +553 -0
  89. package/src/core/selector.ts +16 -0
  90. package/src/global.d.ts +11 -0
  91. package/src/index.ts +75 -0
  92. package/src/lib/utils.ts +6 -0
  93. package/src/players/DashJsPlayer.ts +642 -0
  94. package/src/players/HlsJsPlayer.ts +483 -0
  95. package/src/players/MewsWsPlayer/SourceBufferManager.ts +572 -0
  96. package/src/players/MewsWsPlayer/WebSocketManager.ts +241 -0
  97. package/src/players/MewsWsPlayer/index.ts +1065 -0
  98. package/src/players/MewsWsPlayer/types.ts +106 -0
  99. package/src/players/MistPlayer.ts +188 -0
  100. package/src/players/MistWebRTCPlayer/index.ts +703 -0
  101. package/src/players/NativePlayer.ts +820 -0
  102. package/src/players/VideoJsPlayer.ts +643 -0
  103. package/src/players/WebCodecsPlayer/JitterBuffer.ts +299 -0
  104. package/src/players/WebCodecsPlayer/LatencyProfiles.ts +151 -0
  105. package/src/players/WebCodecsPlayer/RawChunkParser.ts +151 -0
  106. package/src/players/WebCodecsPlayer/SyncController.ts +456 -0
  107. package/src/players/WebCodecsPlayer/WebSocketController.ts +564 -0
  108. package/src/players/WebCodecsPlayer/index.ts +1650 -0
  109. package/src/players/WebCodecsPlayer/polyfills/MediaStreamTrackGenerator.ts +379 -0
  110. package/src/players/WebCodecsPlayer/types.ts +542 -0
  111. package/src/players/WebCodecsPlayer/worker/decoder.worker.ts +1360 -0
  112. package/src/players/WebCodecsPlayer/worker/types.ts +276 -0
  113. package/src/players/index.ts +22 -0
  114. package/src/styles/animations.css +21 -0
  115. package/src/styles/index.ts +52 -0
  116. package/src/styles/player.css +2126 -0
  117. package/src/styles/tailwind.css +1015 -0
  118. package/src/types.ts +421 -0
  119. package/src/vanilla/FrameWorksPlayer.ts +367 -0
  120. package/src/vanilla/index.ts +22 -0
@@ -0,0 +1,346 @@
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
+
21
+ import { TypedEventEmitter } from './EventEmitter';
22
+
23
+ export interface MistSignalingConfig {
24
+ /** WebSocket URL (will convert http to ws) */
25
+ url: string;
26
+ /** Connection timeout in ms (default: 5000) */
27
+ timeout?: number;
28
+ /** Callback for debug logging */
29
+ onLog?: (message: string) => void;
30
+ }
31
+
32
+ export interface MistTimeUpdate {
33
+ /** Current playback position in ms */
34
+ current: number;
35
+ /** End position in ms (0 for live) */
36
+ end: number;
37
+ /** Begin position in ms (buffer start) */
38
+ begin: number;
39
+ /** Currently active track IDs */
40
+ tracks?: string[];
41
+ /** Whether playback is paused */
42
+ paused?: boolean;
43
+ /** Whether at live point */
44
+ live_point?: boolean;
45
+ }
46
+
47
+ export interface MistSignalingEvents {
48
+ /** Connection established */
49
+ 'connected': void;
50
+ /** Connection closed */
51
+ 'disconnected': { code: number };
52
+ /** SDP answer received */
53
+ 'answer_sdp': { result: boolean; answer_sdp: string };
54
+ /** Time/track update */
55
+ 'time_update': MistTimeUpdate;
56
+ /** Seek completed */
57
+ 'seeked': { live_point?: boolean };
58
+ /** Playback speed changed */
59
+ 'speed_changed': { play_rate: number; play_rate_curr: number };
60
+ /** Stream ended */
61
+ 'stopped': void;
62
+ /** Error occurred */
63
+ 'error': { message: string };
64
+ }
65
+
66
+ export type MistSignalingState = 'connecting' | 'connected' | 'disconnected' | 'closed';
67
+
68
+ /**
69
+ * MistSignaling handles WebSocket communication with MistServer for WebRTC
70
+ */
71
+ export class MistSignaling extends TypedEventEmitter<MistSignalingEvents> {
72
+ private ws: WebSocket | null = null;
73
+ private url: string;
74
+ private timeout: number;
75
+ private timeoutId: ReturnType<typeof setTimeout> | null = null;
76
+ private onLog: (message: string) => void;
77
+ private _state: MistSignalingState = 'disconnected';
78
+
79
+ // Promise for seek operation
80
+ public seekPromise: {
81
+ resolve: (msg: string) => void;
82
+ reject: (msg: string) => void;
83
+ } | null = null;
84
+
85
+ constructor(config: MistSignalingConfig) {
86
+ super();
87
+ // Convert http(s) to ws(s)
88
+ this.url = config.url.replace(/^http/, 'ws');
89
+ this.timeout = config.timeout ?? 5000;
90
+ this.onLog = config.onLog ?? (() => {});
91
+ }
92
+
93
+ /**
94
+ * Get current connection state
95
+ */
96
+ get state(): MistSignalingState {
97
+ return this._state;
98
+ }
99
+
100
+ /**
101
+ * Check if connected
102
+ */
103
+ get isConnected(): boolean {
104
+ return this._state === 'connected';
105
+ }
106
+
107
+ /**
108
+ * Connect to MistServer WebSocket
109
+ */
110
+ connect(): void {
111
+ if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
112
+ this.onLog('Already connected or connecting');
113
+ return;
114
+ }
115
+
116
+ this._state = 'connecting';
117
+ this.onLog(`Connecting to ${this.url}`);
118
+
119
+ try {
120
+ this.ws = new WebSocket(this.url);
121
+ } catch (e) {
122
+ this.onLog(`Failed to create WebSocket: ${e}`);
123
+ this._state = 'disconnected';
124
+ return;
125
+ }
126
+
127
+ // Connection timeout
128
+ this.timeoutId = setTimeout(() => {
129
+ if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {
130
+ this.onLog('WebSocket connection timeout');
131
+ this.ws.close();
132
+ this._state = 'disconnected';
133
+ this.emit('error', { message: 'Connection timeout' });
134
+ }
135
+ }, this.timeout);
136
+
137
+ this.ws.onopen = () => {
138
+ if (this.timeoutId) {
139
+ clearTimeout(this.timeoutId);
140
+ this.timeoutId = null;
141
+ }
142
+ this._state = 'connected';
143
+ this.onLog('WebSocket connected');
144
+ this.emit('connected', undefined);
145
+ };
146
+
147
+ this.ws.onmessage = (event) => {
148
+ try {
149
+ const cmd = JSON.parse(event.data);
150
+ this.handleMessage(cmd);
151
+ } catch (err) {
152
+ this.onLog(`Failed to parse message: ${err}`);
153
+ }
154
+ };
155
+
156
+ this.ws.onclose = (event) => {
157
+ if (this.timeoutId) {
158
+ clearTimeout(this.timeoutId);
159
+ this.timeoutId = null;
160
+ }
161
+ this._state = 'closed';
162
+ this.onLog(`WebSocket closed (code: ${event.code})`);
163
+ this.emit('disconnected', { code: event.code });
164
+ };
165
+
166
+ this.ws.onerror = (event) => {
167
+ this.onLog(`WebSocket error: ${event}`);
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Handle incoming message from MistServer
173
+ */
174
+ private handleMessage(cmd: Record<string, unknown>): void {
175
+ const type = cmd.type as string;
176
+
177
+ switch (type) {
178
+ case 'on_connected':
179
+ // Already handled by onopen
180
+ break;
181
+
182
+ case 'on_disconnected':
183
+ this._state = 'disconnected';
184
+ this.emit('disconnected', { code: (cmd.code as number) || 0 });
185
+ break;
186
+
187
+ case 'on_answer_sdp':
188
+ this.emit('answer_sdp', {
189
+ result: cmd.result as boolean,
190
+ answer_sdp: cmd.answer_sdp as string,
191
+ });
192
+ break;
193
+
194
+ case 'on_time':
195
+ this.emit('time_update', {
196
+ current: cmd.current as number,
197
+ end: cmd.end as number,
198
+ begin: cmd.begin as number,
199
+ tracks: cmd.tracks as string[] | undefined,
200
+ paused: cmd.paused as boolean | undefined,
201
+ live_point: cmd.live_point as boolean | undefined,
202
+ });
203
+ break;
204
+
205
+ case 'seek':
206
+ this.emit('seeked', {
207
+ live_point: (cmd as Record<string, unknown>).live_point as boolean | undefined,
208
+ });
209
+ // Resolve seek promise if pending
210
+ if (this.seekPromise) {
211
+ this.seekPromise.resolve('Seeked');
212
+ this.seekPromise = null;
213
+ }
214
+ break;
215
+
216
+ case 'set_speed':
217
+ this.emit('speed_changed', {
218
+ play_rate: (cmd as Record<string, unknown>).play_rate as number,
219
+ play_rate_curr: (cmd as Record<string, unknown>).play_rate_curr as number,
220
+ });
221
+ break;
222
+
223
+ case 'on_stop':
224
+ this.emit('stopped', undefined);
225
+ break;
226
+
227
+ case 'on_error':
228
+ this.emit('error', { message: cmd.message as string });
229
+ break;
230
+
231
+ default:
232
+ this.onLog(`Unhandled message type: ${type}`);
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Send a message to MistServer
238
+ */
239
+ send(cmd: Record<string, unknown>): boolean {
240
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
241
+ this.onLog('Cannot send: WebSocket not connected');
242
+ return false;
243
+ }
244
+
245
+ try {
246
+ this.ws.send(JSON.stringify(cmd));
247
+ return true;
248
+ } catch (e) {
249
+ this.onLog(`Failed to send message: ${e}`);
250
+ return false;
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Send SDP offer to MistServer
256
+ */
257
+ sendOfferSDP(sdp: string): boolean {
258
+ return this.send({ type: 'offer_sdp', offer_sdp: sdp });
259
+ }
260
+
261
+ /**
262
+ * Seek to position (in seconds or "live")
263
+ */
264
+ seek(time: number | 'live'): Promise<string> {
265
+ return new Promise((resolve, reject) => {
266
+ if (!this.isConnected) {
267
+ reject('Not connected');
268
+ return;
269
+ }
270
+
271
+ // Cancel previous seek if pending
272
+ if (this.seekPromise) {
273
+ this.seekPromise.reject('New seek requested');
274
+ }
275
+
276
+ // Send seek command (time in ms for MistServer)
277
+ const seekTime = time === 'live' ? 'live' : time * 1000;
278
+ this.send({ type: 'seek', seek_time: seekTime });
279
+
280
+ // Store promise handlers
281
+ this.seekPromise = { resolve, reject };
282
+ });
283
+ }
284
+
285
+ /**
286
+ * Pause playback (hold)
287
+ */
288
+ pause(): boolean {
289
+ return this.send({ type: 'hold' });
290
+ }
291
+
292
+ /**
293
+ * Stop playback
294
+ */
295
+ stop(): boolean {
296
+ return this.send({ type: 'stop' });
297
+ }
298
+
299
+ /**
300
+ * Set track selection
301
+ * @param video - Video track selection (e.g., "~1080x720", "|500000", "none")
302
+ * @param audio - Audio track selection (e.g., "eng", "none")
303
+ */
304
+ setTracks(options: { video?: string; audio?: string }): boolean {
305
+ return this.send({ type: 'tracks', ...options });
306
+ }
307
+
308
+ /**
309
+ * Set playback speed
310
+ * @param rate - Playback rate (1.0 normal, "auto" for live catch-up)
311
+ */
312
+ setSpeed(rate: number | 'auto'): boolean {
313
+ return this.send({ type: 'set_speed', play_rate: rate });
314
+ }
315
+
316
+ /**
317
+ * Close the connection
318
+ */
319
+ close(): void {
320
+ if (this.timeoutId) {
321
+ clearTimeout(this.timeoutId);
322
+ this.timeoutId = null;
323
+ }
324
+
325
+ if (this.seekPromise) {
326
+ this.seekPromise.reject('Connection closed');
327
+ this.seekPromise = null;
328
+ }
329
+
330
+ if (this.ws) {
331
+ this._state = 'closed';
332
+ this.ws.close();
333
+ this.ws = null;
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Destroy and cleanup
339
+ */
340
+ destroy(): void {
341
+ this.close();
342
+ this.removeAllListeners();
343
+ }
344
+ }
345
+
346
+ export default MistSignaling;