avbridge 2.11.0 → 2.12.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/{avi-B5CQYB7L.cjs → avi-EQE6AR75.cjs} +4 -4
  3. package/dist/{avi-2ILLBNPQ.cjs.map → avi-EQE6AR75.cjs.map} +1 -1
  4. package/dist/{avi-RWWPN2PR.js → avi-NNHH4AAA.js} +3 -3
  5. package/dist/{avi-JXU4GQL2.js.map → avi-NNHH4AAA.js.map} +1 -1
  6. package/dist/{avi-JXU4GQL2.js → avi-S7EY54YA.js} +3 -3
  7. package/dist/{avi-RWWPN2PR.js.map → avi-S7EY54YA.js.map} +1 -1
  8. package/dist/{avi-2ILLBNPQ.cjs → avi-Y3N325WZ.cjs} +4 -4
  9. package/dist/{avi-B5CQYB7L.cjs.map → avi-Y3N325WZ.cjs.map} +1 -1
  10. package/dist/{chunk-GYIJU44C.js → chunk-2LNXMGT6.js} +5 -5
  11. package/dist/{chunk-GYIJU44C.js.map → chunk-2LNXMGT6.js.map} +1 -1
  12. package/dist/{chunk-DCSOQH2N.js → chunk-3AI5WFFN.js} +40 -16
  13. package/dist/chunk-3AI5WFFN.js.map +1 -0
  14. package/dist/{chunk-2NSOOMXW.js → chunk-3YKWU4FM.js} +3 -3
  15. package/dist/{chunk-2NSOOMXW.js.map → chunk-3YKWU4FM.js.map} +1 -1
  16. package/dist/{chunk-CL6UEUQF.js → chunk-5Y5BTB5D.js} +5 -5
  17. package/dist/{chunk-CL6UEUQF.js.map → chunk-5Y5BTB5D.js.map} +1 -1
  18. package/dist/{chunk-37UOSAVI.cjs → chunk-7EF4VTUS.cjs} +23 -23
  19. package/dist/{chunk-IHNHHEA2.js.map → chunk-7EF4VTUS.cjs.map} +1 -1
  20. package/dist/{chunk-OTFS7DC4.cjs → chunk-GJBNLPGI.cjs} +14 -14
  21. package/dist/{chunk-OTFS7DC4.cjs.map → chunk-GJBNLPGI.cjs.map} +1 -1
  22. package/dist/{chunk-BYGZN4Z5.cjs → chunk-HBHSUGNI.cjs} +5 -5
  23. package/dist/{chunk-BYGZN4Z5.cjs.map → chunk-HBHSUGNI.cjs.map} +1 -1
  24. package/dist/{chunk-L7A3ECI2.cjs → chunk-HZUVMXBN.cjs} +4 -4
  25. package/dist/{chunk-L7A3ECI2.cjs.map → chunk-HZUVMXBN.cjs.map} +1 -1
  26. package/dist/{chunk-Z33SBWL5.cjs → chunk-YPZFGJV3.cjs} +40 -16
  27. package/dist/chunk-YPZFGJV3.cjs.map +1 -0
  28. package/dist/{chunk-IHNHHEA2.js → chunk-Z26PXRUY.js} +9 -9
  29. package/dist/chunk-Z26PXRUY.js.map +1 -0
  30. package/dist/element-browser.js +42 -18
  31. package/dist/element-browser.js.map +1 -1
  32. package/dist/element.cjs +5 -5
  33. package/dist/element.d.cts +1 -1
  34. package/dist/element.d.ts +1 -1
  35. package/dist/element.js +4 -4
  36. package/dist/index.cjs +21 -21
  37. package/dist/index.d.cts +2 -2
  38. package/dist/index.d.ts +2 -2
  39. package/dist/index.js +9 -9
  40. package/dist/{libav-demux-3N5Y3VQA.cjs → libav-demux-575OYCT2.cjs} +9 -9
  41. package/dist/{libav-demux-3N5Y3VQA.cjs.map → libav-demux-575OYCT2.cjs.map} +1 -1
  42. package/dist/{libav-demux-JXD4OTLM.js → libav-demux-SXZDLC7W.js} +4 -4
  43. package/dist/{libav-demux-JXD4OTLM.js.map → libav-demux-SXZDLC7W.js.map} +1 -1
  44. package/dist/libav-http-reader-2S5HAHW4.js +3 -0
  45. package/dist/{libav-http-reader-WXG3Z7AI.js.map → libav-http-reader-2S5HAHW4.js.map} +1 -1
  46. package/dist/libav-http-reader-Q356EO2K.cjs +16 -0
  47. package/dist/{libav-http-reader-AZLE7YFS.cjs.map → libav-http-reader-Q356EO2K.cjs.map} +1 -1
  48. package/dist/{player-DDdNVFDv.d.cts → player-bQ6n4hVp.d.cts} +15 -0
  49. package/dist/{player-DDdNVFDv.d.ts → player-bQ6n4hVp.d.ts} +15 -0
  50. package/dist/player.cjs +60 -15
  51. package/dist/player.cjs.map +1 -1
  52. package/dist/player.d.cts +21 -0
  53. package/dist/player.d.ts +21 -0
  54. package/dist/player.js +60 -15
  55. package/dist/player.js.map +1 -1
  56. package/dist/remux-7TA4FKTY.js +10 -0
  57. package/dist/{remux-56V7LDAD.js.map → remux-7TA4FKTY.js.map} +1 -1
  58. package/dist/remux-VPKCLHHM.cjs +35 -0
  59. package/dist/{remux-KUS5GIL6.cjs.map → remux-VPKCLHHM.cjs.map} +1 -1
  60. package/package.json +1 -1
  61. package/src/element/avbridge-player.ts +36 -8
  62. package/src/element/player-styles.ts +13 -1
  63. package/src/player.ts +3 -3
  64. package/src/types.ts +15 -0
  65. package/src/util/libav-http-reader.ts +58 -19
  66. package/dist/chunk-37UOSAVI.cjs.map +0 -1
  67. package/dist/chunk-DCSOQH2N.js.map +0 -1
  68. package/dist/chunk-Z33SBWL5.cjs.map +0 -1
  69. package/dist/libav-http-reader-AZLE7YFS.cjs +0 -16
  70. package/dist/libav-http-reader-WXG3Z7AI.js +0 -3
  71. package/dist/remux-56V7LDAD.js +0 -10
  72. package/dist/remux-KUS5GIL6.cjs +0 -35
