@banou/media-player 0.9.0 → 0.10.0
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 +7 -0
- package/dist/engine/index.js +1 -1
- package/dist/engine/thumbnails.d.ts +11 -0
- package/dist/{engine-DZrYu66u.js → engine-YeMWShCv.js} +35 -19
- package/dist/index.js +204 -194
- package/dist/react/hooks/use-thumbnails.d.ts +12 -1
- package/dist/react/player.d.ts +1 -0
- package/dist/react/source-feature.d.ts +22 -0
- package/package.json +1 -1
- package/src/lib/engine/thumbnails.ts +80 -21
- package/src/lib/react/components/progress-bar.tsx +17 -4
- package/src/lib/react/hooks/use-thumbnails.ts +19 -3
- package/src/lib/react/source-feature.ts +12 -0
- package/src/lib/react/video-player.tsx +4 -2
package/README.md
CHANGED
|
@@ -58,6 +58,13 @@ player.play()
|
|
|
58
58
|
|
|
59
59
|
`useSeekThumbnails` and `usePictureInPicture` are exported for reuse outside the bundled chrome.
|
|
60
60
|
|
|
61
|
+
`useSeekThumbnails` returns `{ thumbnails, requestThumbnail }`. Previews are generated from the start
|
|
62
|
+
of the file to the end, which is right until somebody points at the seekbar: `requestThumbnail(time)`
|
|
63
|
+
moves the preview covering `time` to the front of that queue, and the walk carries on behind it from
|
|
64
|
+
wherever it had got to. Pass `undefined` when the pointer leaves. The bundled seekbar calls it for
|
|
65
|
+
you, so this is only for a chrome you draw yourself. It cannot interrupt a decode already in flight,
|
|
66
|
+
so the wait is the tail of that one rather than the whole backlog.
|
|
67
|
+
|
|
61
68
|
`downloadedRanges` paints byte spans you already hold onto the seekbar, mapped through the keyframe
|
|
62
69
|
index rather than by percentage, because a file's download progress is not its playback progress:
|
|
63
70
|
containers carry headers, fonts and attachments that occupy no time at all.
|
package/dist/engine/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, r as c, s as l, t as u, u as d } from "../engine-
|
|
1
|
+
import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, r as c, s as l, t as u, u as d } from "../engine-YeMWShCv.js";
|
|
2
2
|
export { i as DEFAULT_BUFFER_SIZE, e as MediaElementError, a as SUBTITLES_OFF, u as createPictureInPicture, d as createSubtitleRenderer, c as createThumbnailGenerator, n as getTimeRanges, s as isMediaElementError, o as pictureInPictureMode, l as startPlayback, t as terminateRemuxer, r as updateSourceBuffer };
|
|
@@ -17,6 +17,17 @@ export type ThumbnailGeneratorOptions = {
|
|
|
17
17
|
export type ThumbnailGenerator = {
|
|
18
18
|
/** Report which byte ranges are readable. Called with no argument when the whole file is. */
|
|
19
19
|
update: (ranges?: [number, number][]) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Where the viewer is pointing, so that preview is decoded next. `undefined` when they stop.
|
|
22
|
+
*
|
|
23
|
+
* Only the slot covering `time` jumps the queue, and only for as long as it is still waiting, so
|
|
24
|
+
* this moves one preview forward rather than re-ordering the run. Everything behind it keeps the
|
|
25
|
+
* order it was claimed in and carries on the moment the jumped slot is done.
|
|
26
|
+
*
|
|
27
|
+
* It cannot interrupt a decode that has already started, so the wait is the tail of the one in
|
|
28
|
+
* flight and not the whole backlog.
|
|
29
|
+
*/
|
|
30
|
+
prioritize: (time: number | undefined) => void;
|
|
20
31
|
destroy: () => void;
|
|
21
32
|
};
|
|
22
33
|
export declare const createThumbnailGenerator: (options: ThumbnailGeneratorOptions) => Promise<ThumbnailGenerator>;
|
|
@@ -404,7 +404,14 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
404
404
|
}
|
|
405
405
|
for (let [e, t] of a.entries()) t.endTime = a[e + 1]?.timestamp ?? n;
|
|
406
406
|
a.length > 1 && a.at(-1).timestamp > n - r * 2 && a.pop();
|
|
407
|
-
let l = [], u = !1, d =
|
|
407
|
+
let l = [], u = !1, d = [], f = !1, p, m = () => {
|
|
408
|
+
let e = p;
|
|
409
|
+
if (e !== void 0) {
|
|
410
|
+
let t = d.findIndex(({ timestamp: t, endTime: n }) => t <= e && e < n);
|
|
411
|
+
if (t >= 0) return t;
|
|
412
|
+
}
|
|
413
|
+
return 0;
|
|
414
|
+
}, h = () => {
|
|
408
415
|
let e = [];
|
|
409
416
|
for (let [t, n] of l.entries()) {
|
|
410
417
|
n.startTime - (e.at(-1)?.endTime ?? 0) > .01 && e.push({
|
|
@@ -425,30 +432,39 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
425
432
|
startTime: t,
|
|
426
433
|
endTime: n
|
|
427
434
|
}), o(e);
|
|
428
|
-
},
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
435
|
+
}, g = async (e) => {
|
|
436
|
+
if (u) return;
|
|
437
|
+
let t = await Promise.race([c.readKeyframe(e.timestamp), new Promise((e, t) => setTimeout(() => t(/* @__PURE__ */ Error("timed out")), M))]), n = await createImageBitmap(new Blob([t], { type: "image/png" })), r = new OffscreenCanvas(s, Math.max(1, Math.round(n.height * (s / n.width))));
|
|
438
|
+
r.getContext("2d").drawImage(n, 0, 0, r.width, r.height), n.close();
|
|
439
|
+
let i = await r.convertToBlob({
|
|
440
|
+
type: "image/webp",
|
|
441
|
+
quality: .7
|
|
442
|
+
});
|
|
443
|
+
u || (l = [...l, {
|
|
444
|
+
url: URL.createObjectURL(i),
|
|
445
|
+
startTime: e.timestamp,
|
|
446
|
+
endTime: e.endTime
|
|
447
|
+
}].sort((e, t) => e.startTime - t.startTime), h());
|
|
448
|
+
}, _ = () => {
|
|
449
|
+
if (f || u || !d.length) return;
|
|
450
|
+
let e = d.splice(m(), 1)[0];
|
|
451
|
+
f = !0, g(e).catch(() => {
|
|
443
452
|
e.attempts += 1, e.done = e.attempts >= ae;
|
|
453
|
+
}).finally(() => {
|
|
454
|
+
f = !1, _();
|
|
444
455
|
});
|
|
456
|
+
}, v = (e) => {
|
|
457
|
+
e.done = !0, d.push(e), _();
|
|
445
458
|
};
|
|
446
|
-
return
|
|
459
|
+
return h(), {
|
|
447
460
|
update: (e) => {
|
|
448
|
-
if (!u) for (let t of a) t.done || (!e || e.some(([e, n]) => e <= t.startByte && t.endByte <= n)) &&
|
|
461
|
+
if (!u) for (let t of a) t.done || (!e || e.some(([e, n]) => e <= t.startByte && t.endByte <= n)) && v(t);
|
|
462
|
+
},
|
|
463
|
+
prioritize: (e) => {
|
|
464
|
+
u || (p = e);
|
|
449
465
|
},
|
|
450
466
|
destroy: () => {
|
|
451
|
-
u = !0;
|
|
467
|
+
u = !0, d.length = 0;
|
|
452
468
|
for (let e of l) URL.revokeObjectURL(e.url);
|
|
453
469
|
l = [], A(c);
|
|
454
470
|
}
|