@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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* - Track switch msgqueue handling
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import type { SourceBufferManagerOptions } from
|
|
15
|
+
import type { SourceBufferManagerOptions } from "./types";
|
|
16
16
|
|
|
17
17
|
export class SourceBufferManager {
|
|
18
18
|
private mediaSource: MediaSource;
|
|
@@ -62,12 +62,12 @@ export class SourceBufferManager {
|
|
|
62
62
|
return true;
|
|
63
63
|
}
|
|
64
64
|
if (!codecs || !codecs.length) {
|
|
65
|
-
this.onError(
|
|
65
|
+
this.onError("No codecs provided");
|
|
66
66
|
return false;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const container =
|
|
70
|
-
const mime = `video/${container};codecs="${codecs.join(
|
|
69
|
+
const container = "mp4"; // Could be 'webm' for WebM container
|
|
70
|
+
const mime = `video/${container};codecs="${codecs.join(",")}"`;
|
|
71
71
|
|
|
72
72
|
if (!MediaSource.isTypeSupported(mime)) {
|
|
73
73
|
this.onError(`Unsupported MSE codec: ${mime}`);
|
|
@@ -78,7 +78,7 @@ export class SourceBufferManager {
|
|
|
78
78
|
// Create SourceBuffer (mews.js:211)
|
|
79
79
|
this.sourceBuffer = this.mediaSource.addSourceBuffer(mime);
|
|
80
80
|
// Use segments mode - fragments will be put at correct time (mews.js:212)
|
|
81
|
-
this.sourceBuffer.mode =
|
|
81
|
+
this.sourceBuffer.mode = "segments";
|
|
82
82
|
// Save current codecs (mews.js:215)
|
|
83
83
|
this._codecs = codecs.slice();
|
|
84
84
|
|
|
@@ -92,7 +92,7 @@ export class SourceBufferManager {
|
|
|
92
92
|
|
|
93
93
|
return true;
|
|
94
94
|
} catch (e: any) {
|
|
95
|
-
this.onError(e?.message ||
|
|
95
|
+
this.onError(e?.message || "Failed to create SourceBuffer");
|
|
96
96
|
return false;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -144,7 +144,7 @@ export class SourceBufferManager {
|
|
|
144
144
|
|
|
145
145
|
if (this._busy) {
|
|
146
146
|
// Still busy, put back in queue (mews.js:296-300)
|
|
147
|
-
if (this.debugging) console.warn(
|
|
147
|
+
if (this.debugging) console.warn("MEWS: wanted to append but busy, requeuing");
|
|
148
148
|
this.queue.unshift(data);
|
|
149
149
|
return;
|
|
150
150
|
}
|
|
@@ -165,13 +165,13 @@ export class SourceBufferManager {
|
|
|
165
165
|
} catch (e: any) {
|
|
166
166
|
// Error handling (mews.js:306-338)
|
|
167
167
|
switch (e?.name) {
|
|
168
|
-
case
|
|
168
|
+
case "QuotaExceededError": {
|
|
169
169
|
// Buffer is full - clean up and retry (mews.js:308-324)
|
|
170
170
|
const buffered = this.videoElement.buffered;
|
|
171
171
|
if (buffered.length && this.videoElement.currentTime - buffered.start(0) > 1) {
|
|
172
172
|
// Clear as much from buffer as we can
|
|
173
173
|
if (this.debugging) {
|
|
174
|
-
console.log(
|
|
174
|
+
console.log("MEWS: QuotaExceededError, cleaning buffer");
|
|
175
175
|
}
|
|
176
176
|
this._clean(1); // Keep 1 second
|
|
177
177
|
this._busy = false;
|
|
@@ -181,7 +181,7 @@ export class SourceBufferManager {
|
|
|
181
181
|
// Can't clean more, skip ahead (mews.js:316-319)
|
|
182
182
|
const bufferEnd = buffered.end(buffered.length - 1);
|
|
183
183
|
if (this.debugging) {
|
|
184
|
-
console.log(
|
|
184
|
+
console.log("MEWS: QuotaExceededError, skipping ahead");
|
|
185
185
|
}
|
|
186
186
|
this.videoElement.currentTime = bufferEnd;
|
|
187
187
|
this._busy = false;
|
|
@@ -190,7 +190,7 @@ export class SourceBufferManager {
|
|
|
190
190
|
}
|
|
191
191
|
break;
|
|
192
192
|
}
|
|
193
|
-
case
|
|
193
|
+
case "InvalidStateError": {
|
|
194
194
|
// Playback is borked (mews.js:326-334)
|
|
195
195
|
if (this.videoElement.error) {
|
|
196
196
|
// Video element error will handle this
|
|
@@ -200,7 +200,7 @@ export class SourceBufferManager {
|
|
|
200
200
|
break;
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
|
-
this.onError(e?.message ||
|
|
203
|
+
this.onError(e?.message || "Append buffer failed");
|
|
204
204
|
this._busy = false;
|
|
205
205
|
}
|
|
206
206
|
}
|
|
@@ -245,12 +245,12 @@ export class SourceBufferManager {
|
|
|
245
245
|
changeCodecs(codecs: string[], switchPointMs?: number): void {
|
|
246
246
|
// Skip reinit if codecs are identical (mews.js:676)
|
|
247
247
|
if (this.codecsEqual(this._codecs, codecs)) {
|
|
248
|
-
if (this.debugging) console.log(
|
|
248
|
+
if (this.debugging) console.log("MEWS: keeping source buffer, codecs same");
|
|
249
249
|
return;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
const container =
|
|
253
|
-
const mime = `video/${container};codecs="${codecs.join(
|
|
252
|
+
const container = "mp4";
|
|
253
|
+
const mime = `video/${container};codecs="${codecs.join(",")}"`;
|
|
254
254
|
if (!MediaSource.isTypeSupported(mime)) {
|
|
255
255
|
this.onError(`Unsupported codec for switch: ${mime}`);
|
|
256
256
|
return;
|
|
@@ -265,7 +265,7 @@ export class SourceBufferManager {
|
|
|
265
265
|
|
|
266
266
|
const pendingCodecs = codecs.slice();
|
|
267
267
|
|
|
268
|
-
if (typeof switchPointMs ===
|
|
268
|
+
if (typeof switchPointMs === "number" && switchPointMs > 0) {
|
|
269
269
|
// Wait for playback to reach switching point (mews.js:751-785)
|
|
270
270
|
this.awaitSwitchingPoint(mime, switchPointMs, pendingCodecs);
|
|
271
271
|
} else {
|
|
@@ -368,7 +368,7 @@ export class SourceBufferManager {
|
|
|
368
368
|
this.queue = [];
|
|
369
369
|
|
|
370
370
|
// Remove old sourceBuffer
|
|
371
|
-
if (this.sourceBuffer && this.mediaSource.readyState ===
|
|
371
|
+
if (this.sourceBuffer && this.mediaSource.readyState === "open") {
|
|
372
372
|
try {
|
|
373
373
|
this.mediaSource.removeSourceBuffer(this.sourceBuffer);
|
|
374
374
|
} catch {
|
|
@@ -381,7 +381,7 @@ export class SourceBufferManager {
|
|
|
381
381
|
try {
|
|
382
382
|
// Create new sourceBuffer (mews.js:713-715)
|
|
383
383
|
this.sourceBuffer = this.mediaSource.addSourceBuffer(mime);
|
|
384
|
-
this.sourceBuffer.mode =
|
|
384
|
+
this.sourceBuffer.mode = "segments";
|
|
385
385
|
this._codecs = newCodecs;
|
|
386
386
|
|
|
387
387
|
this.installEventHandlers();
|
|
@@ -399,7 +399,7 @@ export class SourceBufferManager {
|
|
|
399
399
|
this.append(frag);
|
|
400
400
|
}
|
|
401
401
|
} catch (e: any) {
|
|
402
|
-
this.onError(e?.message ||
|
|
402
|
+
this.onError(e?.message || "Failed to reinit SourceBuffer");
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
405
|
|
|
@@ -417,21 +417,21 @@ export class SourceBufferManager {
|
|
|
417
417
|
// Wait for video.currentTime to reach switch point
|
|
418
418
|
const onTimeUpdate = () => {
|
|
419
419
|
if (this.videoElement.currentTime >= tSec) {
|
|
420
|
-
this.videoElement.removeEventListener(
|
|
421
|
-
this.videoElement.removeEventListener(
|
|
420
|
+
this.videoElement.removeEventListener("timeupdate", onTimeUpdate);
|
|
421
|
+
this.videoElement.removeEventListener("waiting", onWaiting);
|
|
422
422
|
clearAndReinit();
|
|
423
423
|
}
|
|
424
424
|
};
|
|
425
425
|
|
|
426
426
|
// Or if video is waiting (buffer empty before switch point)
|
|
427
427
|
const onWaiting = () => {
|
|
428
|
-
this.videoElement.removeEventListener(
|
|
429
|
-
this.videoElement.removeEventListener(
|
|
428
|
+
this.videoElement.removeEventListener("timeupdate", onTimeUpdate);
|
|
429
|
+
this.videoElement.removeEventListener("waiting", onWaiting);
|
|
430
430
|
clearAndReinit();
|
|
431
431
|
};
|
|
432
432
|
|
|
433
|
-
this.videoElement.addEventListener(
|
|
434
|
-
this.videoElement.addEventListener(
|
|
433
|
+
this.videoElement.addEventListener("timeupdate", onTimeUpdate);
|
|
434
|
+
this.videoElement.addEventListener("waiting", onWaiting);
|
|
435
435
|
}
|
|
436
436
|
|
|
437
437
|
/**
|
|
@@ -468,14 +468,14 @@ export class SourceBufferManager {
|
|
|
468
468
|
|
|
469
469
|
if (this.debugging) {
|
|
470
470
|
console.log(
|
|
471
|
-
|
|
472
|
-
this.msgqueue ? `${this.msgqueue.length} more queue(s) remain` :
|
|
471
|
+
"MEWS: drained msgqueue",
|
|
472
|
+
this.msgqueue ? `${this.msgqueue.length} more queue(s) remain` : ""
|
|
473
473
|
);
|
|
474
474
|
}
|
|
475
475
|
|
|
476
476
|
// Manually trigger updateend if queue was empty (mews.js:363-366)
|
|
477
477
|
if (do_do && this.sourceBuffer) {
|
|
478
|
-
this.sourceBuffer.dispatchEvent(new Event(
|
|
478
|
+
this.sourceBuffer.dispatchEvent(new Event("updateend"));
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
481
|
|
|
@@ -486,9 +486,9 @@ export class SourceBufferManager {
|
|
|
486
486
|
private installEventHandlers(): void {
|
|
487
487
|
if (!this.sourceBuffer) return;
|
|
488
488
|
|
|
489
|
-
this.sourceBuffer.addEventListener(
|
|
489
|
+
this.sourceBuffer.addEventListener("updateend", () => {
|
|
490
490
|
if (!this.sourceBuffer) {
|
|
491
|
-
if (this.debugging) console.log(
|
|
491
|
+
if (this.debugging) console.log("MEWS: updateend but sourceBuffer is null");
|
|
492
492
|
return;
|
|
493
493
|
}
|
|
494
494
|
|
|
@@ -506,33 +506,38 @@ export class SourceBufferManager {
|
|
|
506
506
|
|
|
507
507
|
for (let i = 0; i < do_funcs.length; i++) {
|
|
508
508
|
if (!this.sourceBuffer) {
|
|
509
|
-
if (this.debugging) console.warn(
|
|
509
|
+
if (this.debugging) console.warn("MEWS: doing updateend but sb was reset");
|
|
510
510
|
break;
|
|
511
511
|
}
|
|
512
512
|
if (this.sourceBuffer.updating) {
|
|
513
513
|
// Still updating, requeue remaining functions (mews.js:255-259)
|
|
514
514
|
this.do_on_updateend = this.do_on_updateend.concat(do_funcs.slice(i));
|
|
515
|
-
if (this.debugging) console.warn(
|
|
515
|
+
if (this.debugging) console.warn("MEWS: doing updateend but was interrupted");
|
|
516
516
|
break;
|
|
517
517
|
}
|
|
518
518
|
try {
|
|
519
519
|
// Pass remaining functions as argument (mews.js:261)
|
|
520
520
|
do_funcs[i](i < do_funcs.length - 1 ? do_funcs.slice(i + 1) : []);
|
|
521
521
|
} catch (e) {
|
|
522
|
-
console.error(
|
|
522
|
+
console.error("MEWS: error in do_on_updateend:", e);
|
|
523
523
|
}
|
|
524
524
|
}
|
|
525
525
|
|
|
526
526
|
this._busy = false;
|
|
527
527
|
|
|
528
528
|
// Process queued data (mews.js:269-272)
|
|
529
|
-
if (
|
|
529
|
+
if (
|
|
530
|
+
this.sourceBuffer &&
|
|
531
|
+
this.queue.length > 0 &&
|
|
532
|
+
!this.sourceBuffer.updating &&
|
|
533
|
+
!this.videoElement.error
|
|
534
|
+
) {
|
|
530
535
|
this._append(this.queue.shift()!);
|
|
531
536
|
}
|
|
532
537
|
});
|
|
533
538
|
|
|
534
|
-
this.sourceBuffer.addEventListener(
|
|
535
|
-
this.onError(
|
|
539
|
+
this.sourceBuffer.addEventListener("error", () => {
|
|
540
|
+
this.onError("SourceBuffer error");
|
|
536
541
|
});
|
|
537
542
|
}
|
|
538
543
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Ported from reference: mews.js:387-883
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import type { WebSocketManagerOptions, MewsMessage, MewsMessageListener } from
|
|
10
|
+
import type { WebSocketManagerOptions, MewsMessage, MewsMessageListener } from "./types";
|
|
11
11
|
|
|
12
12
|
export class WebSocketManager {
|
|
13
13
|
private ws: WebSocket | null = null;
|
|
@@ -44,7 +44,7 @@ export class WebSocketManager {
|
|
|
44
44
|
|
|
45
45
|
// Protocol mismatch check (non-fatal warning)
|
|
46
46
|
try {
|
|
47
|
-
const pageProto = window.location.protocol.replace(/^http/,
|
|
47
|
+
const pageProto = window.location.protocol.replace(/^http/, "ws");
|
|
48
48
|
const srcProto = new URL(this.url, window.location.href).protocol;
|
|
49
49
|
if (pageProto !== srcProto) {
|
|
50
50
|
this.onError(`Protocol mismatch ${pageProto} vs ${srcProto}`);
|
|
@@ -52,7 +52,7 @@ export class WebSocketManager {
|
|
|
52
52
|
} catch {}
|
|
53
53
|
|
|
54
54
|
const ws = new WebSocket(this.url);
|
|
55
|
-
ws.binaryType =
|
|
55
|
+
ws.binaryType = "arraybuffer";
|
|
56
56
|
this.ws = ws;
|
|
57
57
|
|
|
58
58
|
ws.onopen = () => {
|
|
@@ -67,7 +67,7 @@ export class WebSocketManager {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
ws.onerror = () => {
|
|
70
|
-
this.onError(
|
|
70
|
+
this.onError("WebSocket error");
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
ws.onclose = () => {
|
|
@@ -83,7 +83,7 @@ export class WebSocketManager {
|
|
|
83
83
|
}, backoff);
|
|
84
84
|
} else {
|
|
85
85
|
this.onClose();
|
|
86
|
-
this.onError(
|
|
86
|
+
this.onError("WebSocket closed");
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
89
|
}
|
|
@@ -101,7 +101,7 @@ export class WebSocketManager {
|
|
|
101
101
|
if (this.isDestroyed) return false;
|
|
102
102
|
|
|
103
103
|
if (retry > MAX_RETRIES) {
|
|
104
|
-
this.onError(
|
|
104
|
+
this.onError("Too many send retries");
|
|
105
105
|
return false;
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -156,7 +156,7 @@ export class WebSocketManager {
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
destroy(): void {
|
|
159
|
-
console.debug(
|
|
159
|
+
console.debug("[WebSocketManager] destroy() called");
|
|
160
160
|
this.isDestroyed = true;
|
|
161
161
|
this.clearReconnectTimer();
|
|
162
162
|
|
|
@@ -175,7 +175,7 @@ export class WebSocketManager {
|
|
|
175
175
|
} catch {}
|
|
176
176
|
this.ws = null;
|
|
177
177
|
}
|
|
178
|
-
console.debug(
|
|
178
|
+
console.debug("[WebSocketManager] destroy() completed");
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
isConnected(): boolean {
|
|
@@ -232,7 +232,7 @@ export class WebSocketManager {
|
|
|
232
232
|
callbacks[i](msg);
|
|
233
233
|
} catch (e) {
|
|
234
234
|
// Don't let one listener crash others
|
|
235
|
-
console.error(
|
|
235
|
+
console.error("MEWS listener error:", e);
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
}
|