@banou/media-player 0.8.6 → 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.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, u as l } from "../engine
|
|
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
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 };
|
|
@@ -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,85 +220,92 @@ 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), !
|
|
228
|
-
},
|
|
227
|
+
t && n || (console.error(e), !J && (J = !0, O?.(n ? Error("Reading the video file failed", { cause: e }) : e)));
|
|
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
|
|
231
|
-
},
|
|
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
|
+
}, ne = () => {
|
|
232
232
|
let e = a(T);
|
|
233
233
|
if (!e.length) return !0;
|
|
234
234
|
let t = n.currentTime;
|
|
235
235
|
if (Math.max(...e.map((e) => e.end)) >= t + g) return !1;
|
|
236
236
|
let r = e.find((e) => e.start <= t + S && t < e.end);
|
|
237
237
|
return !r || r.end < t + _;
|
|
238
|
-
},
|
|
238
|
+
}, Z = () => {
|
|
239
239
|
let e = n.currentTime;
|
|
240
240
|
return a(T).find((t) => t.start <= e + S && e < t.end);
|
|
241
|
-
},
|
|
242
|
-
let e =
|
|
243
|
-
return !!e && e.end >=
|
|
244
|
-
},
|
|
241
|
+
}, re = () => {
|
|
242
|
+
let e = Z();
|
|
243
|
+
return !!e && e.end >= q - .1;
|
|
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
|
-
|
|
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
|
-
let t = await
|
|
267
|
-
if (
|
|
266
|
+
let t = await X(!0).then(() => !0, () => !1);
|
|
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
|
-
|
|
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,8 +390,8 @@ 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 } = e, r = e.mode ??
|
|
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
396
|
}, h = () => {
|
|
390
397
|
a && m(a.composite, a.context);
|
|
@@ -411,11 +418,11 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
411
418
|
l = !0;
|
|
412
419
|
let { mirror: e } = a;
|
|
413
420
|
h(), e.play().then(() => new Promise((e) => {
|
|
414
|
-
setTimeout(e,
|
|
421
|
+
setTimeout(e, F);
|
|
415
422
|
})).catch(() => {}).finally(() => {
|
|
416
423
|
e.pause(), setTimeout(() => {
|
|
417
424
|
l = !1;
|
|
418
|
-
},
|
|
425
|
+
}, F);
|
|
419
426
|
});
|
|
420
427
|
}, E = [["play", () => {
|
|
421
428
|
t.play().catch(() => {});
|
|
@@ -452,7 +459,7 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
452
459
|
};
|
|
453
460
|
if (a = f, u.srcObject = f.stream, (e.container ?? t.parentElement ?? document.body).appendChild(u), v(), s = setInterval(() => {
|
|
454
461
|
t.paused && h();
|
|
455
|
-
},
|
|
462
|
+
}, P), u.play().catch(() => {}), u.readyState === 0 && await new Promise((e) => {
|
|
456
463
|
let t = () => {
|
|
457
464
|
clearTimeout(n), e();
|
|
458
465
|
}, n = setTimeout(t, 1e3);
|
|
@@ -498,4 +505,4 @@ var a = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
|
|
|
498
505
|
};
|
|
499
506
|
};
|
|
500
507
|
//#endregion
|
|
501
|
-
export { T as a, m as c, C as i, a as l,
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, c as t, n, r, s as i, t as a } from "./engine
|
|
1
|
+
import { a as e, c as t, n, r, s as i, t as a } from "./engine-B6flRjLd.js";
|
|
2
2
|
import { Children as o, Fragment as s, isValidElement as c, useCallback as l, useEffect as u, useMemo as d, useRef as f, useState as p } from "react";
|
|
3
3
|
import { css as m, keyframes as h } from "@emotion/react";
|
|
4
4
|
import { createPlayer as g, useContainerAttach as _, useMediaAttach as v } from "@videojs/react";
|
package/package.json
CHANGED
|
@@ -329,7 +329,35 @@ export const startPlayback = async (options: PlaybackOptions): Promise<PlaybackC
|
|
|
329
329
|
videoElement.addEventListener('seeking', onSeeking)
|
|
330
330
|
teardown.push(() => videoElement.removeEventListener('seeking', onSeeking))
|
|
331
331
|
|
|
332
|
+
/**
|
|
333
|
+
* A terminal failure of the media element, which NOTHING here used to observe.
|
|
334
|
+
*
|
|
335
|
+
* `MediaError` is set once and the element never plays again, but the pump below kept running,
|
|
336
|
+
* and every `appendBuffer` after it throws `InvalidStateError: The HTMLMediaElement.error
|
|
337
|
+
* attribute is not null`. `updateSourceBuffer`'s chain deliberately survives a rejection, so that
|
|
338
|
+
* repeated forever, and `flushPending` swallows four attempts and rethrows the fifth. What
|
|
339
|
+
* reached the viewer was therefore the FIFTH `InvalidStateError` rather than the real cause, and
|
|
340
|
+
* the real cause never appeared anywhere at all.
|
|
341
|
+
*
|
|
342
|
+
* That cost a session: a decode failure presented as an append bug, which is a completely
|
|
343
|
+
* different place to look. Report what actually happened, then stop.
|
|
344
|
+
*/
|
|
345
|
+
let elementFailed = false
|
|
346
|
+
const onElementError = () => {
|
|
347
|
+
if (elementFailed) return
|
|
348
|
+
elementFailed = true
|
|
349
|
+
const error = videoElement.error
|
|
350
|
+
reportError(
|
|
351
|
+
new Error(`the media element failed: ${error?.message ?? 'unknown'}`, { cause: error }),
|
|
352
|
+
false,
|
|
353
|
+
)
|
|
354
|
+
}
|
|
355
|
+
videoElement.addEventListener('error', onElementError)
|
|
356
|
+
teardown.push(() => videoElement.removeEventListener('error', onElementError))
|
|
357
|
+
|
|
332
358
|
const interval = setInterval(() => {
|
|
359
|
+
// Nothing below can succeed against a failed element, and retrying only buries the real error.
|
|
360
|
+
if (elementFailed || videoElement.error) return
|
|
333
361
|
evict().catch(() => {})
|
|
334
362
|
pump().catch((error) => reportError(error, false))
|
|
335
363
|
// every remove() puts the MediaSource back to 'open', so the end has to be re-armed
|