package/dist/player.d.cts CHANGED
@@ -209,6 +209,14 @@ interface CreatePlayerOptions {
209
209
  * for interceptors, logging, or environments without a global fetch.
210
210
  */
211
211
  fetchFn?: FetchFn;
212
+ /**
213
+ * Byte budget for the libav HTTP reader's LRU cache of fetched ranges.
214
+ * Defaults to 8 MB. Set to `0` to disable caching. Raise this when the
215
+ * app plays seek-heavy legacy-container media from URLs — hot regions
216
+ * (header/moov, tail index, current window) stay resident instead of
217
+ * being re-fetched on every bounce.
218
+ */
219
+ cacheBytes?: number;
212
220
  }
213
221
  /** Signature-compatible with `globalThis.fetch`. */
214
222
  type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
@@ -216,6 +224,13 @@ type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Respons
216
224
  interface TransportConfig {
217
225
  requestInit?: RequestInit;
218
226
  fetchFn?: FetchFn;
227
+ /**
228
+ * Byte budget for the libav HTTP reader's LRU cache of fetched ranges.
229
+ * Defaults to 8 MB. Set to `0` to disable caching entirely. Higher
230
+ * values help seek-heavy network playback keep hot regions
231
+ * (header/moov, tail index, current read) resident.
232
+ */
233
+ cacheBytes?: number;
219
234
  }
