@banou/media-player 0.10.3 → 0.10.4
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/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var B = {
|
|
|
20
20
|
selectAudioTrack: () => {},
|
|
21
21
|
hideUI: !1,
|
|
22
22
|
setHideUI: () => {},
|
|
23
|
+
hasMedia: !1,
|
|
23
24
|
togglePictureInPicture: null,
|
|
24
25
|
pictureInPictureMode: null,
|
|
25
26
|
burnedInSubtitles: !1,
|
|
@@ -48,7 +49,7 @@ var B = {
|
|
|
48
49
|
} catch {
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
51
|
-
}, G = (e) => e?.replace(/_/g, " ").trim() || void 0,
|
|
52
|
+
}, G = (e) => e?.replace(/_/g, " ").trim() || void 0, K = (e) => {
|
|
52
53
|
let t = e.map((e) => W(e.language) ?? G(e.title) ?? `Track ${e.streamIndex}`), n = t.reduce((e, t) => ({
|
|
53
54
|
...e,
|
|
54
55
|
[t]: (e[t] ?? 0) + 1
|
|
@@ -60,27 +61,27 @@ var B = {
|
|
|
60
61
|
label: (n[i] ?? 0) > 1 && a && a !== i ? `${i} (${a})` : i
|
|
61
62
|
};
|
|
62
63
|
});
|
|
63
|
-
},
|
|
64
|
+
}, q = (e) => K(e).map(({ track: e, label: t }) => ({
|
|
64
65
|
id: e.streamIndex,
|
|
65
66
|
label: t
|
|
66
|
-
})),
|
|
67
|
+
})), ee = [
|
|
67
68
|
0,
|
|
68
69
|
250,
|
|
69
70
|
1e3,
|
|
70
71
|
3e3,
|
|
71
72
|
1e4
|
|
72
|
-
],
|
|
73
|
+
], te = 6e4, ne = 500, re = 15e3, ie = (e) => e instanceof Error ? e.message : String(e), ae = (e) => {
|
|
73
74
|
let t = [], n = e?.cause;
|
|
74
75
|
for (let e = 0; n != null && e < 8; e++) {
|
|
75
76
|
if (typeof MediaError < "u" && n instanceof MediaError) {
|
|
76
77
|
t.push(`MediaError code ${n.code}${n.message ? `: ${n.message}` : ""}`);
|
|
77
78
|
break;
|
|
78
79
|
}
|
|
79
|
-
t.push(
|
|
80
|
+
t.push(ie(n)), n = n?.cause;
|
|
80
81
|
}
|
|
81
82
|
return t.length ? t.join("\n") : void 0;
|
|
82
|
-
},
|
|
83
|
-
let a = U(), { read: o, size: s, publicPath: c = "", libavWorkerUrl: l = "", jassubWorkerUrl: f = "", jassubWasmUrl: h = "", jassubLegacyWasmUrl: g, defaultFontUrl: _, bufferSize: v, autoplay: y = !1, chapters: b, seekPrepareBudgetMs: x =
|
|
83
|
+
}, oe = (e, t, r) => {
|
|
84
|
+
let a = U(), { read: o, size: s, publicPath: c = "", libavWorkerUrl: l = "", jassubWorkerUrl: f = "", jassubWasmUrl: h = "", jassubLegacyWasmUrl: g, defaultFontUrl: _, bufferSize: v, autoplay: y = !1, chapters: b, seekPrepareBudgetMs: x = ne } = r ?? {}, S = p(b);
|
|
84
85
|
S.current = b;
|
|
85
86
|
let [C, w] = m(void 0), [T, E] = m(0), D = p({
|
|
86
87
|
count: 0,
|
|
@@ -117,7 +118,7 @@ var B = {
|
|
|
117
118
|
a.setSourceState({ seekingTo: e });
|
|
118
119
|
let c = t.videoElement, l = () => {
|
|
119
120
|
c?.removeEventListener("seeked", l), clearTimeout(u), a.setSourceState({ seekingTo: void 0 });
|
|
120
|
-
}, u = setTimeout(l,
|
|
121
|
+
}, u = setTimeout(l, re);
|
|
121
122
|
c?.addEventListener("seeked", l);
|
|
122
123
|
let d = setTimeout(() => {
|
|
123
124
|
o = "deadline", s();
|
|
@@ -147,7 +148,7 @@ var B = {
|
|
|
147
148
|
ready: !1
|
|
148
149
|
});
|
|
149
150
|
let u = (t, n) => {
|
|
150
|
-
let r = Date.now(), i =
|
|
151
|
+
let r = Date.now(), i = ie(t), o = ae(t), s = a.playbackErrors, c = s[s.length - 1];
|
|
151
152
|
if (c && c.message === i && c.detail === o && c.recovered === n) {
|
|
152
153
|
let e = {
|
|
153
154
|
...c,
|
|
@@ -172,11 +173,11 @@ var B = {
|
|
|
172
173
|
let t = n(e);
|
|
173
174
|
if (u(e, t), t) {
|
|
174
175
|
let t = performance.now();
|
|
175
|
-
t - D.current.at >
|
|
176
|
+
t - D.current.at > te && (D.current = {
|
|
176
177
|
count: 0,
|
|
177
178
|
at: t
|
|
178
179
|
});
|
|
179
|
-
let n =
|
|
180
|
+
let n = ee[Math.min(D.current.count, ee.length - 1)];
|
|
180
181
|
D.current = {
|
|
181
182
|
count: D.current.count + 1,
|
|
182
183
|
at: t
|
|
@@ -213,13 +214,13 @@ var B = {
|
|
|
213
214
|
onSeek: (e) => N.current?.(e),
|
|
214
215
|
onSubtitleStreams: (e) => {
|
|
215
216
|
r || a.setSourceState({
|
|
216
|
-
subtitleTracks:
|
|
217
|
+
subtitleTracks: q(e),
|
|
217
218
|
...j.current ? {} : { selectedSubtitleTrack: e[0]?.streamIndex }
|
|
218
219
|
});
|
|
219
220
|
},
|
|
220
221
|
onAudioStreams: (e, t) => {
|
|
221
222
|
r || a.setSourceState({
|
|
222
|
-
audioTracks:
|
|
223
|
+
audioTracks: q(e),
|
|
223
224
|
selectedAudioTrack: t
|
|
224
225
|
});
|
|
225
226
|
}
|
|
@@ -259,13 +260,13 @@ var B = {
|
|
|
259
260
|
y,
|
|
260
261
|
T
|
|
261
262
|
]);
|
|
262
|
-
},
|
|
263
|
+
}, se = 5e3, ce = 6e4, le = ({ publicPath: e, workerUrl: t, length: n, read: i, downloadedRanges: a }) => {
|
|
263
264
|
let [o, s] = m([]), c = p(null), l = p(i);
|
|
264
265
|
l.current = i;
|
|
265
266
|
let h = f(() => a?.map(({ startByteOffset: e, endByteOffset: t }) => [e, t]), [a?.map(({ startByteOffset: e, endByteOffset: t }) => `${e}-${t}`).join(",")]), g = p(h);
|
|
266
267
|
return g.current = h, d(() => {
|
|
267
268
|
if (!n || !i || !e || !t) return;
|
|
268
|
-
let a = !1, o = null, u, d =
|
|
269
|
+
let a = !1, o = null, u, d = se, f = () => {
|
|
269
270
|
r({
|
|
270
271
|
publicPath: e,
|
|
271
272
|
workerUrl: t,
|
|
@@ -281,7 +282,7 @@ var B = {
|
|
|
281
282
|
}
|
|
282
283
|
o = e, c.current = e, e.update(g.current);
|
|
283
284
|
}, () => {
|
|
284
|
-
a || (u = setTimeout(f, d), d = Math.min(d * 2,
|
|
285
|
+
a || (u = setTimeout(f, d), d = Math.min(d * 2, ce));
|
|
285
286
|
});
|
|
286
287
|
};
|
|
287
288
|
return f(), () => {
|
|
@@ -299,7 +300,7 @@ var B = {
|
|
|
299
300
|
c.current?.prioritize(e);
|
|
300
301
|
}, [])
|
|
301
302
|
};
|
|
302
|
-
},
|
|
303
|
+
}, ue = (e, n) => {
|
|
303
304
|
let r = p(null), [i, o] = m(!1), [s] = m(() => t());
|
|
304
305
|
d(() => {
|
|
305
306
|
if (!e || !n || !s) return;
|
|
@@ -327,7 +328,7 @@ var B = {
|
|
|
327
328
|
mode: s,
|
|
328
329
|
burnedIn: i
|
|
329
330
|
};
|
|
330
|
-
},
|
|
331
|
+
}, J = {
|
|
331
332
|
headings: {
|
|
332
333
|
large: "\n font-weight: 600;\n font-size: calc(2.8 * var(--mp-unit));\n line-height: calc(3.4 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(3.4 * var(--mp-unit));\n line-height: calc(4.1 * var(--mp-unit));\n }\n ",
|
|
333
334
|
medium: "\n font-weight: 600;\n font-size: calc(2.4 * var(--mp-unit));\n line-height: calc(2.9 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(2.8 * var(--mp-unit));\n line-height: calc(3.4 * var(--mp-unit));\n }\n ",
|
|
@@ -354,7 +355,7 @@ var B = {
|
|
|
354
355
|
medium: "\n font-weight: 500;\n font-size: calc(0.8 * var(--mp-unit));\n line-height: calc(1.1 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(1 * var(--mp-unit));\n line-height: calc(1.4 * var(--mp-unit));\n }\n ",
|
|
355
356
|
regular: "\n font-weight: 400;\n font-size: calc(0.8 * var(--mp-unit));\n line-height: calc(1.1 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(1 * var(--mp-unit));\n line-height: calc(1.4 * var(--mp-unit));\n }\n "
|
|
356
357
|
}
|
|
357
|
-
},
|
|
358
|
+
}, de = h`
|
|
358
359
|
display: flex;
|
|
359
360
|
justify-content: center;
|
|
360
361
|
align-items: center;
|
|
@@ -367,7 +368,7 @@ var B = {
|
|
|
367
368
|
margin: auto;
|
|
368
369
|
pointer-events: none;
|
|
369
370
|
}
|
|
370
|
-
`,
|
|
371
|
+
`, fe = h`
|
|
371
372
|
position: absolute;
|
|
372
373
|
top: 0;
|
|
373
374
|
left: 0;
|
|
@@ -375,7 +376,7 @@ var B = {
|
|
|
375
376
|
padding: calc(1.2 * var(--mp-unit)) calc(1.6 * var(--mp-unit));
|
|
376
377
|
/* clears a notch once the player is fullscreen; resolves to zero everywhere else */
|
|
377
378
|
padding-top: calc(calc(1.2 * var(--mp-unit)) + env(safe-area-inset-top, 0px));
|
|
378
|
-
${
|
|
379
|
+
${J.headings.small}
|
|
379
380
|
color: white;
|
|
380
381
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
381
382
|
z-index: 2;
|
|
@@ -396,7 +397,7 @@ var B = {
|
|
|
396
397
|
|
|
397
398
|
background: linear-gradient(180deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.3) 30%, rgba(0,0,0,0.2) 60%, rgba(0,0,0,0.1) 80%, transparent 100%);
|
|
398
399
|
transition: opacity 0.1s cubic-bezier(.4,0,1,1);
|
|
399
|
-
`,
|
|
400
|
+
`, pe = h`
|
|
400
401
|
position: absolute;
|
|
401
402
|
inset: 0;
|
|
402
403
|
z-index: 2;
|
|
@@ -416,40 +417,40 @@ var B = {
|
|
|
416
417
|
to { transform: rotate(360deg); }
|
|
417
418
|
`} 0.8s linear infinite;
|
|
418
419
|
}
|
|
419
|
-
`,
|
|
420
|
+
`, me = h`
|
|
420
421
|
position: absolute;
|
|
421
422
|
inset: auto 0 20%;
|
|
422
423
|
z-index: 3;
|
|
423
424
|
padding: 0 calc(2 * var(--mp-unit));
|
|
424
425
|
text-align: center;
|
|
425
426
|
color: #fff;
|
|
426
|
-
${
|
|
427
|
+
${J.bLarge.regular}
|
|
427
428
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
428
429
|
pointer-events: none;
|
|
429
|
-
`,
|
|
430
|
+
`, he = (e) => e instanceof Error ? e.message : typeof e == "string" ? e : "Playback failed", ge = ({ onSubtitleRef: e }) => {
|
|
430
431
|
let t = U((e) => e.title), n = U((e) => e.hideUI), r = U((e) => e.playbackError), i = U((e) => e.ready), a = U((e) => e.size), o = U((e) => e.waiting), s = U((e) => e.seekingTo);
|
|
431
432
|
return /* @__PURE__ */ w(S, { children: [
|
|
432
433
|
t ? /* @__PURE__ */ C("div", {
|
|
433
434
|
className: "title",
|
|
434
|
-
css:
|
|
435
|
+
css: fe,
|
|
435
436
|
style: { ...n ? {
|
|
436
437
|
opacity: "0",
|
|
437
438
|
pointerEvents: "none"
|
|
438
439
|
} : {} },
|
|
439
440
|
children: t
|
|
440
441
|
}) : void 0,
|
|
441
|
-
((a ? !i : o) || s !== void 0) && !r ? /* @__PURE__ */ C("div", { css:
|
|
442
|
+
((a ? !i : o) || s !== void 0) && !r ? /* @__PURE__ */ C("div", { css: pe }) : void 0,
|
|
442
443
|
r ? /* @__PURE__ */ C("div", {
|
|
443
|
-
css:
|
|
444
|
-
children:
|
|
444
|
+
css: me,
|
|
445
|
+
children: he(r)
|
|
445
446
|
}) : void 0,
|
|
446
447
|
/* @__PURE__ */ C("div", {
|
|
447
448
|
className: "subtitles",
|
|
448
449
|
ref: e,
|
|
449
|
-
css:
|
|
450
|
+
css: de
|
|
450
451
|
})
|
|
451
452
|
] });
|
|
452
|
-
},
|
|
453
|
+
}, _e = 1e-4, ve = 1, ye = (e) => Math.max(_e, Math.min(ve, e)) ** 2, be = (e) => Math.max(_e, Math.min(ve, e)) ** (ve / 2), Y = (e) => {
|
|
453
454
|
if (e === void 0) return "0:00";
|
|
454
455
|
let t = Math.floor(e / 3600), n = Math.floor(e % 3600 / 60), r = Math.floor(e % 60);
|
|
455
456
|
return t > 0 ? `${t}:${n < 10 ? "0" : ""}${n}:${r < 10 ? "0" : ""}${r}` : `${n}:${r < 10 ? "0" : ""}${r}`;
|
|
@@ -485,7 +486,7 @@ var B = {
|
|
|
485
486
|
z-index: 3;
|
|
486
487
|
|
|
487
488
|
* {
|
|
488
|
-
${
|
|
489
|
+
${J.bMedium.regular}
|
|
489
490
|
}
|
|
490
491
|
|
|
491
492
|
${e === "sm" && h`
|
|
@@ -773,7 +774,7 @@ var B = {
|
|
|
773
774
|
box-shadow: 0 0 calc(1 * var(--mp-unit)) rgba(0, 0, 0, .5);
|
|
774
775
|
|
|
775
776
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
776
|
-
${
|
|
777
|
+
${J.bMedium.bold}
|
|
777
778
|
|
|
778
779
|
gap: calc(.6 * var(--mp-unit));
|
|
779
780
|
|
|
@@ -989,7 +990,7 @@ var B = {
|
|
|
989
990
|
V
|
|
990
991
|
]), W = f(() => V >= 0 ? je(z, (e) => e === V) : void 0, [z, V]), G = f(() => {
|
|
991
992
|
if (y !== void 0) return u.find(({ start: e, end: t }) => e <= y && y < t);
|
|
992
|
-
}, [u, y]),
|
|
993
|
+
}, [u, y]), K = f(() => {
|
|
993
994
|
if (y) {
|
|
994
995
|
if (c) return c(y);
|
|
995
996
|
if (s.length) return s.find(({ startTime: e, endTime: t }) => e <= y && y < t);
|
|
@@ -998,7 +999,7 @@ var B = {
|
|
|
998
999
|
s,
|
|
999
1000
|
c,
|
|
1000
1001
|
y
|
|
1001
|
-
]),
|
|
1002
|
+
]), q = (e, t) => /* @__PURE__ */ w("div", {
|
|
1002
1003
|
className: e ? `track ${e}` : "track",
|
|
1003
1004
|
style: t ? { maskImage: t } : void 0,
|
|
1004
1005
|
children: [
|
|
@@ -1027,7 +1028,7 @@ var B = {
|
|
|
1027
1028
|
onMouseMove: P,
|
|
1028
1029
|
onMouseOut: F,
|
|
1029
1030
|
children: [
|
|
1030
|
-
|
|
1031
|
+
q(void 0, H),
|
|
1031
1032
|
y ? /* @__PURE__ */ w("div", {
|
|
1032
1033
|
className: "cursor-time",
|
|
1033
1034
|
style: {
|
|
@@ -1044,7 +1045,7 @@ var B = {
|
|
|
1044
1045
|
}) : void 0,
|
|
1045
1046
|
/* @__PURE__ */ C("div", { className: "progress" }),
|
|
1046
1047
|
/* @__PURE__ */ C("div", { className: "hover" }),
|
|
1047
|
-
W ?
|
|
1048
|
+
W ? q("focus", W) : void 0,
|
|
1048
1049
|
/* @__PURE__ */ C("div", { className: "scrubber" }),
|
|
1049
1050
|
/* @__PURE__ */ C("div", {
|
|
1050
1051
|
className: "padding",
|
|
@@ -1056,7 +1057,7 @@ var B = {
|
|
|
1056
1057
|
/* @__PURE__ */ C("div", {
|
|
1057
1058
|
className: "thumbnail",
|
|
1058
1059
|
style: { left: `clamp(var(--thumbnail-half), ${I(y ?? 1)}%, calc(100% - var(--thumbnail-half)))` },
|
|
1059
|
-
children:
|
|
1060
|
+
children: K?.url ? /* @__PURE__ */ C("img", { src: K.url }) : void 0
|
|
1060
1061
|
})
|
|
1061
1062
|
]
|
|
1062
1063
|
});
|
|
@@ -1170,7 +1171,7 @@ var B = {
|
|
|
1170
1171
|
|
|
1171
1172
|
border-radius: 8px;
|
|
1172
1173
|
background-color: rgba(28,28,28,0.95);
|
|
1173
|
-
${
|
|
1174
|
+
${J.bMedium.regular}
|
|
1174
1175
|
|
|
1175
1176
|
z-index: 4;
|
|
1176
1177
|
|
|
@@ -1213,7 +1214,7 @@ var B = {
|
|
|
1213
1214
|
|
|
1214
1215
|
.secondary {
|
|
1215
1216
|
color: #eee;
|
|
1216
|
-
${
|
|
1217
|
+
${J.bSmall.regular}
|
|
1217
1218
|
}
|
|
1218
1219
|
}
|
|
1219
1220
|
}
|
|
@@ -1255,7 +1256,7 @@ var B = {
|
|
|
1255
1256
|
.failed {
|
|
1256
1257
|
border-bottom: 1px solid #4D4D4E;
|
|
1257
1258
|
color: #f66;
|
|
1258
|
-
${
|
|
1259
|
+
${J.bSmall.regular}
|
|
1259
1260
|
}
|
|
1260
1261
|
}
|
|
1261
1262
|
`, it = ({ title: e, tracks: t, selected: n, onSelect: r, onBack: i, offLabel: a, pending: o, failed: s }) => {
|
|
@@ -1370,7 +1371,7 @@ ${rt}
|
|
|
1370
1371
|
|
|
1371
1372
|
color: #fff;
|
|
1372
1373
|
cursor: pointer;
|
|
1373
|
-
${
|
|
1374
|
+
${J.bSmall.regular}
|
|
1374
1375
|
|
|
1375
1376
|
&:hover {
|
|
1376
1377
|
background-color: rgba(255,255,255,.1);
|
|
@@ -1391,7 +1392,7 @@ ${rt}
|
|
|
1391
1392
|
|
|
1392
1393
|
.when {
|
|
1393
1394
|
color: #bbb;
|
|
1394
|
-
${
|
|
1395
|
+
${J.bSmall.regular}
|
|
1395
1396
|
|
|
1396
1397
|
/* the one part of the line worth scanning for, so it is the one part at full brightness */
|
|
1397
1398
|
.count {
|
|
@@ -1410,7 +1411,7 @@ ${rt}
|
|
|
1410
1411
|
color: #ddd;
|
|
1411
1412
|
overflow-wrap: anywhere;
|
|
1412
1413
|
white-space: pre-wrap;
|
|
1413
|
-
${
|
|
1414
|
+
${J.bSmall.regular}
|
|
1414
1415
|
}
|
|
1415
1416
|
}
|
|
1416
1417
|
}
|
|
@@ -1874,7 +1875,7 @@ ${rt}
|
|
|
1874
1875
|
border-radius: 4px;
|
|
1875
1876
|
|
|
1876
1877
|
.volume-value {
|
|
1877
|
-
${
|
|
1878
|
+
${J.bMedium.regular};
|
|
1878
1879
|
color: #ffffff;
|
|
1879
1880
|
}
|
|
1880
1881
|
}
|
|
@@ -2060,7 +2061,7 @@ ${rt}
|
|
|
2060
2061
|
|
|
2061
2062
|
.left {
|
|
2062
2063
|
.time {
|
|
2063
|
-
${
|
|
2064
|
+
${J.bMedium.regular}
|
|
2064
2065
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
2065
2066
|
}
|
|
2066
2067
|
}
|
|
@@ -2242,12 +2243,12 @@ ${rt}
|
|
|
2242
2243
|
}
|
|
2243
2244
|
|
|
2244
2245
|
.title {
|
|
2245
|
-
${
|
|
2246
|
+
${J.bMedium.bold}
|
|
2246
2247
|
color: #fff;
|
|
2247
2248
|
}
|
|
2248
2249
|
|
|
2249
2250
|
.body {
|
|
2250
|
-
${
|
|
2251
|
+
${J.bSmall.regular}
|
|
2251
2252
|
color: rgba(255, 255, 255, 0.75);
|
|
2252
2253
|
}
|
|
2253
2254
|
|
|
@@ -2310,7 +2311,7 @@ ${rt}
|
|
|
2310
2311
|
pointer-events: auto;
|
|
2311
2312
|
cursor: pointer;
|
|
2312
2313
|
|
|
2313
|
-
${
|
|
2314
|
+
${J.bMedium.bold}
|
|
2314
2315
|
color: #fff;
|
|
2315
2316
|
padding: calc(1 * var(--mp-unit)) calc(1.8 * var(--mp-unit));
|
|
2316
2317
|
border: 1px solid rgba(255, 255, 255, .55);
|
|
@@ -2447,49 +2448,53 @@ ${rt}
|
|
|
2447
2448
|
item: e
|
|
2448
2449
|
}];
|
|
2449
2450
|
}), Bt = ({ ref: e, onVideoRef: t, onSubtitleRef: n, overlay: r, controls: i, children: a }) => {
|
|
2450
|
-
let o = U(), s = U((e) => e.hideUI), c = U((e) => e.setHideUI), l = p(void 0),
|
|
2451
|
+
let o = U(), s = U((e) => e.hideUI), c = U((e) => e.setHideUI), l = U((e) => e.hasMedia), u = p(void 0), f = p("mouse"), m = p({
|
|
2451
2452
|
x: -1,
|
|
2452
2453
|
y: -1
|
|
2453
|
-
}),
|
|
2454
|
-
d(() => () => clearTimeout(
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2454
|
+
}), h = p(null);
|
|
2455
|
+
d(() => () => clearTimeout(u.current), []), d(() => {
|
|
2456
|
+
l || (clearTimeout(u.current), c(!1));
|
|
2457
|
+
}, [l, c]);
|
|
2458
|
+
let g = () => {
|
|
2459
|
+
l && c(!0);
|
|
2460
|
+
}, _ = (t) => {
|
|
2461
|
+
h.current = t, typeof e == "function" ? e(t) : e && (e.current = t);
|
|
2462
|
+
}, v = () => {
|
|
2463
|
+
if (f.current !== "mouse") return !1;
|
|
2464
|
+
let { x: e, y: t } = m.current;
|
|
2465
|
+
if (!h.current || e < 0) return !1;
|
|
2461
2466
|
let n = document.elementFromPoint(e, t);
|
|
2462
|
-
return !!n &&
|
|
2463
|
-
},
|
|
2464
|
-
if (
|
|
2465
|
-
|
|
2467
|
+
return !!n && h.current.contains(n) && !n.closest(".video");
|
|
2468
|
+
}, y = () => {
|
|
2469
|
+
if (v()) {
|
|
2470
|
+
u.current = setTimeout(y, It);
|
|
2466
2471
|
return;
|
|
2467
2472
|
}
|
|
2468
|
-
|
|
2469
|
-
},
|
|
2470
|
-
c(!1), clearTimeout(
|
|
2473
|
+
g();
|
|
2474
|
+
}, b = () => {
|
|
2475
|
+
c(!1), clearTimeout(u.current), u.current = setTimeout(y, It);
|
|
2471
2476
|
};
|
|
2472
2477
|
return /* @__PURE__ */ w("div", {
|
|
2473
2478
|
css: Rt,
|
|
2474
|
-
ref:
|
|
2479
|
+
ref: _,
|
|
2475
2480
|
onPointerMove: (e) => {
|
|
2476
|
-
|
|
2481
|
+
f.current = e.pointerType, e.pointerType === "mouse" && (m.current = {
|
|
2477
2482
|
x: e.clientX,
|
|
2478
2483
|
y: e.clientY
|
|
2479
|
-
},
|
|
2484
|
+
}, b());
|
|
2480
2485
|
},
|
|
2481
2486
|
onPointerDown: (e) => {
|
|
2482
|
-
|
|
2487
|
+
f.current = e.pointerType;
|
|
2483
2488
|
},
|
|
2484
2489
|
onMouseOut: (e) => {
|
|
2485
2490
|
let t = e.relatedTarget;
|
|
2486
2491
|
if (t && e.currentTarget.contains(t)) return;
|
|
2487
2492
|
let { left: n, right: r, top: i, bottom: a } = e.currentTarget.getBoundingClientRect();
|
|
2488
|
-
e.clientX >= n && e.clientX < r && e.clientY >= i && e.clientY < a || (clearTimeout(
|
|
2493
|
+
e.clientX >= n && e.clientX < r && e.clientY >= i && e.clientY < a || (clearTimeout(u.current), g());
|
|
2489
2494
|
},
|
|
2490
2495
|
className: s ? "hide" : "",
|
|
2491
2496
|
children: [
|
|
2492
|
-
/* @__PURE__ */ C(
|
|
2497
|
+
/* @__PURE__ */ C(ge, { onSubtitleRef: n }),
|
|
2493
2498
|
zt(r).map(({ key: e, item: t }) => /* @__PURE__ */ C("div", {
|
|
2494
2499
|
css: Lt,
|
|
2495
2500
|
style: { ...s ? {
|
|
@@ -2505,11 +2510,11 @@ ${rt}
|
|
|
2505
2510
|
/* @__PURE__ */ w("div", {
|
|
2506
2511
|
className: "video",
|
|
2507
2512
|
onClick: () => {
|
|
2508
|
-
if (
|
|
2513
|
+
if (f.current === "mouse") {
|
|
2509
2514
|
o.togglePaused();
|
|
2510
2515
|
return;
|
|
2511
2516
|
}
|
|
2512
|
-
s ?
|
|
2517
|
+
s ? b() : (clearTimeout(u.current), g());
|
|
2513
2518
|
},
|
|
2514
2519
|
children: [t ? /* @__PURE__ */ C("video", {
|
|
2515
2520
|
ref: t,
|
|
@@ -2538,31 +2543,33 @@ ${rt}
|
|
|
2538
2543
|
k,
|
|
2539
2544
|
A,
|
|
2540
2545
|
j
|
|
2541
|
-
]),
|
|
2542
|
-
let { thumbnails: M, requestThumbnail: N } =
|
|
2546
|
+
]), oe(b, S, r);
|
|
2547
|
+
let { thumbnails: M, requestThumbnail: N } = le({
|
|
2543
2548
|
publicPath: c,
|
|
2544
2549
|
workerUrl: l,
|
|
2545
2550
|
length: h === !1 ? void 0 : o,
|
|
2546
2551
|
read: f ?? u,
|
|
2547
2552
|
downloadedRanges: s
|
|
2548
|
-
}), P = n?.thumbnails?.all ?? M, { toggle: F, mode: I, burnedIn: L } =
|
|
2553
|
+
}), P = n?.thumbnails?.all ?? M, { toggle: F, mode: I, burnedIn: L } = ue(b, S), R = U((e) => e.setSourceState), z = n ? !!n.media : o !== void 0;
|
|
2549
2554
|
d(() => {
|
|
2550
2555
|
R({
|
|
2551
2556
|
title: i,
|
|
2552
2557
|
size: o,
|
|
2553
|
-
downloadedRanges: s
|
|
2558
|
+
downloadedRanges: s,
|
|
2559
|
+
hasMedia: z
|
|
2554
2560
|
});
|
|
2555
2561
|
}, [
|
|
2556
2562
|
R,
|
|
2557
2563
|
i,
|
|
2558
2564
|
o,
|
|
2559
|
-
s
|
|
2565
|
+
s,
|
|
2566
|
+
z
|
|
2560
2567
|
]);
|
|
2561
|
-
let
|
|
2568
|
+
let B = n?.thumbnails?.at;
|
|
2562
2569
|
d(() => {
|
|
2563
2570
|
R({
|
|
2564
2571
|
thumbnails: P,
|
|
2565
|
-
thumbnailAt:
|
|
2572
|
+
thumbnailAt: B,
|
|
2566
2573
|
requestThumbnail: N,
|
|
2567
2574
|
togglePictureInPicture: F,
|
|
2568
2575
|
pictureInPictureMode: I,
|
|
@@ -2571,35 +2578,35 @@ ${rt}
|
|
|
2571
2578
|
}, [
|
|
2572
2579
|
R,
|
|
2573
2580
|
P,
|
|
2574
|
-
|
|
2581
|
+
B,
|
|
2575
2582
|
N,
|
|
2576
2583
|
F,
|
|
2577
2584
|
I,
|
|
2578
2585
|
L
|
|
2579
2586
|
]);
|
|
2580
|
-
let
|
|
2587
|
+
let V = n?.subtitles?.selection, H = n?.audioTracks?.selection;
|
|
2581
2588
|
return d(() => {
|
|
2582
|
-
|
|
2583
|
-
subtitleTracks:
|
|
2589
|
+
V && R({
|
|
2590
|
+
subtitleTracks: V.options.map(({ id: e, label: t, disabled: n }) => ({
|
|
2584
2591
|
id: e,
|
|
2585
2592
|
label: t,
|
|
2586
2593
|
disabled: n
|
|
2587
2594
|
})),
|
|
2588
|
-
selectedSubtitleTrack:
|
|
2589
|
-
selectSubtitleTrack: (e) =>
|
|
2590
|
-
subtitleOffLabel:
|
|
2595
|
+
selectedSubtitleTrack: V.selectedId ?? void 0,
|
|
2596
|
+
selectSubtitleTrack: (e) => V.select(e == null ? null : String(e)),
|
|
2597
|
+
subtitleOffLabel: V.offLabel
|
|
2591
2598
|
});
|
|
2592
|
-
}, [R,
|
|
2593
|
-
|
|
2594
|
-
audioTracks:
|
|
2599
|
+
}, [R, V]), d(() => {
|
|
2600
|
+
H && R({
|
|
2601
|
+
audioTracks: H.options.map(({ id: e, label: t, disabled: n }) => ({
|
|
2595
2602
|
id: e,
|
|
2596
2603
|
label: t,
|
|
2597
2604
|
disabled: n
|
|
2598
2605
|
})),
|
|
2599
|
-
selectedAudioTrack:
|
|
2600
|
-
selectAudioTrack: (e) =>
|
|
2606
|
+
selectedAudioTrack: H.selectedId ?? void 0,
|
|
2607
|
+
selectAudioTrack: (e) => H.select(String(e))
|
|
2601
2608
|
});
|
|
2602
|
-
}, [R,
|
|
2609
|
+
}, [R, H]), d(() => {
|
|
2603
2610
|
a && R({ chapters: a });
|
|
2604
2611
|
}, [R, a]), /* @__PURE__ */ C(Bt, {
|
|
2605
2612
|
ref: _,
|
|
@@ -2726,4 +2733,4 @@ ${rt}
|
|
|
2726
2733
|
throw Error(`Unknown source type: ${e}`);
|
|
2727
2734
|
};
|
|
2728
2735
|
//#endregion
|
|
2729
|
-
export { Ut as MediaPlayer, Ut as default, H as Player, e as SUBTITLES_OFF, a as createPictureInPicture, o as createSubtitleRenderer, r as createThumbnailGenerator, Yt as inputToRemuxerInput, Gt as isDelegatedTracks, Wt as isExternalThumbnails, V as sourceFeature, i as startPlayback,
|
|
2736
|
+
export { Ut as MediaPlayer, Ut as default, H as Player, e as SUBTITLES_OFF, a as createPictureInPicture, o as createSubtitleRenderer, r as createThumbnailGenerator, Yt as inputToRemuxerInput, Gt as isDelegatedTracks, Wt as isExternalThumbnails, V as sourceFeature, i as startPlayback, ue as usePictureInPicture, U as usePlayer, le as useSeekThumbnails };
|
package/dist/react/player.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare const Player: import("@videojs/react").CreatePlayerResult<import(
|
|
|
16
16
|
selectAudioTrack: (id: string | number) => void | Promise<void>;
|
|
17
17
|
hideUI: boolean;
|
|
18
18
|
setHideUI: (hide: boolean) => void;
|
|
19
|
+
hasMedia: boolean;
|
|
19
20
|
togglePictureInPicture: (() => void) | null;
|
|
20
21
|
pictureInPictureMode: import("../engine").PictureInPictureMode | null;
|
|
21
22
|
burnedInSubtitles: boolean;
|
|
@@ -116,6 +116,19 @@ export type SourceState = {
|
|
|
116
116
|
/** Chrome auto-hide. True means the controls, title and cursor are hidden. */
|
|
117
117
|
hideUI: boolean;
|
|
118
118
|
setHideUI: (hide: boolean) => void;
|
|
119
|
+
/**
|
|
120
|
+
* Whether there is anything loaded to play at all.
|
|
121
|
+
*
|
|
122
|
+
* Not the same question as `ready`, which is about a source that HAS been handed over and is still
|
|
123
|
+
* booting. This one separates that from having been given nothing, and the chrome needs the
|
|
124
|
+
* difference: idle-hiding with no media leaves a black rectangle with no controls, no title and no
|
|
125
|
+
* cursor, and no way back, since the only thing that reveals the chrome again is a pointer move over
|
|
126
|
+
* a player the viewer has no reason to think is there.
|
|
127
|
+
*
|
|
128
|
+
* Written by the React layer, which is the only place both arms are visible: bytes for a local
|
|
129
|
+
* source, an element for a media this player does not own.
|
|
130
|
+
*/
|
|
131
|
+
hasMedia: boolean;
|
|
119
132
|
/**
|
|
120
133
|
* Owned here, not by `pip`: that watches the media element, and the window holds a mirror.
|
|
121
134
|
*
|
|
@@ -234,6 +247,19 @@ export declare const sourceFeature: import("@videojs/react").PlayerFeature<{
|
|
|
234
247
|
/** Chrome auto-hide. True means the controls, title and cursor are hidden. */
|
|
235
248
|
hideUI: boolean;
|
|
236
249
|
setHideUI: (hide: boolean) => void;
|
|
250
|
+
/**
|
|
251
|
+
* Whether there is anything loaded to play at all.
|
|
252
|
+
*
|
|
253
|
+
* Not the same question as `ready`, which is about a source that HAS been handed over and is still
|
|
254
|
+
* booting. This one separates that from having been given nothing, and the chrome needs the
|
|
255
|
+
* difference: idle-hiding with no media leaves a black rectangle with no controls, no title and no
|
|
256
|
+
* cursor, and no way back, since the only thing that reveals the chrome again is a pointer move over
|
|
257
|
+
* a player the viewer has no reason to think is there.
|
|
258
|
+
*
|
|
259
|
+
* Written by the React layer, which is the only place both arms are visible: bytes for a local
|
|
260
|
+
* source, an element for a media this player does not own.
|
|
261
|
+
*/
|
|
262
|
+
hasMedia: boolean;
|
|
237
263
|
/**
|
|
238
264
|
* Owned here, not by `pip`: that watches the media element, and the window holds a mirror.
|
|
239
265
|
*
|
package/package.json
CHANGED
|
@@ -119,6 +119,7 @@ export const Chrome = ({ ref, onVideoRef, onSubtitleRef, overlay, controls, chil
|
|
|
119
119
|
const player = usePlayer()
|
|
120
120
|
const hideUI = usePlayer((state) => state.hideUI)
|
|
121
121
|
const setHideUI = usePlayer((state) => state.setHideUI)
|
|
122
|
+
const hasMedia = usePlayer((state) => state.hasMedia)
|
|
122
123
|
const autoHide = useRef<ReturnType<typeof setTimeout>>(undefined)
|
|
123
124
|
// a tap and a click mean different things, so the last pointer kind is remembered
|
|
124
125
|
const lastPointerType = useRef<string>('mouse')
|
|
@@ -128,6 +129,27 @@ export const Chrome = ({ ref, onVideoRef, onSubtitleRef, overlay, controls, chil
|
|
|
128
129
|
|
|
129
130
|
useEffect(() => () => clearTimeout(autoHide.current), [])
|
|
130
131
|
|
|
132
|
+
/*
|
|
133
|
+
* With nothing loaded the chrome never hides, and anything already hidden comes back.
|
|
134
|
+
*
|
|
135
|
+
* Hiding is only ever reversed by a pointer move over the player, which is a fair bet while a video
|
|
136
|
+
* is playing and a bad one when the box is empty: three seconds after mount the controls, the title
|
|
137
|
+
* and the cursor all go, leaving a black rectangle that gives the viewer no reason to think there is
|
|
138
|
+
* a player there to wave at. The effect covers the media going AWAY, which the guard below cannot:
|
|
139
|
+
* its timer may already be in flight, holding a `hasMedia` that was true when it was scheduled.
|
|
140
|
+
*/
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (hasMedia) return
|
|
143
|
+
clearTimeout(autoHide.current)
|
|
144
|
+
setHideUI(false)
|
|
145
|
+
}, [hasMedia, setHideUI])
|
|
146
|
+
|
|
147
|
+
/** The single door to hiding, so no path can bypass the empty-player case. */
|
|
148
|
+
const hide = () => {
|
|
149
|
+
if (!hasMedia) return
|
|
150
|
+
setHideUI(true)
|
|
151
|
+
}
|
|
152
|
+
|
|
131
153
|
// The caller's ref still gets the element: video.js attaches the fullscreen container through it,
|
|
132
154
|
// and this needs the same node to hit test against.
|
|
133
155
|
const setRoot = (element: HTMLDivElement | null) => {
|
|
@@ -165,7 +187,7 @@ export const Chrome = ({ ref, onVideoRef, onSubtitleRef, overlay, controls, chil
|
|
|
165
187
|
autoHide.current = setTimeout(hideUnlessTheMouseIsOnAControl, AUTO_HIDE_DELAY)
|
|
166
188
|
return
|
|
167
189
|
}
|
|
168
|
-
|
|
190
|
+
hide()
|
|
169
191
|
}
|
|
170
192
|
|
|
171
193
|
const reveal = () => {
|
|
@@ -196,7 +218,7 @@ export const Chrome = ({ ref, onVideoRef, onSubtitleRef, overlay, controls, chil
|
|
|
196
218
|
if (hideUI) reveal()
|
|
197
219
|
else {
|
|
198
220
|
clearTimeout(autoHide.current)
|
|
199
|
-
|
|
221
|
+
hide()
|
|
200
222
|
}
|
|
201
223
|
}
|
|
202
224
|
|
|
@@ -209,7 +231,7 @@ export const Chrome = ({ ref, onVideoRef, onSubtitleRef, overlay, controls, chil
|
|
|
209
231
|
const inside = ev.clientX >= left && ev.clientX < right && ev.clientY >= top && ev.clientY < bottom
|
|
210
232
|
if (inside) return
|
|
211
233
|
clearTimeout(autoHide.current)
|
|
212
|
-
|
|
234
|
+
hide()
|
|
213
235
|
}
|
|
214
236
|
|
|
215
237
|
return (
|
|
@@ -127,6 +127,20 @@ export type SourceState = {
|
|
|
127
127
|
hideUI: boolean
|
|
128
128
|
setHideUI: (hide: boolean) => void
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Whether there is anything loaded to play at all.
|
|
132
|
+
*
|
|
133
|
+
* Not the same question as `ready`, which is about a source that HAS been handed over and is still
|
|
134
|
+
* booting. This one separates that from having been given nothing, and the chrome needs the
|
|
135
|
+
* difference: idle-hiding with no media leaves a black rectangle with no controls, no title and no
|
|
136
|
+
* cursor, and no way back, since the only thing that reveals the chrome again is a pointer move over
|
|
137
|
+
* a player the viewer has no reason to think is there.
|
|
138
|
+
*
|
|
139
|
+
* Written by the React layer, which is the only place both arms are visible: bytes for a local
|
|
140
|
+
* source, an element for a media this player does not own.
|
|
141
|
+
*/
|
|
142
|
+
hasMedia: boolean
|
|
143
|
+
|
|
130
144
|
/**
|
|
131
145
|
* Owned here, not by `pip`: that watches the media element, and the window holds a mirror.
|
|
132
146
|
*
|
|
@@ -210,6 +224,7 @@ const initialState: SourceState = {
|
|
|
210
224
|
selectAudioTrack: () => {},
|
|
211
225
|
hideUI: false,
|
|
212
226
|
setHideUI: () => {},
|
|
227
|
+
hasMedia: false,
|
|
213
228
|
togglePictureInPicture: null,
|
|
214
229
|
pictureInPictureMode: null,
|
|
215
230
|
burnedInSubtitles: false,
|
|
@@ -269,9 +269,16 @@ const PlayerRoot = ({ options, children }: { options: MediaPlayerOptions, childr
|
|
|
269
269
|
// attaches: when attach swaps in the real setter the identity changes and these publish again.
|
|
270
270
|
const setSourceState = usePlayer((state) => state.setSourceState)
|
|
271
271
|
|
|
272
|
+
/*
|
|
273
|
+
* Read here because this is the only place both arms are in scope: a local source is bytes, and a
|
|
274
|
+
* remote one is an element somebody else owns. `size` alone cannot answer it, since the remote arm
|
|
275
|
+
* legitimately has none, and the chrome would then treat every remote player as having no media.
|
|
276
|
+
*/
|
|
277
|
+
const hasMedia = remote ? !!remote.media : size !== undefined
|
|
278
|
+
|
|
272
279
|
useEffect(() => {
|
|
273
|
-
setSourceState({ title, size, downloadedRanges })
|
|
274
|
-
}, [setSourceState, title, size, downloadedRanges])
|
|
280
|
+
setSourceState({ title, size, downloadedRanges, hasMedia })
|
|
281
|
+
}, [setSourceState, title, size, downloadedRanges, hasMedia])
|
|
275
282
|
|
|
276
283
|
const thumbnailAt = remote?.thumbnails?.at
|
|
277
284
|
useEffect(() => {
|