@banou/media-player 0.8.5 → 0.8.7
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/engine/index.d.ts +2 -2
- package/dist/engine/index.js +2 -2
- package/dist/engine/picture-in-picture.d.ts +18 -6
- package/dist/{engine-Dmc7JSd9.js → engine-B6flRjLd.js} +149 -111
- package/dist/index.js +521 -364
- package/dist/react/components/burn-in-hint.d.ts +9 -0
- package/dist/react/components/icons.d.ts +8 -0
- package/dist/react/hooks/use-picture-in-picture.d.ts +17 -2
- package/dist/react/player.d.ts +2 -0
- package/dist/react/source-feature.d.ts +17 -1
- package/dist/utils/colors.d.ts +2 -0
- package/package.json +1 -1
- package/src/lib/engine/index.ts +2 -2
- package/src/lib/engine/picture-in-picture.ts +183 -49
- package/src/lib/engine/playback.ts +28 -0
- package/src/lib/react/components/burn-in-hint.tsx +105 -0
- package/src/lib/react/components/chrome.tsx +3 -0
- package/src/lib/react/components/control-bar.tsx +76 -3
- package/src/lib/react/components/icons.tsx +15 -0
- package/src/lib/react/hooks/use-picture-in-picture.ts +30 -12
- package/src/lib/react/source-feature.ts +12 -1
- package/src/lib/react/video-player.tsx +15 -3
- package/src/lib/utils/colors.ts +2 -0
package/dist/engine/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export { createThumbnailGenerator } from './thumbnails';
|
|
|
6
6
|
export type { ThumbnailGenerator, ThumbnailGeneratorOptions, ThumbnailImage } from './thumbnails';
|
|
7
7
|
export { getTimeRanges, updateSourceBuffer } from './source-buffer';
|
|
8
8
|
export type { TimeRange } from './source-buffer';
|
|
9
|
-
export { createPictureInPicture } from './picture-in-picture';
|
|
10
|
-
export type { PictureInPictureController, PictureInPictureOptions } from './picture-in-picture';
|
|
9
|
+
export { createPictureInPicture, pictureInPictureMode } from './picture-in-picture';
|
|
10
|
+
export type { PictureInPictureController, PictureInPictureOptions, PictureInPictureMode } from './picture-in-picture';
|
package/dist/engine/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "../engine-
|
|
2
|
-
export {
|
|
1
|
+
import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c, u as l } from "../engine-B6flRjLd.js";
|
|
2
|
+
export { n as DEFAULT_BUFFER_SIZE, s as SUBTITLES_OFF, c as createPictureInPicture, t as createSubtitleRenderer, o as createThumbnailGenerator, r as getTimeRanges, i as pictureInPictureMode, e as startPlayback, a as terminateRemuxer, l as updateSourceBuffer };
|
|
@@ -6,22 +6,34 @@
|
|
|
6
6
|
* `captureStream()` backs a hidden mirror element, which is the one that enters the window. The
|
|
7
7
|
* original element keeps playing and stays the only audio source.
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* `window` opens a real picture in picture window. `burn-in` cannot, and instead paints the
|
|
11
|
+
* composite into the player itself so the browser's OWN picture in picture control carries the
|
|
12
|
+
* subtitles with it.
|
|
13
|
+
*/
|
|
14
|
+
export type PictureInPictureMode = 'window' | 'burn-in';
|
|
9
15
|
export type PictureInPictureOptions = {
|
|
10
16
|
video: HTMLVideoElement;
|
|
11
17
|
/** The subtitle canvas. jassub sizes it to the video's content rect, so it maps 1:1. */
|
|
12
18
|
canvas: HTMLCanvasElement;
|
|
13
19
|
maxWidth?: number;
|
|
14
|
-
/** Where the
|
|
20
|
+
/** Where the mirror is mounted. It must be in the document. Defaults to the video's parent. */
|
|
15
21
|
container?: HTMLElement;
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
fallback?: () => Promise<void>;
|
|
22
|
+
/** Overrides detection. Passing a mode the browser cannot honour is the caller's problem. */
|
|
23
|
+
mode?: PictureInPictureMode;
|
|
24
|
+
/** Burn-in only, so the chrome can light the control up and say what happened. */
|
|
25
|
+
onBurnedInChange?: (burnedIn: boolean) => void;
|
|
21
26
|
};
|
|
22
27
|
export type PictureInPictureController = {
|
|
23
28
|
toggle: () => Promise<void>;
|
|
24
29
|
destroy: () => void;
|
|
30
|
+
mode: PictureInPictureMode;
|
|
25
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* null means offer no control at all. That covers Safari, whose picture in picture is
|
|
34
|
+
* `webkitSetPresentationMode` and not the W3C API, so neither arm here can drive it. A dead button
|
|
35
|
+
* is worse than no button.
|
|
36
|
+
*/
|
|
37
|
+
export declare const pictureInPictureMode: () => PictureInPictureMode | null;
|
|
26
38
|
/** Takes over the document's Media Session play/pause handlers while a session is open. */
|
|
27
39
|
export declare const createPictureInPicture: (options: PictureInPictureOptions) => PictureInPictureController;
|
|
@@ -168,7 +168,7 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
168
168
|
clearTimeout(n), t.terminate();
|
|
169
169
|
});
|
|
170
170
|
}, T = async (t) => {
|
|
171
|
-
let { videoElement: n, canvasElement: r, read: i, length: o, publicPath: c, libavWorkerUrl: l, jassubWorkerUrl: u, jassubWasmUrl: d, jassubLegacyWasmUrl: f, defaultFontUrl: p, bufferSize: T = C, audioStreamIndex: E, onReady: D, onError: O, onRecovered: k, onSeek: A, onSubtitleStreams: j, onAudioStreams:
|
|
171
|
+
let { videoElement: n, canvasElement: r, read: i, length: o, publicPath: c, libavWorkerUrl: l, jassubWorkerUrl: u, jassubWasmUrl: d, jassubLegacyWasmUrl: f, defaultFontUrl: p, bufferSize: T = C, audioStreamIndex: E, onReady: D, onError: O, onRecovered: k, onSeek: A, onSubtitleStreams: j, onAudioStreams: ee } = t, M = await e({
|
|
172
172
|
publicPath: c,
|
|
173
173
|
workerUrl: l,
|
|
174
174
|
workerOptions: { type: "module" },
|
|
@@ -176,18 +176,18 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
176
176
|
length: o,
|
|
177
177
|
audioStreamIndex: E,
|
|
178
178
|
read: i
|
|
179
|
-
}),
|
|
180
|
-
if (!
|
|
181
|
-
|
|
182
|
-
for (let e of [...
|
|
179
|
+
}), N = [], P = !1, F = () => {
|
|
180
|
+
if (!P) {
|
|
181
|
+
P = !0;
|
|
182
|
+
for (let e of [...N].reverse()) try {
|
|
183
183
|
e();
|
|
184
184
|
} catch {}
|
|
185
185
|
}
|
|
186
186
|
};
|
|
187
|
-
|
|
187
|
+
N.push(() => w(M));
|
|
188
188
|
try {
|
|
189
|
-
let e = await
|
|
190
|
-
|
|
189
|
+
let e = await M.init(), t = e.audioStreams ?? [], i = t.some((e) => e.streamIndex === E) ? E : t[0]?.streamIndex ?? -1;
|
|
190
|
+
ee?.(t, i);
|
|
191
191
|
let o = m({
|
|
192
192
|
video: n,
|
|
193
193
|
canvas: r,
|
|
@@ -197,11 +197,11 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
197
197
|
defaultFontUrl: p,
|
|
198
198
|
onStreams: j
|
|
199
199
|
});
|
|
200
|
-
if (
|
|
200
|
+
if (N.push(() => o.destroy()), e.attachments?.length && o.pushAttachments(e.attachments), !e.info.output.videoMimeType) throw Error("The video codec in this file could not be identified");
|
|
201
201
|
let c = [e.info.output.videoMimeType, e.info.output.audioMimeType].filter(Boolean).join(","), l = `video/mp4; codecs="${c}"`;
|
|
202
202
|
if (!MediaSource.isTypeSupported(l)) throw Error(`This browser cannot play the codecs in this file: ${c}`);
|
|
203
203
|
let C = new MediaSource(), w = URL.createObjectURL(C);
|
|
204
|
-
|
|
204
|
+
N.push(() => URL.revokeObjectURL(w)), n.src = w;
|
|
205
205
|
let T = await new Promise((t, n) => {
|
|
206
206
|
let r = setTimeout(() => {
|
|
207
207
|
i(), n(/* @__PURE__ */ Error("The MediaSource never opened"));
|
|
@@ -220,14 +220,14 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
220
220
|
i(), n(/* @__PURE__ */ Error("The MediaSource closed before a SourceBuffer could be created"));
|
|
221
221
|
};
|
|
222
222
|
C.addEventListener("sourceopen", a, { once: !0 }), C.addEventListener("sourceclose", o, { once: !0 }), C.addEventListener("error", o, { once: !0 });
|
|
223
|
-
}), { appendBuffer:
|
|
224
|
-
await
|
|
225
|
-
let
|
|
223
|
+
}), { appendBuffer: I, unbufferRange: L, updateTimestampOffset: R, endOfStream: z } = s(T, C);
|
|
224
|
+
await I(e.data), e.subtitles?.length && o.pushFragments(e.subtitles), D?.();
|
|
225
|
+
let B = !1, V = !1, H = !1, U = 0, W = 0, G = null, K = 0, q = 0, J = !1, te = 0, Y = (e, t) => {
|
|
226
226
|
let n = e?.message === "Cancelled";
|
|
227
|
-
t && n || (console.error(e), !
|
|
227
|
+
t && n || (console.error(e), !J && (J = !0, O?.(n ? Error("Reading the video file failed", { cause: e }) : e)));
|
|
228
228
|
}, X = async (e = !1) => {
|
|
229
229
|
let t = n.currentTime, r = e ? v : h, i = e ? y : g;
|
|
230
|
-
for (let { start: e, end: n } of a(T)) e < t + r && await
|
|
230
|
+
for (let { start: e, end: n } of a(T)) e < t + r && await L(e, t + r), n > t + i && await L(t + i, n);
|
|
231
231
|
}, ne = () => {
|
|
232
232
|
let e = a(T);
|
|
233
233
|
if (!e.length) return !0;
|
|
@@ -240,65 +240,72 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
240
240
|
return a(T).find((t) => t.start <= e + S && e < t.end);
|
|
241
241
|
}, re = () => {
|
|
242
242
|
let e = Z();
|
|
243
|
-
return !!e && e.end >=
|
|
243
|
+
return !!e && e.end >= q - .1;
|
|
244
244
|
}, Q = () => {
|
|
245
245
|
let e = a(T).map((e) => e.end);
|
|
246
|
-
e.length && (
|
|
247
|
-
},
|
|
248
|
-
|
|
249
|
-
let t = ++
|
|
246
|
+
e.length && (q = Math.max(q, ...e));
|
|
247
|
+
}, ie = async (e) => {
|
|
248
|
+
V = !0, G = null, K = 0, te = e;
|
|
249
|
+
let t = ++W;
|
|
250
250
|
try {
|
|
251
|
-
let { data: n, pts: r, subtitles: i } = await
|
|
252
|
-
if (
|
|
253
|
-
n.byteLength && (await
|
|
251
|
+
let { data: n, pts: r, subtitles: i } = await M.seek(e);
|
|
252
|
+
if (P || t !== W || (i?.length && o.pushFragments(i), await R(r), P || t !== W)) return;
|
|
253
|
+
n.byteLength && (await I(n), Q());
|
|
254
254
|
} catch (e) {
|
|
255
|
-
Y(e,
|
|
255
|
+
Y(e, P || t !== W);
|
|
256
256
|
} finally {
|
|
257
|
-
t ===
|
|
257
|
+
t === W && (V = !1);
|
|
258
258
|
}
|
|
259
|
-
},
|
|
260
|
-
let e =
|
|
259
|
+
}, ae = async () => {
|
|
260
|
+
let e = G;
|
|
261
261
|
if (e) try {
|
|
262
|
-
await
|
|
262
|
+
await I(e), Q(), G === e && (G = null, K = 0);
|
|
263
263
|
} catch (t) {
|
|
264
|
-
if (
|
|
264
|
+
if (G !== e) return;
|
|
265
265
|
if (t?.name === "QuotaExceededError") {
|
|
266
266
|
let t = await X(!0).then(() => !0, () => !1);
|
|
267
|
-
if (
|
|
267
|
+
if (G !== e) return;
|
|
268
268
|
if (t) {
|
|
269
|
-
|
|
269
|
+
H = !1, await ie(Z()?.end ?? n.currentTime);
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
|
-
if (
|
|
274
|
-
throw
|
|
273
|
+
if (K += 1, K < b) return;
|
|
274
|
+
throw G = null, t;
|
|
275
275
|
}
|
|
276
|
-
},
|
|
277
|
-
if (
|
|
278
|
-
let e = ++
|
|
279
|
-
|
|
276
|
+
}, oe = async () => {
|
|
277
|
+
if (B || V || P || !G && (H || !ne())) return;
|
|
278
|
+
let e = ++U, t = W, n = () => P || e !== U || t !== W;
|
|
279
|
+
B = !0;
|
|
280
280
|
try {
|
|
281
|
-
if (!
|
|
282
|
-
let { data: e, subtitles: t, finished: r } = await
|
|
283
|
-
if (n() || (r && (
|
|
284
|
-
|
|
281
|
+
if (!G) {
|
|
282
|
+
let { data: e, subtitles: t, finished: r } = await M.read();
|
|
283
|
+
if (n() || (r && (H = !0), t?.length && o.pushFragments(t), !e.byteLength)) return;
|
|
284
|
+
G = e, K = 0;
|
|
285
285
|
}
|
|
286
|
-
await
|
|
286
|
+
await ae(), !n() && J && (J = !1, k?.());
|
|
287
287
|
} catch (e) {
|
|
288
288
|
Y(e, n());
|
|
289
289
|
} finally {
|
|
290
|
-
e ===
|
|
290
|
+
e === U && (B = !1);
|
|
291
291
|
}
|
|
292
|
-
},
|
|
292
|
+
}, se = (e) => e >= te && !!Z(), ce = () => {
|
|
293
293
|
let t = n.currentTime, r = e.info.input.duration || n.duration;
|
|
294
|
-
r > 0 && A?.(Math.min(Math.max(t / r, 0), 1)), !
|
|
294
|
+
r > 0 && A?.(Math.min(Math.max(t / r, 0), 1)), !se(t) && (H = !1, ie(t));
|
|
295
|
+
};
|
|
296
|
+
n.addEventListener("seeking", ce), N.push(() => n.removeEventListener("seeking", ce));
|
|
297
|
+
let $ = !1, le = () => {
|
|
298
|
+
if ($) return;
|
|
299
|
+
$ = !0;
|
|
300
|
+
let e = n.error;
|
|
301
|
+
Y(Error(`the media element failed: ${e?.message ?? "unknown"}`, { cause: e }), !1);
|
|
295
302
|
};
|
|
296
|
-
n.addEventListener("
|
|
297
|
-
let
|
|
298
|
-
X().catch(() => {}),
|
|
303
|
+
n.addEventListener("error", le), N.push(() => n.removeEventListener("error", le));
|
|
304
|
+
let ue = setInterval(() => {
|
|
305
|
+
$ || n.error || (X().catch(() => {}), oe().catch((e) => Y(e, !1)), H && !G && re() && C.readyState === "open" && z().catch(() => {}));
|
|
299
306
|
}, 100);
|
|
300
|
-
return
|
|
301
|
-
destroy:
|
|
307
|
+
return N.push(() => clearInterval(ue)), {
|
|
308
|
+
destroy: F,
|
|
302
309
|
selectSubtitleStream: (e) => o.selectStream(e),
|
|
303
310
|
indexes: e.indexes ?? [],
|
|
304
311
|
duration: e.info.input.duration,
|
|
@@ -306,9 +313,9 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
306
313
|
audioMimeType: e.info.output.audioMimeType
|
|
307
314
|
};
|
|
308
315
|
} catch (e) {
|
|
309
|
-
throw
|
|
316
|
+
throw F(), e;
|
|
310
317
|
}
|
|
311
|
-
}, E = 5, D = 500, O = 320, k = 1e6, A = 3, j = 1e4,
|
|
318
|
+
}, E = 5, D = 500, O = 320, k = 1e6, A = 3, j = 1e4, ee = async (e) => {
|
|
312
319
|
let { publicPath: n, workerUrl: r, length: i, read: a, onThumbnails: o, width: s = O } = e, c = await t({
|
|
313
320
|
publicPath: n,
|
|
314
321
|
workerUrl: r,
|
|
@@ -383,88 +390,119 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
383
390
|
} catch (e) {
|
|
384
391
|
throw w(c), e;
|
|
385
392
|
}
|
|
386
|
-
},
|
|
387
|
-
let { video: t, canvas: n,
|
|
393
|
+
}, M = 1280, N = 1920, P = 250, F = 100, I = () => typeof HTMLCanvasElement < "u" && "captureStream" in HTMLCanvasElement.prototype, L = () => typeof document < "u" && typeof HTMLVideoElement < "u" && typeof HTMLVideoElement.prototype.requestPictureInPicture == "function" && !!document.pictureInPictureEnabled, R = () => typeof HTMLVideoElement < "u" && "mozCaptureStream" in HTMLVideoElement.prototype, z = () => I() ? L() ? "window" : R() ? "burn-in" : null : null, B = (e) => {
|
|
394
|
+
let { video: t, canvas: n } = e, r = e.mode ?? z() ?? "window", i = e.maxWidth ?? (r === "burn-in" ? N : M), a, o, s, c = !1, l = !1, u = !1, d = !1, f, p = () => r === "burn-in" ? !!a : !!a && document.pictureInPictureElement === a.mirror, m = (e, r) => {
|
|
388
395
|
r.drawImage(t, 0, 0, e.width, e.height), n.width > 0 && n.height > 0 && r.drawImage(n, 0, 0, e.width, e.height);
|
|
389
|
-
}, f = () => {
|
|
390
|
-
i && d(i.composite, i.context);
|
|
391
|
-
}, p = "requestVideoFrameCallback" in t, m = () => {
|
|
392
|
-
f(), h();
|
|
393
396
|
}, h = () => {
|
|
394
|
-
|
|
395
|
-
}, g = () => {
|
|
396
|
-
|
|
397
|
-
}, _ = () => {
|
|
398
|
-
"mediaSession" in navigator && (navigator.mediaSession.playbackState = t.paused ? "paused" : "playing");
|
|
397
|
+
a && m(a.composite, a.context);
|
|
398
|
+
}, g = "requestVideoFrameCallback" in t, _ = () => {
|
|
399
|
+
h(), v();
|
|
399
400
|
}, v = () => {
|
|
400
|
-
|
|
401
|
+
d || !a || (o = g ? t.requestVideoFrameCallback(_) : requestAnimationFrame(_));
|
|
401
402
|
}, y = () => {
|
|
402
|
-
|
|
403
|
-
s = !1;
|
|
404
|
-
}));
|
|
403
|
+
o !== void 0 && (g ? t.cancelVideoFrameCallback(o) : cancelAnimationFrame(o)), s !== void 0 && clearInterval(s), o = void 0, s = void 0;
|
|
405
404
|
}, b = () => {
|
|
406
|
-
|
|
405
|
+
"mediaSession" in navigator && (navigator.mediaSession.playbackState = t.paused ? "paused" : "playing");
|
|
407
406
|
}, x = () => {
|
|
408
|
-
|
|
409
|
-
}, S =
|
|
407
|
+
c || l || !t.paused || t.play().catch(() => {});
|
|
408
|
+
}, S = () => {
|
|
409
|
+
c || l || (t.paused || t.pause(), r !== "burn-in" && (c = !0, a?.mirror.play().catch(() => {}).finally(() => {
|
|
410
|
+
c = !1;
|
|
411
|
+
})));
|
|
412
|
+
}, C = () => {
|
|
413
|
+
b(), a?.mirror.play().catch(() => {});
|
|
414
|
+
}, w = () => {
|
|
415
|
+
b(), r === "burn-in" && a?.mirror.pause();
|
|
416
|
+
}, T = () => {
|
|
417
|
+
if (r !== "burn-in" || !a || !t.paused || l) return;
|
|
418
|
+
l = !0;
|
|
419
|
+
let { mirror: e } = a;
|
|
420
|
+
h(), e.play().then(() => new Promise((e) => {
|
|
421
|
+
setTimeout(e, F);
|
|
422
|
+
})).catch(() => {}).finally(() => {
|
|
423
|
+
e.pause(), setTimeout(() => {
|
|
424
|
+
l = !1;
|
|
425
|
+
}, F);
|
|
426
|
+
});
|
|
427
|
+
}, E = [["play", () => {
|
|
410
428
|
t.play().catch(() => {});
|
|
411
|
-
}], ["pause", () => t.pause()]],
|
|
412
|
-
if ("mediaSession" in navigator) for (let [t, n] of
|
|
429
|
+
}], ["pause", () => t.pause()]], D = (e) => {
|
|
430
|
+
if ("mediaSession" in navigator) for (let [t, n] of E) try {
|
|
413
431
|
navigator.mediaSession.setActionHandler(t, e ? n : null);
|
|
414
432
|
} catch {}
|
|
415
|
-
},
|
|
416
|
-
if (
|
|
417
|
-
|
|
418
|
-
|
|
433
|
+
}, O = () => {
|
|
434
|
+
if (y(), D(!1), t.removeEventListener("play", C), t.removeEventListener("pause", w), t.removeEventListener("seeked", T), !a) {
|
|
435
|
+
f?.();
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
let { stream: e, mirror: n } = a;
|
|
439
|
+
n.removeEventListener("play", x), n.removeEventListener("pause", S), n.removeEventListener("leavepictureinpicture", k);
|
|
419
440
|
for (let t of e.getTracks()) t.stop();
|
|
420
|
-
n.remove(),
|
|
421
|
-
},
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
441
|
+
n.remove(), a = void 0, f?.();
|
|
442
|
+
}, k = () => O(), A = (e) => {
|
|
443
|
+
let r = t.style.opacity, i = n.style.display;
|
|
444
|
+
e.style.cssText = "position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#000;z-index:1", t.style.opacity = "0", n.style.display = "none", f = () => {
|
|
445
|
+
f = void 0, t.style.opacity = r, n.style.display = i;
|
|
446
|
+
};
|
|
447
|
+
}, j = async () => {
|
|
448
|
+
let n = Math.min(t.videoWidth || i, i), o = Math.round(n * ((t.videoHeight || 9) / (t.videoWidth || 16))), c = document.createElement("canvas");
|
|
449
|
+
c.width = n, c.height = o;
|
|
450
|
+
let l = c.getContext("2d");
|
|
451
|
+
if (!l) throw Error("the picture in picture composite has no 2d context");
|
|
452
|
+
let u = document.createElement("video");
|
|
453
|
+
u.muted = !0, u.playsInline = !0, r === "burn-in" ? A(u) : u.style.cssText = "position:fixed;width:1px;height:1px;opacity:0;pointer-events:none;left:-1px;top:-1px", m(c, l);
|
|
454
|
+
let f = {
|
|
455
|
+
composite: c,
|
|
456
|
+
context: l,
|
|
457
|
+
stream: c.captureStream(),
|
|
458
|
+
mirror: u
|
|
459
|
+
};
|
|
460
|
+
if (a = f, u.srcObject = f.stream, (e.container ?? t.parentElement ?? document.body).appendChild(u), v(), s = setInterval(() => {
|
|
461
|
+
t.paused && h();
|
|
462
|
+
}, P), u.play().catch(() => {}), u.readyState === 0 && await new Promise((e) => {
|
|
437
463
|
let t = () => {
|
|
438
464
|
clearTimeout(n), e();
|
|
439
465
|
}, n = setTimeout(t, 1e3);
|
|
440
|
-
|
|
441
|
-
}),
|
|
466
|
+
u.addEventListener("loadedmetadata", t, { once: !0 });
|
|
467
|
+
}), d || a !== f) {
|
|
468
|
+
u.remove();
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (u.addEventListener("play", x), u.addEventListener("pause", S), u.addEventListener("leavepictureinpicture", k), t.addEventListener("play", C), t.addEventListener("pause", w), t.addEventListener("seeked", T), D(!0), b(), r === "burn-in") {
|
|
472
|
+
t.paused && u.pause(), e.onBurnedInChange?.(!0);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
await u.requestPictureInPicture();
|
|
442
476
|
};
|
|
443
477
|
return {
|
|
444
478
|
toggle: async () => {
|
|
445
|
-
if (!(
|
|
446
|
-
|
|
447
|
-
await document.exitPictureInPicture().catch(() => {});
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
if (!F()) {
|
|
451
|
-
await E();
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
document.pictureInPictureElement && await document.exitPictureInPicture().catch(() => {}), c = !0;
|
|
479
|
+
if (!(d || u)) {
|
|
480
|
+
u = !0;
|
|
455
481
|
try {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
482
|
+
if (p()) {
|
|
483
|
+
if (r === "burn-in") {
|
|
484
|
+
O(), e.onBurnedInChange?.(!1);
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
await document.exitPictureInPicture().catch(() => {});
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
r !== "burn-in" && document.pictureInPictureElement && await document.exitPictureInPicture().catch(() => {});
|
|
491
|
+
try {
|
|
492
|
+
await j();
|
|
493
|
+
} catch (t) {
|
|
494
|
+
console.warn("subtitle compositing for picture in picture failed", t), O(), r === "burn-in" && e.onBurnedInChange?.(!1);
|
|
495
|
+
}
|
|
459
496
|
} finally {
|
|
460
|
-
|
|
497
|
+
u = !1;
|
|
461
498
|
}
|
|
462
499
|
}
|
|
463
500
|
},
|
|
501
|
+
mode: r,
|
|
464
502
|
destroy: () => {
|
|
465
|
-
|
|
503
|
+
d = !0, r !== "burn-in" && p() && document.exitPictureInPicture().catch(() => {}), O(), r === "burn-in" && e.onBurnedInChange?.(!1);
|
|
466
504
|
}
|
|
467
505
|
};
|
|
468
506
|
};
|
|
469
507
|
//#endregion
|
|
470
|
-
export {
|
|
508
|
+
export { T as a, m as c, C as i, a as l, z as n, w as o, ee as r, c as s, B as t, s as u };
|