220
235
  /** Events emitted by {@link UnifiedPlayer}. Strongly typed. */
221
236
  interface PlayerEventMap {
@@ -380,6 +395,12 @@ declare class AvbridgePlayerElement extends HTMLElement {
380
395
  private _updateSeekTooltip;
381
396
  private _updateSeekVisuals;
382
397
  private _updateTime;
398
+ /**
399
+ * Render every buffered range as its own segment so gaps (common on MSE
400
+ * after seeks) are visible. Not gated by `_userSeeking` — ranges should
401
+ * keep updating while the user scrubs, and runs cheaply on `progress`.
402
+ */
403
+ private _updateBuffered;
383
404
  private _toggleMute;
384
405
  private _updateVolume;
385
406
  private _toggleSettings;
package/dist/player.d.ts CHANGED
@@ -209,6 +209,14 @@ interface CreatePlayerOptions {
209
209
  * for interceptors, logging, or environments without a global fetch.
210
210
  */
211
211
  fetchFn?: FetchFn;
212
+ /**
213
+ * Byte budget for the libav HTTP reader's LRU cache of fetched ranges.
214
+ * Defaults to 8 MB. Set to `0` to disable caching. Raise this when the
215
+ * app plays seek-heavy legacy-container media from URLs — hot regions
216
+ * (header/moov, tail index, current window) stay resident instead of
217
+ * being re-fetched on every bounce.
218
+ */
219
+ cacheBytes?: number;
212
220
  }
213
221
  /** Signature-compatible with `globalThis.fetch`. */
214
222
  type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
@@ -216,6 +224,13 @@ type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Respons
216
224
  interface TransportConfig {
217
225
  requestInit?: RequestInit;
218
226
  fetchFn?: FetchFn;
227
+ /**
228
+ * Byte budget for the libav HTTP reader's LRU cache of fetched ranges.
229
+ * Defaults to 8 MB. Set to `0` to disable caching entirely. Higher
230
+ * values help seek-heavy network playback keep hot regions
231
+ * (header/moov, tail index, current read) resident.
232
+ */
233
+ cacheBytes?: number;
219
234
  }
220
235
  /** Events emitted by {@link UnifiedPlayer}. Strongly typed. */
221
236
  interface PlayerEventMap {
@@ -380,6 +395,12 @@ declare class AvbridgePlayerElement extends HTMLElement {
380
395
  private _updateSeekTooltip;
381
396
  private _updateSeekVisuals;
382
397
  private _updateTime;
398
+ /**
399
+ * Render every buffered range as its own segment so gaps (common on MSE
400
+ * after seeks) are visible. Not gated by `_userSeeking` — ranges should
401
+ * keep updating while the user scrubs, and runs cheaply on `progress`.
402
+ */
403
+ private _updateBuffered;
383
404
  private _toggleMute;
384
405
  private _updateVolume;
385
406
  private _toggleSettings;
package/dist/player.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AvbridgeError, ERR_ALL_STRATEGIES_EXHAUSTED, ERR_PLAYER_NOT_READY, normalizeSource, sniffNormalizedSource, ERR_PROBE_FAILED, ERR_PROBE_UNKNOWN_CONTAINER, ERR_LIBAV_NOT_REACHABLE, ERR_MSE_NOT_SUPPORTED, ERR_MSE_CODEC_NOT_SUPPORTED } from './chunk-E76AMWI4.js';
2
2
  import { dbg, loadLibav } from './chunk-IAYKFGFG.js';
3
- import './chunk-DCSOQH2N.js';
3
+ import './chunk-3AI5WFFN.js';
4
4
  import { SubtitleResourceBag, discoverSidecars, attachSubtitleTracks, SubtitleOverlay } from './chunk-EDDWAN2L.js';
5
5
  import './chunk-LUFA47FP.js';
6
6
 
@@ -237,7 +237,7 @@ async function probe(source, transport) {
237
237
  const hasUnknownCodec = result.videoTracks.some((t) => t.codec === "unknown") || result.audioTracks.some((t) => t.codec === "unknown");
238
238
  if (hasUnknownCodec) {
239
239
  try {
240
- const { probeWithLibav } = await import('./avi-JXU4GQL2.js');
240
+ const { probeWithLibav } = await import('./avi-S7EY54YA.js');
241
241
  return await probeWithLibav(normalized, sniffed);
242
242
  } catch {
243
243
  return result;
@@ -250,7 +250,7 @@ async function probe(source, transport) {
250
250
  mediabunnyErr.message
251
251
  );
252
252
  try {
253
- const { probeWithLibav } = await import('./avi-JXU4GQL2.js');
253
+ const { probeWithLibav } = await import('./avi-S7EY54YA.js');
254
254
  return await probeWithLibav(normalized, sniffed);
255
255
  } catch (libavErr) {
256
256
  const mbMsg = mediabunnyErr.message || String(mediabunnyErr);
@@ -264,7 +264,7 @@ async function probe(source, transport) {
264
264
  }
265
265
  }
266
266
  try {
267
- const { probeWithLibav } = await import('./avi-JXU4GQL2.js');
267
+ const { probeWithLibav } = await import('./avi-S7EY54YA.js');
268
268
  return await probeWithLibav(normalized, sniffed);
269
269
  } catch (err) {
270
270
  const inner = err instanceof Error ? err.message : String(err);
@@ -2021,7 +2021,7 @@ async function startHybridDecoder(opts) {
2021
2021
  const variant = pickLibavVariant(opts.context);
2022
2022
  const libav = await loadLibav(variant);
2023
2023
  const bridge = await loadBridge();
2024
- const { prepareLibavInput } = await import('./libav-http-reader-WXG3Z7AI.js');
2024
+ const { prepareLibavInput } = await import('./libav-http-reader-2S5HAHW4.js');
2025
2025
  const inputHandle = await prepareLibavInput(libav, opts.filename, opts.source, opts.transport);
2026
2026
  const readPkt = await libav.av_packet_alloc();
2027
2027
  const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(opts.filename);
@@ -2691,7 +2691,7 @@ async function startDecoder(opts) {
2691
2691
  const variant = "avbridge";
2692
2692
  const libav = await loadLibav(variant);
2693
2693
  const bridge = await loadBridge2();
2694
- const { prepareLibavInput } = await import('./libav-http-reader-WXG3Z7AI.js');
2694
+ const { prepareLibavInput } = await import('./libav-http-reader-2S5HAHW4.js');
2695
2695
  const inputHandle = await prepareLibavInput(libav, opts.filename, opts.source, opts.transport);
2696
2696
  const readPkt = await libav.av_packet_alloc();
2697
2697
  const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(opts.filename);
@@ -3420,9 +3420,9 @@ var UnifiedPlayer = class _UnifiedPlayer {
3420
3420
  constructor(options, registry) {
3421
3421
  this.options = options;
3422
3422
  this.registry = registry;
3423
- const { requestInit, fetchFn } = options;
3424
- if (requestInit || fetchFn) {
3425
- this.transport = { requestInit, fetchFn };
3423
+ const { requestInit, fetchFn, cacheBytes } = options;
3424
+ if (requestInit || fetchFn || cacheBytes !== void 0) {
3425
+ this.transport = { requestInit, fetchFn, cacheBytes };
3426
3426
  }
3427
3427
  }
3428
3428
  options;
@@ -5033,6 +5033,12 @@ var PLAYER_STYLES = (
5033
5033
  display: flex;
5034
5034
  align-items: center;
5035
5035
  cursor: pointer;
5036
+ /* Claim all touch gestures on the seek bar. Without this, Android
5037
+ * browsers (Chrome, Samsung Internet) treat horizontal drags as
5038
+ * scroll candidates and cancel pointermove once the gesture
5039
+ * resolves, breaking scrub. touch-action must be set in CSS \u2014
5040
+ * preventDefault() on pointerdown is too late. */
5041
+ touch-action: none;
5036
5042
  }
5037
5043
 
5038
5044
  .avp-seek-track {
@@ -5050,7 +5056,13 @@ var PLAYER_STYLES = (
5050
5056
 
5051
5057
  .avp-seek-buffered {
5052
5058
  position: absolute;
5053
- left: 0;
5059
+ inset: 0;
5060
+ pointer-events: none;
5061
+ }
5062
+
5063
+ .avp-seek-buffered-range {
5064
+ position: absolute;
5065
+ top: 0;
5054
5066
  height: 100%;
5055
5067
  background: rgba(255, 255, 255, 0.35);
5056
5068
  border-radius: inherit;
@@ -5610,6 +5622,7 @@ var AvbridgePlayerElement = class _AvbridgePlayerElement extends HTMLElement {
5610
5622
  on(this._video, "ended", () => this._setState("ended"));
5611
5623
  on(this._video, "error", () => this._setState("error"));
5612
5624
  on(this._video, "timeupdate", () => this._updateTime());
5625
+ on(this._video, "progress", () => this._updateBuffered());
5613
5626
  on(this._video, "volumechange", () => this._updateVolume());
5614
5627
  on(this._video, "trackschange", () => this._buildSettingsMenu());
5615
5628
  on(this._video, "durationchange", () => {
@@ -5826,13 +5839,45 @@ var AvbridgePlayerElement = class _AvbridgePlayerElement extends HTMLElement {
5826
5839
  this._seekInput.value = String(t);
5827
5840
  this._updateSeekVisuals(t);
5828
5841
  this._timeDisplay.textContent = `${formatTime(t)} / ${formatTime(d)}`;
5842
+ this._updateBuffered();
5843
+ }
5844
+ /**
5845
+ * Render every buffered range as its own segment so gaps (common on MSE
5846
+ * after seeks) are visible. Not gated by `_userSeeking` — ranges should
5847
+ * keep updating while the user scrubs, and runs cheaply on `progress`.
5848
+ */
5849
+ _updateBuffered() {
5850
+ const d = this._video.duration;
5851
+ if (!(d > 0)) return;
5852
+ let buf;
5829
5853
  try {
5830
- const buf = this._video.buffered;
5831
- if (buf && buf.length > 0 && d > 0) {
5832
- const end = buf.end(buf.length - 1);
5833
- this._seekBuffered.style.width = `${end / d * 100}%`;
5834
- }
5854
+ buf = this._video.buffered;
5835
5855
  } catch {
5856
+ return;
5857
+ }
5858
+ const count = buf ? buf.length : 0;
5859
+ const host = this._seekBuffered;
5860
+ while (host.childElementCount > count) host.lastElementChild.remove();
5861
+ while (host.childElementCount < count) {
5862
+ const seg = document.createElement("div");
5863
+ seg.className = "avp-seek-buffered-range";
5864
+ host.appendChild(seg);
5865
+ }
5866
+ for (let i = 0; i < count; i++) {
5867
+ let start;
5868
+ let end;
5869
+ try {
5870
+ start = buf.start(i);
5871
+ end = buf.end(i);
5872
+ } catch {
5873
+ continue;
5874
+ }
5875
+ const s = Math.max(0, start);
5876
+ const e = Math.min(d, end);
5877
+ if (e <= s) continue;
5878
+ const seg = host.children[i];
5879
+ seg.style.left = `${s / d * 100}%`;
5880
+ seg.style.width = `${(e - s) / d * 100}%`;
5836
5881
  }
5837
5882
  }
5838
5883
  // ── Controls: volume ───────────────────────────────────────────────────