@livepeer-frameworks/player-core 0.1.0 → 0.1.1
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/player.css +182 -42
- package/package.json +1 -1
- package/src/core/ABRController.ts +38 -36
- package/src/core/CodecUtils.ts +49 -46
- package/src/core/Disposable.ts +4 -4
- 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 +527 -384
- package/src/core/PlayerInterface.ts +83 -59
- package/src/core/PlayerManager.ts +79 -133
- package/src/core/PlayerRegistry.ts +59 -42
- 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 +34 -31
- 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 +46 -35
- 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 +263 -221
- 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 +8 -8
- package/src/styles/animations.css +2 -1
- package/src/styles/player.css +182 -42
- package/src/styles/tailwind.css +473 -159
- package/src/types.ts +43 -43
- package/src/vanilla/FrameWorksPlayer.ts +29 -14
- package/src/vanilla/index.ts +4 -4
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Check if native MediaStreamTrackGenerator is available
|
|
17
17
|
*/
|
|
18
18
|
export function hasNativeMediaStreamTrackGenerator(): boolean {
|
|
19
|
-
return typeof (globalThis as any).MediaStreamTrackGenerator !==
|
|
19
|
+
return typeof (globalThis as any).MediaStreamTrackGenerator !== "undefined";
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -34,13 +34,13 @@ export class VideoTrackGeneratorPolyfill {
|
|
|
34
34
|
|
|
35
35
|
constructor() {
|
|
36
36
|
// Create offscreen canvas
|
|
37
|
-
this.canvas = document.createElement(
|
|
37
|
+
this.canvas = document.createElement("canvas");
|
|
38
38
|
this.canvas.width = 1920; // Will be resized on first frame
|
|
39
39
|
this.canvas.height = 1080;
|
|
40
40
|
|
|
41
|
-
const ctx = this.canvas.getContext(
|
|
41
|
+
const ctx = this.canvas.getContext("2d", { desynchronized: true });
|
|
42
42
|
if (!ctx) {
|
|
43
|
-
throw new Error(
|
|
43
|
+
throw new Error("Failed to create canvas 2D context");
|
|
44
44
|
}
|
|
45
45
|
this.ctx = ctx;
|
|
46
46
|
|
|
@@ -48,7 +48,7 @@ export class VideoTrackGeneratorPolyfill {
|
|
|
48
48
|
const stream = this.canvas.captureStream();
|
|
49
49
|
const tracks = stream.getVideoTracks();
|
|
50
50
|
if (tracks.length === 0) {
|
|
51
|
-
throw new Error(
|
|
51
|
+
throw new Error("Failed to capture stream from canvas");
|
|
52
52
|
}
|
|
53
53
|
this.track = tracks[0];
|
|
54
54
|
|
|
@@ -140,13 +140,13 @@ export class AudioTrackGeneratorPolyfill {
|
|
|
140
140
|
|
|
141
141
|
constructor() {
|
|
142
142
|
// Create audio context
|
|
143
|
-
this.audioContext = new AudioContext({ latencyHint:
|
|
143
|
+
this.audioContext = new AudioContext({ latencyHint: "interactive" });
|
|
144
144
|
|
|
145
145
|
// Create destination for MediaStreamTrack
|
|
146
146
|
this.destination = this.audioContext.createMediaStreamDestination();
|
|
147
147
|
const tracks = this.destination.stream.getAudioTracks();
|
|
148
148
|
if (tracks.length === 0) {
|
|
149
|
-
throw new Error(
|
|
149
|
+
throw new Error("Failed to create audio destination");
|
|
150
150
|
}
|
|
151
151
|
this.track = tracks[0];
|
|
152
152
|
|
|
@@ -234,16 +234,13 @@ export class AudioTrackGeneratorPolyfill {
|
|
|
234
234
|
registerProcessor('synced-audio-processor', SyncedAudioProcessor);
|
|
235
235
|
`;
|
|
236
236
|
|
|
237
|
-
const blob = new Blob([workletCode], { type:
|
|
237
|
+
const blob = new Blob([workletCode], { type: "application/javascript" });
|
|
238
238
|
const url = URL.createObjectURL(blob);
|
|
239
239
|
|
|
240
240
|
try {
|
|
241
241
|
await this.audioContext.audioWorklet.addModule(url);
|
|
242
242
|
|
|
243
|
-
this.workletNode = new AudioWorkletNode(
|
|
244
|
-
this.audioContext,
|
|
245
|
-
'synced-audio-processor'
|
|
246
|
-
);
|
|
243
|
+
this.workletNode = new AudioWorkletNode(this.audioContext, "synced-audio-processor");
|
|
247
244
|
this.workletNode.connect(this.destination);
|
|
248
245
|
|
|
249
246
|
this.initialized = true;
|
|
@@ -293,7 +290,7 @@ export class AudioTrackGeneratorPolyfill {
|
|
|
293
290
|
const samples = this.sampleBuffer.shift();
|
|
294
291
|
if (samples) {
|
|
295
292
|
this.workletNode.port.postMessage(
|
|
296
|
-
{ type:
|
|
293
|
+
{ type: "samples", samples },
|
|
297
294
|
{ transfer: [samples.buffer] }
|
|
298
295
|
);
|
|
299
296
|
}
|
|
@@ -340,9 +337,7 @@ export class AudioTrackGeneratorPolyfill {
|
|
|
340
337
|
* @param kind - 'video' or 'audio'
|
|
341
338
|
* @returns Native generator or polyfill
|
|
342
339
|
*/
|
|
343
|
-
export function createTrackGenerator(
|
|
344
|
-
kind: 'video' | 'audio'
|
|
345
|
-
): {
|
|
340
|
+
export function createTrackGenerator(kind: "video" | "audio"): {
|
|
346
341
|
writable: WritableStream<VideoFrame | AudioData>;
|
|
347
342
|
getTrack: () => MediaStreamTrack;
|
|
348
343
|
close: () => void;
|
|
@@ -360,7 +355,7 @@ export function createTrackGenerator(
|
|
|
360
355
|
}
|
|
361
356
|
|
|
362
357
|
// Fall back to polyfill
|
|
363
|
-
if (kind ===
|
|
358
|
+
if (kind === "video") {
|
|
364
359
|
const polyfill = new VideoTrackGeneratorPolyfill();
|
|
365
360
|
return {
|
|
366
361
|
writable: polyfill.writable as WritableStream<VideoFrame | AudioData>,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// Latency Profile Types
|
|
9
9
|
// ============================================================================
|
|
10
10
|
|
|
11
|
-
export type LatencyProfileName =
|
|
11
|
+
export type LatencyProfileName = "ultra-low" | "low" | "balanced" | "quality";
|
|
12
12
|
|
|
13
13
|
export interface LatencyProfile {
|
|
14
14
|
name: string;
|
|
@@ -34,7 +34,7 @@ export interface LatencyProfile {
|
|
|
34
34
|
// Raw Chunk Types (12-byte binary header protocol)
|
|
35
35
|
// ============================================================================
|
|
36
36
|
|
|
37
|
-
export type ChunkType =
|
|
37
|
+
export type ChunkType = "key" | "delta" | "init";
|
|
38
38
|
|
|
39
39
|
export interface RawChunk {
|
|
40
40
|
/** Track index from server */
|
|
@@ -53,7 +53,7 @@ export interface RawChunk {
|
|
|
53
53
|
// Track Types
|
|
54
54
|
// ============================================================================
|
|
55
55
|
|
|
56
|
-
export type TrackType =
|
|
56
|
+
export type TrackType = "video" | "audio" | "meta";
|
|
57
57
|
|
|
58
58
|
export interface TrackInfo {
|
|
59
59
|
idx: number;
|
|
@@ -76,17 +76,17 @@ export interface TrackInfo {
|
|
|
76
76
|
// ============================================================================
|
|
77
77
|
|
|
78
78
|
export type ControlMessageType =
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
79
|
+
| "codec_data"
|
|
80
|
+
| "info"
|
|
81
|
+
| "on_time"
|
|
82
|
+
| "tracks"
|
|
83
|
+
| "set_speed"
|
|
84
|
+
| "pause"
|
|
85
|
+
| "on_stop"
|
|
86
|
+
| "error";
|
|
87
87
|
|
|
88
88
|
export interface CodecDataMessage {
|
|
89
|
-
type:
|
|
89
|
+
type: "codec_data";
|
|
90
90
|
/** Current stream position in milliseconds */
|
|
91
91
|
current?: number;
|
|
92
92
|
/** List of WebCodecs-compatible codec strings (e.g., "avc1.42001f", "mp4a.40.2") */
|
|
@@ -100,7 +100,7 @@ export interface CodecDataMessage {
|
|
|
100
100
|
* Sent by MistServer with full stream information
|
|
101
101
|
*/
|
|
102
102
|
export interface InfoMessage {
|
|
103
|
-
type:
|
|
103
|
+
type: "info";
|
|
104
104
|
/** Stream metadata including tracks */
|
|
105
105
|
meta?: {
|
|
106
106
|
tracks?: Record<string, TrackInfo>;
|
|
@@ -110,7 +110,7 @@ export interface InfoMessage {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
export interface OnTimeMessage {
|
|
113
|
-
type:
|
|
113
|
+
type: "on_time";
|
|
114
114
|
/** Current playback time (seconds) */
|
|
115
115
|
current: number;
|
|
116
116
|
/** Total duration (seconds, Infinity for live) */
|
|
@@ -122,34 +122,34 @@ export interface OnTimeMessage {
|
|
|
122
122
|
/** Server-reported jitter (ms) */
|
|
123
123
|
jitter?: number;
|
|
124
124
|
/** Current play rate */
|
|
125
|
-
play_rate?: number |
|
|
125
|
+
play_rate?: number | "auto";
|
|
126
126
|
/** Current play rate (alias) */
|
|
127
|
-
play_rate_curr?: number |
|
|
127
|
+
play_rate_curr?: number | "auto" | "fast-forward";
|
|
128
128
|
/** Active track indices */
|
|
129
129
|
tracks?: number[];
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
export interface TracksMessage {
|
|
133
|
-
type:
|
|
133
|
+
type: "tracks";
|
|
134
134
|
tracks: TrackInfo[];
|
|
135
135
|
codecs?: string[];
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
export interface SetSpeedMessage {
|
|
139
|
-
type:
|
|
140
|
-
play_rate: number |
|
|
139
|
+
type: "set_speed";
|
|
140
|
+
play_rate: number | "auto";
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
export interface PauseMessage {
|
|
144
|
-
type:
|
|
144
|
+
type: "pause";
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
export interface OnStopMessage {
|
|
148
|
-
type:
|
|
148
|
+
type: "on_stop";
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
export interface ErrorMessage {
|
|
152
|
-
type:
|
|
152
|
+
type: "error";
|
|
153
153
|
message: string;
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -165,32 +165,32 @@ export type ControlMessage =
|
|
|
165
165
|
|
|
166
166
|
// Outbound control commands
|
|
167
167
|
export interface PlayCommand {
|
|
168
|
-
type:
|
|
168
|
+
type: "play";
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
export interface HoldCommand {
|
|
172
|
-
type:
|
|
172
|
+
type: "hold";
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
export interface SeekCommand {
|
|
176
|
-
type:
|
|
176
|
+
type: "seek";
|
|
177
177
|
seek_time: number; // milliseconds
|
|
178
178
|
ff_add?: number; // fast-forward buffer request (ms)
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
export interface SetSpeedCommand {
|
|
182
|
-
type:
|
|
183
|
-
play_rate: number |
|
|
182
|
+
type: "set_speed";
|
|
183
|
+
play_rate: number | "auto";
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
export interface RequestCodecDataCommand {
|
|
187
|
-
type:
|
|
187
|
+
type: "request_codec_data";
|
|
188
188
|
/** Supported codec combinations - array of [video codecs[], audio codecs[]] */
|
|
189
189
|
supported_combinations?: string[][][];
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
export interface FastForwardCommand {
|
|
193
|
-
type:
|
|
193
|
+
type: "fast_forward";
|
|
194
194
|
ff_add: number; // milliseconds of additional data to request
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -208,29 +208,29 @@ export type ControlCommand =
|
|
|
208
208
|
|
|
209
209
|
// Main thread -> Worker messages
|
|
210
210
|
export interface CreatePipelineMessage {
|
|
211
|
-
type:
|
|
211
|
+
type: "create";
|
|
212
212
|
idx: number;
|
|
213
213
|
track: TrackInfo;
|
|
214
214
|
opts: {
|
|
215
215
|
optimizeForLatency: boolean;
|
|
216
216
|
/** Payload format: 'avcc' (length-prefixed) or 'annexb' (start-code delimited) */
|
|
217
|
-
payloadFormat?:
|
|
217
|
+
payloadFormat?: "avcc" | "annexb";
|
|
218
218
|
};
|
|
219
219
|
uid?: number;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
export interface ConfigurePipelineMessage {
|
|
223
|
-
type:
|
|
223
|
+
type: "configure";
|
|
224
224
|
idx: number;
|
|
225
225
|
header: Uint8Array;
|
|
226
226
|
uid?: number;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
export interface ReceiveChunkMessage {
|
|
230
|
-
type:
|
|
230
|
+
type: "receive";
|
|
231
231
|
idx: number;
|
|
232
232
|
chunk: {
|
|
233
|
-
type:
|
|
233
|
+
type: "key" | "delta";
|
|
234
234
|
timestamp: number; // microseconds
|
|
235
235
|
data: Uint8Array;
|
|
236
236
|
};
|
|
@@ -238,28 +238,28 @@ export interface ReceiveChunkMessage {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
export interface SetWritableMessage {
|
|
241
|
-
type:
|
|
241
|
+
type: "setwritable";
|
|
242
242
|
idx: number;
|
|
243
243
|
writable: WritableStream;
|
|
244
244
|
uid?: number;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
export interface CreateGeneratorMessage {
|
|
248
|
-
type:
|
|
248
|
+
type: "creategenerator";
|
|
249
249
|
idx: number;
|
|
250
250
|
uid?: number;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
export interface ClosePipelineMessage {
|
|
254
|
-
type:
|
|
254
|
+
type: "close";
|
|
255
255
|
idx: number;
|
|
256
256
|
waitEmpty?: boolean;
|
|
257
257
|
uid?: number;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
export interface FrameTimingMessage {
|
|
261
|
-
type:
|
|
262
|
-
action:
|
|
261
|
+
type: "frametiming";
|
|
262
|
+
action: "setSpeed" | "reset" | "setPaused";
|
|
263
263
|
speed?: number;
|
|
264
264
|
tweak?: number;
|
|
265
265
|
paused?: boolean;
|
|
@@ -267,28 +267,28 @@ export interface FrameTimingMessage {
|
|
|
267
267
|
}
|
|
268
268
|
|
|
269
269
|
export interface SeekWorkerMessage {
|
|
270
|
-
type:
|
|
270
|
+
type: "seek";
|
|
271
271
|
seekTime: number; // milliseconds
|
|
272
272
|
uid?: number;
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
export interface DebuggingMessage {
|
|
276
|
-
type:
|
|
277
|
-
value: boolean |
|
|
276
|
+
type: "debugging";
|
|
277
|
+
value: boolean | "verbose";
|
|
278
278
|
uid?: number;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
export interface FrameStepMessage {
|
|
282
|
-
type:
|
|
282
|
+
type: "framestep";
|
|
283
283
|
direction: -1 | 1;
|
|
284
284
|
uid?: number;
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
export interface WriteFrameResponseMessage {
|
|
288
|
-
type:
|
|
288
|
+
type: "writeframe";
|
|
289
289
|
idx: number;
|
|
290
290
|
uid?: number;
|
|
291
|
-
status:
|
|
291
|
+
status: "ok" | "error";
|
|
292
292
|
error?: string;
|
|
293
293
|
}
|
|
294
294
|
|
|
@@ -307,39 +307,39 @@ export type MainToWorkerMessage =
|
|
|
307
307
|
|
|
308
308
|
// Worker -> Main thread messages
|
|
309
309
|
export interface AddTrackMessage {
|
|
310
|
-
type:
|
|
310
|
+
type: "addtrack";
|
|
311
311
|
idx: number;
|
|
312
312
|
track?: MediaStreamTrack; // Safari only
|
|
313
313
|
uid?: number;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
export interface RemoveTrackMessage {
|
|
317
|
-
type:
|
|
317
|
+
type: "removetrack";
|
|
318
318
|
idx: number;
|
|
319
319
|
uid?: number;
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
export interface SetPlaybackRateMessage {
|
|
323
|
-
type:
|
|
323
|
+
type: "setplaybackrate";
|
|
324
324
|
speed: number;
|
|
325
325
|
uid?: number;
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
export interface ClosedMessage {
|
|
329
|
-
type:
|
|
329
|
+
type: "closed";
|
|
330
330
|
idx: number;
|
|
331
331
|
uid?: number;
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
export interface LogMessage {
|
|
335
|
-
type:
|
|
335
|
+
type: "log";
|
|
336
336
|
msg: string;
|
|
337
|
-
level?:
|
|
337
|
+
level?: "info" | "warn" | "error";
|
|
338
338
|
uid?: number;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
export interface SendEventMessage {
|
|
342
|
-
type:
|
|
342
|
+
type: "sendevent";
|
|
343
343
|
kind: string;
|
|
344
344
|
message?: string;
|
|
345
345
|
time?: number;
|
|
@@ -348,21 +348,21 @@ export interface SendEventMessage {
|
|
|
348
348
|
}
|
|
349
349
|
|
|
350
350
|
export interface StatsMessage {
|
|
351
|
-
type:
|
|
351
|
+
type: "stats";
|
|
352
352
|
stats: WorkerStats;
|
|
353
353
|
uid?: number;
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
export interface AckMessage {
|
|
357
|
-
type:
|
|
357
|
+
type: "ack";
|
|
358
358
|
idx?: number;
|
|
359
359
|
uid?: number;
|
|
360
|
-
status?:
|
|
360
|
+
status?: "ok" | "error";
|
|
361
361
|
error?: string;
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
export interface WriteFrameMessage {
|
|
365
|
-
type:
|
|
365
|
+
type: "writeframe";
|
|
366
366
|
idx: number;
|
|
367
367
|
frame: AudioData;
|
|
368
368
|
uid?: number;
|