@banou/media-player 0.10.14 → 0.10.16

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.
@@ -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-DdbOiEX3.js";
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-C9vSEJYW.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 };
@@ -188,7 +188,7 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
188
188
  length: s,
189
189
  audioStreamIndex: _,
190
190
  read: a
191
- }), M = [], N = !1, P = () => {
191
+ }), M = [], N = !1, se = () => {
192
192
  if (!N) {
193
193
  N = !0;
194
194
  for (let e of [...M].reverse()) try {
@@ -237,138 +237,138 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
237
237
  i(), n(/* @__PURE__ */ Error("The MediaSource closed before a SourceBuffer could be created"));
238
238
  };
239
239
  m.addEventListener("sourceopen", a, { once: !0 }), m.addEventListener("sourceclose", o, { once: !0 }), m.addEventListener("error", o, { once: !0 });
240
- }), { appendBuffer: F, unbufferRange: se, updateTimestampOffset: ce, endOfStream: le } = o(A, m);
241
- await F(e.data), e.subtitles?.length && s.pushFragments(e.subtitles), te?.();
242
- let I = !1, L = !1, R = 0, z, ue = () => z ?? n.currentTime, B = !1, de = 0, V = 0, H = null, U = 0, W = 0, G = !1, fe = 0, K = !0, q = (e, t, n = !1) => {
240
+ }), { appendBuffer: P, unbufferRange: ce, updateTimestampOffset: le, endOfStream: ue } = o(A, m);
241
+ await P(e.data), e.subtitles?.length && s.pushFragments(e.subtitles), te?.();
242
+ let F = !1, I = !1, L = 0, R, de = () => R ?? n.currentTime, z = !1, fe = !1, pe = 0, B = 0, V = null, H = 0, U = 0, W = !1, G = 0, K = !0, q = (e, t, n = !1) => {
243
243
  let r = e?.message === "Cancelled";
244
- t && r || (console.error(e), (!G || n) && (G = !0, ne?.(r ? Error("Reading the video file failed", { cause: e }) : e)));
245
- }, pe = async (e = !1) => {
246
- if (R > 0 && !e) return;
247
- let t = n.currentTime, r = e ? x : v, a = e ? S : y, o = i(A), s = (e, t) => (K = !1, se(e, t));
244
+ t && r || (console.error(e), (!W || n) && (W = !0, ne?.(r ? Error("Reading the video file failed", { cause: e }) : e)));
245
+ }, me = async (e = !1) => {
246
+ if (L > 0 && !e) return;
247
+ let t = n.currentTime, r = e ? x : v, a = e ? S : y, o = i(A), s = (e, t) => (K = !1, ce(e, t));
248
248
  o.length && o[0].start < t + r && await s(0, t + r);
249
249
  for (let { end: e } of o) e > t + a && await s(t + a, e);
250
- }, me = () => {
250
+ }, he = () => {
251
251
  let e = i(A);
252
252
  if (!e.length) return !0;
253
- let t = ue(), n = e.find((e) => e.start <= t + T && t < e.end);
254
- return n && n.end >= t + y ? !1 : !n || n.end < t + b;
255
- }, he = (e) => i(A).find((t) => t.start <= e + T && e < t.end), ge = () => he(n.currentTime), _e = (e = n.currentTime) => {
256
- let t = he(e);
257
- return e >= W - .1 || !!t && t.end >= W - .1;
258
- }, ve = () => {
253
+ let t = de(), n = e.find((e) => e.start <= t + T && t < e.end);
254
+ return be() && ve(t) && (!n || n.start <= t) || n && n.end >= t + y ? !1 : !n || n.end < t + b;
255
+ }, ge = (e) => i(A).find((t) => t.start <= e + T && e < t.end), _e = () => ge(n.currentTime), ve = (e = n.currentTime) => {
256
+ let t = ge(e);
257
+ return e >= U - .1 || !!t && t.end >= U - .1;
258
+ }, ye = () => {
259
259
  let e = i(A).map((e) => e.end);
260
- e.length && (W = Math.max(W, ...e));
261
- }, J = async (e) => {
262
- L = !0, H = null, U = 0, fe = e, K = !0;
263
- let t = ++V;
260
+ e.length && (U = Math.max(U, ...e)), z && (fe = !0);
261
+ }, be = () => z || fe && (i(A).at(-1)?.end ?? 0) >= U - .1, J = async (e) => {
262
+ I = !0, V = null, H = 0, G = e, K = !0;
263
+ let t = ++B;
264
264
  try {
265
265
  let { data: n, pts: r, subtitles: i, finished: a } = await j.seek(e);
266
- if (N || t !== V || (a && (B = !0), i?.length && s.pushFragments(i), await ce(r), N || t !== V)) return;
267
- n.byteLength && (await F(n), ve());
266
+ if (N || t !== B || (a && (z = !0), i?.length && s.pushFragments(i), await le(r), N || t !== B)) return;
267
+ n.byteLength && (await P(n), ye());
268
268
  } catch (e) {
269
- t === V && (K = !1), q(e, N || t !== V);
269
+ t === B && (K = !1), q(e, N || t !== B);
270
270
  } finally {
271
- t === V && (L = !1);
271
+ t === B && (I = !1);
272
272
  }
273
- }, ye = async () => {
274
- let e = H;
273
+ }, xe = async () => {
274
+ let e = V;
275
275
  if (e) try {
276
- await F(e), ve(), H === e && (H = null, U = 0);
276
+ await P(e), ye(), V === e && (V = null, H = 0);
277
277
  } catch (t) {
278
- if (H !== e) return;
278
+ if (V !== e) return;
279
279
  if (t?.name === "QuotaExceededError") {
280
- let t = await pe(!0).then(() => !0, () => !1);
281
- if (H !== e) return;
280
+ let t = await me(!0).then(() => !0, () => !1);
281
+ if (V !== e) return;
282
282
  if (t) {
283
- B = !1, await J(ge()?.end ?? n.currentTime);
283
+ z = !1, await J(_e()?.end ?? n.currentTime);
284
284
  return;
285
285
  }
286
286
  }
287
- if (U += 1, U < C) return;
288
- throw H = null, t;
287
+ if (H += 1, H < C) return;
288
+ throw V = null, t;
289
289
  }
290
- }, be = async () => {
291
- if (I || L || Q !== void 0 || N || !H && (B || !me())) return;
292
- let e = ++de, t = V, n = () => N || e !== de || t !== V;
293
- I = !0;
290
+ }, Se = async () => {
291
+ if (F || I || Q !== void 0 || N || !V && (z || !he())) return;
292
+ let e = ++pe, t = B, n = () => N || e !== pe || t !== B;
293
+ F = !0;
294
294
  try {
295
- if (!H) {
295
+ if (!V) {
296
296
  let { data: e, subtitles: t, finished: r } = await j.read();
297
- if (n() || (r && (B = !0), t?.length && s.pushFragments(t), !e.byteLength)) return;
298
- H = e, U = 0;
297
+ if (n() || (r && (z = !0), t?.length && s.pushFragments(t), !e.byteLength)) return;
298
+ V = e, H = 0;
299
299
  }
300
- await ye(), !n() && G && (G = !1, re?.());
300
+ await xe(), !n() && W && (W = !1, re?.());
301
301
  } catch (e) {
302
302
  q(e, n());
303
303
  } finally {
304
- e === de && (I = !1);
304
+ e === pe && (F = !1);
305
305
  }
306
- }, xe = (e) => e >= fe && Se(e) && Ce(e), Se = (e) => i(A).some((t) => t.start <= e && e < t.end), Y = (e) => {
307
- let t = he(e);
306
+ }, Ce = (e) => e >= G && we(e) && Te(e), we = (e) => i(A).some((t) => t.start <= e && e < t.end), Y = (e) => {
307
+ let t = ge(e);
308
308
  return t ? t.end - e : 0;
309
- }, Ce = (e) => Y(e) >= E || B && _e(e), we = async (e) => {
310
- if (!N && !(Se(e) && Ce(e))) {
311
- B = !1, R++, z = e;
309
+ }, Te = (e) => Y(e) >= E || be() && ve(e), Ee = async (e) => {
310
+ if (!N && !(we(e) && Te(e))) {
311
+ z = !1, L++, R = e;
312
312
  try {
313
313
  await J(e);
314
- let t = V;
315
- for (let n = 0; n < ee && !(N || t !== V || B || Y(e) >= E); n++) {
314
+ let t = B;
315
+ for (let n = 0; n < ee && !(N || t !== B || z || Y(e) >= E); n++) {
316
316
  let t = Y(e);
317
- if (await be(), Y(e) <= t) break;
317
+ if (await Se(), Y(e) <= t) break;
318
318
  }
319
319
  } finally {
320
- R--, z === e && (z = void 0);
320
+ L--, R === e && (R = void 0);
321
321
  }
322
322
  }
323
- }, Te = 0, X = null, Z, Ee = (e) => {
324
- let t = performance.now(), n = t - Te;
323
+ }, De = 0, X = null, Z, Oe = (e) => {
324
+ let t = performance.now(), n = t - De;
325
325
  if (n >= D) {
326
- Te = t, X = null, ie?.(e);
326
+ De = t, X = null, ie?.(e);
327
327
  return;
328
328
  }
329
329
  X = e, !Z && (Z = setTimeout(() => {
330
330
  Z = void 0;
331
331
  let e = X;
332
- X = null, !(e === null || N) && (Te = performance.now(), ie?.(e));
332
+ X = null, !(e === null || N) && (De = performance.now(), ie?.(e));
333
333
  }, D - n));
334
334
  };
335
335
  M.push(() => {
336
336
  Z && clearTimeout(Z);
337
337
  });
338
- let De = 0, Q;
338
+ let ke = 0, Q;
339
339
  M.push(() => {
340
340
  Q && clearTimeout(Q);
341
341
  });
342
- let Oe = () => {
342
+ let Ae = () => {
343
343
  let t = n.currentTime, r = e.info.input.duration || n.duration;
344
- r > 0 && Ee(Math.min(Math.max(t / r, 0), 1));
345
- let i = performance.now(), a = i - De < O;
346
- if (De = i, !xe(t) && !(K && (L || Y(t) > 0) && Math.abs(t - fe) < .001)) {
347
- if (B = !1, Q && clearTimeout(Q), !a) {
344
+ r > 0 && Oe(Math.min(Math.max(t / r, 0), 1));
345
+ let i = performance.now(), a = i - ke < O;
346
+ if (ke = i, !Ce(t) && !(K && (I || Y(t) > 0) && Math.abs(t - G) < .001)) {
347
+ if (z = !1, Q && clearTimeout(Q), !a) {
348
348
  Q = void 0, J(t);
349
349
  return;
350
350
  }
351
351
  Q = setTimeout(() => {
352
352
  if (Q = void 0, N) return;
353
353
  let e = n.currentTime;
354
- xe(e) || (B = !1, J(e));
354
+ Ce(e) || (z = !1, J(e));
355
355
  }, O);
356
356
  }
357
357
  };
358
- n.addEventListener("seeking", Oe), M.push(() => n.removeEventListener("seeking", Oe));
359
- let $ = !1, ke = () => {
358
+ n.addEventListener("seeking", Ae), M.push(() => n.removeEventListener("seeking", Ae));
359
+ let $ = !1, je = () => {
360
360
  if ($) return;
361
361
  $ = !0;
362
362
  let e = n.error;
363
363
  q(new g(`the media element failed: ${e?.message ?? "unknown"}`, { cause: e }), !1, !0);
364
364
  };
365
- n.addEventListener("error", ke), M.push(() => n.removeEventListener("error", ke));
366
- let Ae = setInterval(() => {
367
- $ || n.error || (pe().catch(() => {}), be().catch((e) => q(e, !1)), B && !H && _e() && m.readyState === "open" && le().catch(() => {}));
365
+ n.addEventListener("error", je), M.push(() => n.removeEventListener("error", je));
366
+ let Me = setInterval(() => {
367
+ $ || n.error || (me().catch(() => {}), Se().catch((e) => q(e, !1)), be() && !V && ve() && m.readyState === "open" && ue().catch(() => {}));
368
368
  }, 100);
369
- return M.push(() => clearInterval(Ae)), {
370
- destroy: P,
371
- prepareSeek: we,
369
+ return M.push(() => clearInterval(Me)), {
370
+ destroy: se,
371
+ prepareSeek: Ee,
372
372
  videoElement: n,
373
373
  selectSubtitleStream: (e) => s.selectStream(e),
374
374
  indexes: e.indexes ?? [],
@@ -378,9 +378,9 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
378
378
  audioMimeType: e.info.output.audioMimeType
379
379
  };
380
380
  } catch (e) {
381
- throw P(), e;
381
+ throw se(), e;
382
382
  }
383
- }, ne = 5, re = 500, ie = 320, ae = 1e6, oe = 3, j = 1e4, M = 1.5, N = 4e6, P = 3e4, F = async (e) => {
383
+ }, ne = 5, re = 500, ie = 320, ae = 1e6, oe = 3, j = 1e4, M = 1.5, N = 4e6, se = 3e4, P = async (e) => {
384
384
  let { publicPath: n, workerUrl: r, length: i, read: a, onThumbnails: o, width: s = ie } = e, c = await t({
385
385
  publicPath: n,
386
386
  workerUrl: r,
@@ -469,7 +469,7 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
469
469
  }, w = async (e) => {
470
470
  _ = !0;
471
471
  try {
472
- let t = await Promise.race([c.init(), new Promise((e, t) => setTimeout(() => t(/* @__PURE__ */ Error("timed out")), P))]);
472
+ let t = await Promise.race([c.init(), new Promise((e, t) => setTimeout(() => t(/* @__PURE__ */ Error("timed out")), se))]);
473
473
  if (d) return;
474
474
  h = e;
475
475
  let n = l(t.indexes);
@@ -509,8 +509,8 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
509
509
  } catch (e) {
510
510
  throw A(c), e;
511
511
  }
512
- }, se = 1280, ce = 1920, le = 250, I = 100, L = () => typeof HTMLCanvasElement < "u" && "captureStream" in HTMLCanvasElement.prototype, R = () => typeof document < "u" && typeof HTMLVideoElement < "u" && typeof HTMLVideoElement.prototype.requestPictureInPicture == "function" && !!document.pictureInPictureEnabled, z = () => typeof HTMLVideoElement < "u" && "mozCaptureStream" in HTMLVideoElement.prototype, ue = () => L() ? R() ? "window" : z() ? "burn-in" : null : null, B = (e) => {
513
- let { video: t, subtitles: n } = e, r = e.mode ?? ue() ?? "window", i = e.maxWidth ?? (r === "burn-in" ? ce : se), 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) => {
512
+ }, ce = 1280, le = 1920, ue = 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, de = () => I() ? L() ? "window" : R() ? "burn-in" : null : null, z = (e) => {
513
+ let { video: t, subtitles: n } = e, r = e.mode ?? de() ?? "window", i = e.maxWidth ?? (r === "burn-in" ? le : ce), 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) => {
514
514
  r.drawImage(t, 0, 0, e.width, e.height);
515
515
  let i = n.querySelector("canvas");
516
516
  i && i.width > 0 && i.height > 0 && r.drawImage(i, 0, 0, e.width, e.height);
@@ -539,11 +539,11 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
539
539
  l = !0;
540
540
  let { mirror: e } = a;
541
541
  h(), e.play().then(() => new Promise((e) => {
542
- setTimeout(e, I);
542
+ setTimeout(e, F);
543
543
  })).catch(() => {}).finally(() => {
544
544
  e.pause(), setTimeout(() => {
545
545
  l = !1;
546
- }, I);
546
+ }, F);
547
547
  });
548
548
  }, E = [["play", () => {
549
549
  t.play().catch(() => {});
@@ -580,7 +580,7 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
580
580
  };
581
581
  if (a = f, u.srcObject = f.stream, (e.container ?? t.parentElement ?? document.body).appendChild(u), v(), s = setInterval(() => {
582
582
  t.paused && h();
583
- }, le), u.play().catch(() => {}), u.readyState === 0 && await new Promise((e) => {
583
+ }, ue), u.play().catch(() => {}), u.readyState === 0 && await new Promise((e) => {
584
584
  let t = () => {
585
585
  clearTimeout(n), e();
586
586
  }, n = setTimeout(t, 1e3);
@@ -626,4 +626,4 @@ var i = (e) => Array(e.buffered.length).fill(void 0).map((t, n) => ({
626
626
  };
627
627
  };
628
628
  //#endregion
629
- export { g as a, A as c, i as d, o as f, k as i, s as l, ue as n, _ as o, F as r, te as s, B as t, h as u };
629
+ export { g as a, A as c, i as d, o as f, k as i, s as l, de as n, _ as o, P as r, te as s, z as t, h as u };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { l as e, n as t, o as n, r, s as i, t as a, u as o } from "./engine-DdbOiEX3.js";
1
+ import { l as e, n as t, o as n, r, s as i, t as a, u as o } from "./engine-C9vSEJYW.js";
2
2
  import { Children as s, Fragment as c, isValidElement as l, useCallback as u, useEffect as d, useMemo as f, useRef as p, useState as m, useSyncExternalStore as h } from "react";
3
3
  import { css as g, keyframes as _ } from "@emotion/react";
4
4
  import { createPlayer as v, useContainerAttach as y, useMediaAttach as b } from "@videojs/react";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@banou/media-player",
3
- "version": "0.10.14",
3
+ "version": "0.10.16",
4
4
  "description": "A video player for containers and codecs the browser cannot play natively, remuxed on the fly",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -44,7 +44,7 @@
44
44
  "@videojs/react": "10.0.0-beta.26",
45
45
  "ass-compiler": "^0.1.16",
46
46
  "jassub": "^2.5.16",
47
- "libav-wasm": "^0.8.7",
47
+ "libav-wasm": "^0.8.9",
48
48
  "lucide-react": "^0.536.0",
49
49
  "osra": "^0.6.12",
50
50
  "react-tooltip": "^5.28.0"
@@ -271,6 +271,8 @@ export const startPlayback = async (options: PlaybackOptions): Promise<PlaybackC
271
271
  let prepareTarget: number | undefined
272
272
  const bufferAnchor = () => prepareTarget ?? videoElement.currentTime
273
273
  let finished = false
274
+ // whether the end of the file was ever appended, which unlike `finished` a seek does not clear
275
+ let endAppended = false
274
276
  // libav aborts the running task when a new one starts, so both flags need a generation token
275
277
  let readGeneration = 0
276
278
  let seekGeneration = 0
@@ -335,6 +337,11 @@ export const startPlayback = async (options: PlaybackOptions): Promise<PlaybackC
335
337
  if (!ranges.length) return true
336
338
  const ct = bufferAnchor()
337
339
  const range = ranges.find((r) => r.start <= ct + BOUNDARY_SLACK && ct < r.end)
340
+ // A range holding the playhead that runs to an end still buffered leaves nothing to read: after a seek back,
341
+ // reading on only appended again what was buffered, 13 reads of 32 KB on a move to 2 s before the end. From a
342
+ // hole under the slack before that range nothing read the hole, and playback stopped there for good with
343
+ // keyframes 0.833 s apart (measured 2026-10-12)
344
+ if (endInBuffer() && atEnd(ct) && (!range || range.start <= ct)) return false
338
345
  /*
339
346
  * Never read past what evict() keeps, measured on the run holding the anchor rather than
340
347
  * across every island.
@@ -364,7 +371,16 @@ export const startPlayback = async (options: PlaybackOptions): Promise<PlaybackC
364
371
  const trackAppendedEnd = () => {
365
372
  const ends = getTimeRanges(sourceBuffer).map((r) => r.end)
366
373
  if (ends.length) lastAppendedEnd = Math.max(lastAppendedEnd, ...ends)
374
+ if (finished) endAppended = true
367
375
  }
376
+ /*
377
+ * Whether the end of the file is in the buffer. A seek clears `finished`, so past one it is read back
378
+ * from `buffered`, since evict() and the browser both remove data: counted from a flag alone, a move to
379
+ * the end of a file whose end had been removed signalled the end there, endOfStream cut the duration to
380
+ * what was buffered, and the playhead went back to 20 s of 30 in both engines (measured 2026-10-12).
381
+ */
382
+ const endInBuffer = () =>
383
+ finished || (endAppended && (getTimeRanges(sourceBuffer).at(-1)?.end ?? 0) >= lastAppendedEnd - 0.1)
368
384
 
369
385
  const seekTo = async (time: number) => {
370
386
  seeking = true
@@ -489,15 +505,17 @@ export const startPlayback = async (options: PlaybackOptions): Promise<PlaybackC
489
505
  }
490
506
 
491
507
  /**
492
- * Whether a position has its runway, which stops at the end of the file once the remuxer has read to it.
508
+ * Whether a position has its runway, which stops at the end of the file while the end is in the buffer.
493
509
  *
494
510
  * No target in the last 3 s can have the full runway, and re-positioning the remuxer there re-appends
495
- * over the buffered end, after which Firefox 151 stays at the end and never fires `ended`. The end is
496
- * the furthest append, the one `endOfStream` waits on, never the declared duration: that is the longer
497
- * track, while an open MediaSource's `buffered` ends at the shorter one, and evict() reopens it on
498
- * every trim (measured 2026-10-11).
511
+ * over the buffered end, after which Firefox 151 stays at the end and never fires `ended`: its demuxer
512
+ * had read the track's last frame, and once that frame is replaced it waits for one starting at the
513
+ * track's end. So the end counts while it is buffered, even with the reader re-reading toward it after
514
+ * a seek back (measured 2026-10-12). The end is the furthest append, the one `endOfStream` waits on,
515
+ * never the declared duration: that is the longer track, while an open MediaSource's `buffered` ends at
516
+ * the shorter one, and evict() reopens it on every trim (measured 2026-10-11).
499
517
  */
500
- const hasRunway = (time: number) => runwayFrom(time) >= SEEK_RUNWAY || (finished && atEnd(time))
518
+ const hasRunway = (time: number) => runwayFrom(time) >= SEEK_RUNWAY || (endInBuffer() && atEnd(time))
501
519
 
502
520
  /**
503
521
  * Put the data in place for a position the playhead has NOT moved to yet.
@@ -692,7 +710,7 @@ export const startPlayback = async (options: PlaybackOptions): Promise<PlaybackC
692
710
  evict().catch(() => {})
693
711
  pump().catch((error) => reportError(error, false))
694
712
  // every remove() puts the MediaSource back to 'open', so the end has to be re-armed
695
- if (finished && !pending && atEnd() && mediaSource.readyState === 'open') endOfStream().catch(() => {})
713
+ if (endInBuffer() && !pending && atEnd() && mediaSource.readyState === 'open') endOfStream().catch(() => {})
696
714
  }, 100)
697
715
  teardown.push(() => clearInterval(interval))
698
716