avbridge 2.8.4 → 2.10.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 (79) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/README.md +74 -1
  3. package/dist/{avi-F6WZJK5T.cjs → avi-2ILLBNPQ.cjs} +8 -2
  4. package/dist/avi-2ILLBNPQ.cjs.map +1 -0
  5. package/dist/{avi-W6L3BTWU.cjs → avi-B5CQYB7L.cjs} +8 -2
  6. package/dist/avi-B5CQYB7L.cjs.map +1 -0
  7. package/dist/{avi-2JPBSHGA.js → avi-JXU4GQL2.js} +8 -2
  8. package/dist/avi-JXU4GQL2.js.map +1 -0
  9. package/dist/{avi-NJXAXUXK.js → avi-RWWPN2PR.js} +8 -2
  10. package/dist/avi-RWWPN2PR.js.map +1 -0
  11. package/dist/{chunk-X2K3GIWE.js → chunk-2NSOOMXW.js} +14 -3
  12. package/dist/chunk-2NSOOMXW.js.map +1 -0
  13. package/dist/{chunk-KBWQRGHS.js → chunk-3GKM5DFM.js} +119 -8
  14. package/dist/chunk-3GKM5DFM.js.map +1 -0
  15. package/dist/{chunk-ZCUXHW55.cjs → chunk-BYGZN4Z5.cjs} +5 -5
  16. package/dist/{chunk-ZCUXHW55.cjs.map → chunk-BYGZN4Z5.cjs.map} +1 -1
  17. package/dist/{chunk-SMH6IOP2.js → chunk-CL6UEUQF.js} +4 -4
  18. package/dist/{chunk-SMH6IOP2.js.map → chunk-CL6UEUQF.js.map} +1 -1
  19. package/dist/{chunk-SR3MPV4D.js → chunk-GYIJU44C.js} +5 -5
  20. package/dist/{chunk-SR3MPV4D.js.map → chunk-GYIJU44C.js.map} +1 -1
  21. package/dist/{chunk-CPZ7PXAM.cjs → chunk-L7A3ECI2.cjs} +14 -2
  22. package/dist/chunk-L7A3ECI2.cjs.map +1 -0
  23. package/dist/{chunk-YX4AGLNF.cjs → chunk-NQULEIA3.cjs} +129 -18
  24. package/dist/chunk-NQULEIA3.cjs.map +1 -0
  25. package/dist/{chunk-Q2VUO52Z.cjs → chunk-OTFS7DC4.cjs} +12 -12
  26. package/dist/{chunk-Q2VUO52Z.cjs.map → chunk-OTFS7DC4.cjs.map} +1 -1
  27. package/dist/element-browser.js +144 -10
  28. package/dist/element-browser.js.map +1 -1
  29. package/dist/element.cjs +16 -10
  30. package/dist/element.cjs.map +1 -1
  31. package/dist/element.d.cts +11 -6
  32. package/dist/element.d.ts +11 -6
  33. package/dist/element.js +15 -9
  34. package/dist/element.js.map +1 -1
  35. package/dist/index.cjs +20 -20
  36. package/dist/index.d.cts +2 -2
  37. package/dist/index.d.ts +2 -2
  38. package/dist/index.js +8 -8
  39. package/dist/libav-demux-3N5Y3VQA.cjs +31 -0
  40. package/dist/{libav-demux-H2GS46GH.cjs.map → libav-demux-3N5Y3VQA.cjs.map} +1 -1
  41. package/dist/libav-demux-JXD4OTLM.js +6 -0
  42. package/dist/{libav-demux-OWZ4T2YW.js.map → libav-demux-JXD4OTLM.js.map} +1 -1
  43. package/dist/{player-BptSJPfn.d.cts → player-DDdNVFDv.d.cts} +24 -2
  44. package/dist/{player-BptSJPfn.d.ts → player-DDdNVFDv.d.ts} +24 -2
  45. package/dist/player.cjs +413 -117
  46. package/dist/player.cjs.map +1 -1
  47. package/dist/player.d.cts +44 -11
  48. package/dist/player.d.ts +44 -11
  49. package/dist/player.js +413 -117
  50. package/dist/player.js.map +1 -1
  51. package/dist/{remux-WBYIZBBX.js → remux-56V7LDAD.js} +5 -5
  52. package/dist/{remux-WBYIZBBX.js.map → remux-56V7LDAD.js.map} +1 -1
  53. package/dist/{remux-OBSMIENG.cjs → remux-KUS5GIL6.cjs} +10 -10
  54. package/dist/{remux-OBSMIENG.cjs.map → remux-KUS5GIL6.cjs.map} +1 -1
  55. package/package.json +1 -1
  56. package/src/classify/rules.ts +2 -0
  57. package/src/element/avbridge-player.ts +172 -86
  58. package/src/element/avbridge-video.ts +22 -6
  59. package/src/element/player-styles.ts +149 -34
  60. package/src/index.ts +1 -0
  61. package/src/probe/avi.ts +2 -0
  62. package/src/strategies/fallback/audio-output.ts +29 -4
  63. package/src/strategies/fallback/decoder.ts +30 -0
  64. package/src/strategies/fallback/index.ts +42 -0
  65. package/src/strategies/hybrid/decoder.ts +35 -0
  66. package/src/strategies/hybrid/index.ts +26 -0
  67. package/src/strategies/remux/index.ts +8 -0
  68. package/src/types.ts +31 -0
  69. package/src/util/libav-demux.ts +26 -0
  70. package/dist/avi-2JPBSHGA.js.map +0 -1
  71. package/dist/avi-F6WZJK5T.cjs.map +0 -1
  72. package/dist/avi-NJXAXUXK.js.map +0 -1
  73. package/dist/avi-W6L3BTWU.cjs.map +0 -1
  74. package/dist/chunk-CPZ7PXAM.cjs.map +0 -1
  75. package/dist/chunk-KBWQRGHS.js.map +0 -1
  76. package/dist/chunk-X2K3GIWE.js.map +0 -1
  77. package/dist/chunk-YX4AGLNF.cjs.map +0 -1
  78. package/dist/libav-demux-H2GS46GH.cjs +0 -27
  79. package/dist/libav-demux-OWZ4T2YW.js +0 -6
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkS4WAZC2T_cjs = require('./chunk-S4WAZC2T.cjs');
4
- var chunkZCUXHW55_cjs = require('./chunk-ZCUXHW55.cjs');
4
+ var chunkBYGZN4Z5_cjs = require('./chunk-BYGZN4Z5.cjs');
5
5
  var chunk2IJ66NTD_cjs = require('./chunk-2IJ66NTD.cjs');
6
- var chunkCPZ7PXAM_cjs = require('./chunk-CPZ7PXAM.cjs');
6
+ var chunkL7A3ECI2_cjs = require('./chunk-L7A3ECI2.cjs');
7
7
  var chunkG4APZMCP_cjs = require('./chunk-G4APZMCP.cjs');
8
8
  var chunkF3LQJKXK_cjs = require('./chunk-F3LQJKXK.cjs');
9
9
 
@@ -92,7 +92,13 @@ var FALLBACK_VIDEO_CODECS = /* @__PURE__ */ new Set([
92
92
  "rv40",
93
93
  "mpeg2",
94
94
  "mpeg1",
95
- "theora"
95
+ "theora",
96
+ "dv",
97
+ "hq_hqa",
98
+ "rawvideo",
99
+ "qtrle",
100
+ "png",
101
+ "vp6f"
96
102
  ]);
97
103
  var FALLBACK_AUDIO_CODECS = /* @__PURE__ */ new Set([
98
104
  "wmav2",
@@ -728,12 +734,12 @@ async function createRemuxPipeline(ctx, video) {
728
734
  const mb = await import('mediabunny');
729
735
  const videoTrackInfo = ctx.videoTracks[0];
730
736
  if (!videoTrackInfo) throw new Error("remux: source has no video track");
731
- const mbVideoCodec = chunkZCUXHW55_cjs.avbridgeVideoToMediabunny(videoTrackInfo.codec);
737
+ const mbVideoCodec = chunkBYGZN4Z5_cjs.avbridgeVideoToMediabunny(videoTrackInfo.codec);
732
738
  if (!mbVideoCodec) {
733
739
  throw new Error(`remux: video codec "${videoTrackInfo.codec}" is not supported by mediabunny output`);
734
740
  }
735
741
  const input = new mb.Input({
736
- source: await chunkZCUXHW55_cjs.buildMediabunnySourceFromInput(mb, ctx.source),
742
+ source: await chunkBYGZN4Z5_cjs.buildMediabunnySourceFromInput(mb, ctx.source),
737
743
  formats: mb.ALL_FORMATS
738
744
  });
739
745
  const allTracks = await input.getTracks();
@@ -765,7 +771,7 @@ async function createRemuxPipeline(ctx, video) {
765
771
  throw new Error("remux: audio track not found in input");
766
772
  }
767
773
  inputAudio = newInput;
768
- mbAudioCodec = chunkZCUXHW55_cjs.avbridgeAudioToMediabunny(trackInfo.codec);
774
+ mbAudioCodec = chunkBYGZN4Z5_cjs.avbridgeAudioToMediabunny(trackInfo.codec);
769
775
  audioSink = new mb.EncodedPacketSink(newInput);
770
776
  audioConfig = await newInput.getDecoderConfig();
771
777
  }
@@ -976,6 +982,12 @@ async function createRemuxSession(context, video) {
976
982
  }
977
983
  const wasPlaying = !video.paused;
978
984
  await pipeline.seek(time, wasPlaying || wantPlay);
985
+ queueMicrotask(() => {
986
+ try {
987
+ video.dispatchEvent(new Event("seeked"));
988
+ } catch {
989
+ }
990
+ });
979
991
  },
980
992
  async setAudioTrack(id) {
981
993
  if (!context.audioTracks.some((t) => t.id === id)) {
@@ -1364,6 +1376,10 @@ var AudioOutput = class {
1364
1376
  _volume = 1;
1365
1377
  /** User-set muted flag. When true, gain is forced to 0. */
1366
1378
  _muted = false;
1379
+ /** Playback rate. Scales the media clock and each AudioBufferSourceNode's
1380
+ * playbackRate so audio pitches up/down accordingly (same as native
1381
+ * <video>.playbackRate). Default 1. */
1382
+ _rate = 1;
1367
1383
  constructor() {
1368
1384
  this.ctx = new AudioContext();
1369
1385
  this.gain = this.ctx.createGain();
@@ -1385,6 +1401,20 @@ var AudioOutput = class {
1385
1401
  getMuted() {
1386
1402
  return this._muted;
1387
1403
  }
1404
+ /** Set playback rate. Scales the media clock and pitches audio output
1405
+ * (same as native <video>.playbackRate — speed without pitch correction).
1406
+ * Rebases the anchor so the clock transition is seamless. */
1407
+ setPlaybackRate(rate) {
1408
+ if (rate === this._rate) return;
1409
+ const t = this.now();
1410
+ this.mediaTimeOfAnchor = t;
1411
+ this.ctxTimeAtAnchor = this.ctx.currentTime;
1412
+ this.wallAnchorMs = performance.now();
1413
+ this._rate = rate;
1414
+ }
1415
+ getPlaybackRate() {
1416
+ return this._rate;
1417
+ }
1388
1418
  applyGain() {
1389
1419
  const target = this._muted ? 0 : this._volume;
1390
1420
  try {
@@ -1405,12 +1435,12 @@ var AudioOutput = class {
1405
1435
  now() {
1406
1436
  if (this.noAudio) {
1407
1437
  if (this.state === "playing") {
1408
- return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3;
1438
+ return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3 * this._rate;
1409
1439
  }
1410
1440
  return this.mediaTimeOfAnchor;
1411
1441
  }
1412
1442
  if (this.state === "playing") {
1413
- return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor);
1443
+ return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor) * this._rate;
1414
1444
  }
1415
1445
  return this.mediaTimeOfAnchor;
1416
1446
  }
@@ -1462,7 +1492,8 @@ var AudioOutput = class {
1462
1492
  const node = this.ctx.createBufferSource();
1463
1493
  node.buffer = buffer;
1464
1494
  node.connect(this.gain);
1465
- let ctxStart = this.ctxTimeAtAnchor + (this.mediaTimeOfNext - this.mediaTimeOfAnchor);
1495
+ if (this._rate !== 1) node.playbackRate.value = this._rate;
1496
+ let ctxStart = this.ctxTimeAtAnchor + (this.mediaTimeOfNext - this.mediaTimeOfAnchor) / this._rate;
1466
1497
  if (ctxStart < this.ctx.currentTime) {
1467
1498
  this.ctxTimeAtAnchor = this.ctx.currentTime;
1468
1499
  this.mediaTimeOfAnchor = this.mediaTimeOfNext;
@@ -1703,6 +1734,7 @@ async function startHybridDecoder(opts) {
1703
1734
  let videoFramesDecoded = 0;
1704
1735
  let audioFramesDecoded = 0;
1705
1736
  let videoChunksFed = 0;
1737
+ let bufferedUntilSec = 0;
1706
1738
  let syntheticVideoUs = 0;
1707
1739
  let syntheticAudioUs = 0;
1708
1740
  const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);
@@ -1723,6 +1755,18 @@ async function startHybridDecoder(opts) {
1723
1755
  if (myToken !== pumpToken || destroyed) return;
1724
1756
  const videoPackets = videoStream ? packets[videoStream.index] : void 0;
1725
1757
  const audioPackets = audioStream ? packets[audioStream.index] : void 0;
1758
+ if (videoPackets && videoTimeBase) {
1759
+ for (const pkt of videoPackets) {
1760
+ const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, videoTimeBase);
1761
+ if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
1762
+ }
1763
+ }
1764
+ if (audioPackets && audioTimeBase) {
1765
+ for (const pkt of audioPackets) {
1766
+ const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, audioTimeBase);
1767
+ if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
1768
+ }
1769
+ }
1726
1770
  if (audioDec && audioPackets && audioPackets.length > 0) {
1727
1771
  await decodeAudioBatch(audioPackets, myToken);
1728
1772
  }
@@ -1733,7 +1777,7 @@ async function startHybridDecoder(opts) {
1733
1777
  const processed = await applyBSF(videoPackets);
1734
1778
  for (const pkt of processed) {
1735
1779
  if (myToken !== pumpToken || destroyed) return;
1736
- chunkCPZ7PXAM_cjs.sanitizePacketTimestamp(pkt, () => {
1780
+ chunkL7A3ECI2_cjs.sanitizePacketTimestamp(pkt, () => {
1737
1781
  const ts = syntheticVideoUs;
1738
1782
  syntheticVideoUs += videoFrameStepUs;
1739
1783
  return ts;
@@ -1812,7 +1856,7 @@ async function startHybridDecoder(opts) {
1812
1856
  const frames = allFrames;
1813
1857
  for (const f of frames) {
1814
1858
  if (myToken !== pumpToken || destroyed) return;
1815
- chunkCPZ7PXAM_cjs.sanitizeFrameTimestamp(
1859
+ chunkL7A3ECI2_cjs.sanitizeFrameTimestamp(
1816
1860
  f,
1817
1861
  () => {
1818
1862
  const ts = syntheticAudioUs;
@@ -1823,7 +1867,7 @@ async function startHybridDecoder(opts) {
1823
1867
  },
1824
1868
  audioTimeBase
1825
1869
  );
1826
- const samples = chunkCPZ7PXAM_cjs.libavFrameToInterleavedFloat32(f);
1870
+ const samples = chunkL7A3ECI2_cjs.libavFrameToInterleavedFloat32(f);
1827
1871
  if (samples) {
1828
1872
  opts.audio.schedule(samples.data, samples.channels, samples.sampleRate);
1829
1873
  audioFramesDecoded++;
@@ -1979,6 +2023,9 @@ async function startHybridDecoder(opts) {
1979
2023
  (err) => console.error("[avbridge] hybrid pump failed (post-seek):", err)
1980
2024
  );
1981
2025
  },
2026
+ bufferedUntilSec() {
2027
+ return bufferedUntilSec;
2028
+ },
1982
2029
  stats() {
1983
2030
  return {
1984
2031
  decoderType: "webcodecs-hybrid",
@@ -2094,6 +2141,14 @@ async function createHybridSession(ctx, target, transport) {
2094
2141
  get: () => ctx.duration ?? NaN
2095
2142
  });
2096
2143
  }
2144
+ Object.defineProperty(target, "playbackRate", {
2145
+ configurable: true,
2146
+ get: () => audio.getPlaybackRate(),
2147
+ set: (v) => {
2148
+ audio.setPlaybackRate(v);
2149
+ target.dispatchEvent(new Event("ratechange"));
2150
+ }
2151
+ });
2097
2152
  Object.defineProperty(target, "readyState", {
2098
2153
  configurable: true,
2099
2154
  get: () => {
@@ -2106,6 +2161,13 @@ async function createHybridSession(ctx, target, transport) {
2106
2161
  configurable: true,
2107
2162
  get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
2108
2163
  });
2164
+ Object.defineProperty(target, "buffered", {
2165
+ configurable: true,
2166
+ get: () => {
2167
+ const end = handles.bufferedUntilSec();
2168
+ return makeTimeRanges(end > 0 ? [[0, end]] : []);
2169
+ }
2170
+ });
2109
2171
  async function waitForBuffer() {
2110
2172
  const start = performance.now();
2111
2173
  while (true) {
@@ -2119,6 +2181,7 @@ async function createHybridSession(ctx, target, transport) {
2119
2181
  }
2120
2182
  async function doSeek(timeSec) {
2121
2183
  const wasPlaying = audio.isPlaying();
2184
+ target.dispatchEvent(new Event("seeking"));
2122
2185
  await audio.pause().catch(() => {
2123
2186
  });
2124
2187
  await handles.seek(timeSec).catch(
@@ -2130,7 +2193,14 @@ async function createHybridSession(ctx, target, transport) {
2130
2193
  await waitForBuffer();
2131
2194
  await audio.start();
2132
2195
  }
2196
+ target.dispatchEvent(new Event("seeked"));
2133
2197
  }
2198
+ queueMicrotask(() => {
2199
+ try {
2200
+ target.dispatchEvent(new Event("loadedmetadata"));
2201
+ } catch {
2202
+ }
2203
+ });
2134
2204
  let fatalErrorHandler = null;
2135
2205
  handles.onFatalError((reason) => fatalErrorHandler?.(reason));
2136
2206
  return {
@@ -2189,6 +2259,7 @@ async function createHybridSession(ctx, target, transport) {
2189
2259
  delete target.muted;
2190
2260
  delete target.readyState;
2191
2261
  delete target.seekable;
2262
+ delete target.playbackRate;
2192
2263
  } catch {
2193
2264
  }
2194
2265
  },
@@ -2315,6 +2386,7 @@ async function startDecoder(opts) {
2315
2386
  let pumpRunning = null;
2316
2387
  let packetsRead = 0;
2317
2388
  let videoFramesDecoded = 0;
2389
+ let bufferedUntilSec = 0;
2318
2390
  let audioFramesDecoded = 0;
2319
2391
  let watchdogFirstFrameMs = 0;
2320
2392
  let watchdogSlowSinceMs = 0;
@@ -2340,6 +2412,18 @@ async function startDecoder(opts) {
2340
2412
  if (myToken !== pumpToken || destroyed) return;
2341
2413
  const videoPackets = videoStream ? packets[videoStream.index] : void 0;
2342
2414
  const audioPackets = audioStream ? packets[audioStream.index] : void 0;
2415
+ if (videoPackets && videoTimeBase) {
2416
+ for (const pkt of videoPackets) {
2417
+ const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, videoTimeBase);
2418
+ if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
2419
+ }
2420
+ }
2421
+ if (audioPackets && audioTimeBase) {
2422
+ for (const pkt of audioPackets) {
2423
+ const sec = chunkL7A3ECI2_cjs.packetPtsSec(pkt, audioTimeBase);
2424
+ if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
2425
+ }
2426
+ }
2343
2427
  if (audioDec && audioPackets && audioPackets.length > 0) {
2344
2428
  await decodeAudioBatch(audioPackets, myToken);
2345
2429
  }
@@ -2424,7 +2508,7 @@ async function startDecoder(opts) {
2424
2508
  if (myToken !== pumpToken || destroyed) return;
2425
2509
  for (const f of frames) {
2426
2510
  if (myToken !== pumpToken || destroyed) return;
2427
- chunkCPZ7PXAM_cjs.sanitizeFrameTimestamp(
2511
+ chunkL7A3ECI2_cjs.sanitizeFrameTimestamp(
2428
2512
  f,
2429
2513
  () => {
2430
2514
  const ts = syntheticVideoUs;
@@ -2462,7 +2546,7 @@ async function startDecoder(opts) {
2462
2546
  if (myToken !== pumpToken || destroyed) return;
2463
2547
  for (const f of frames) {
2464
2548
  if (myToken !== pumpToken || destroyed) return;
2465
- chunkCPZ7PXAM_cjs.sanitizeFrameTimestamp(
2549
+ chunkL7A3ECI2_cjs.sanitizeFrameTimestamp(
2466
2550
  f,
2467
2551
  () => {
2468
2552
  const ts = syntheticAudioUs;
@@ -2473,7 +2557,7 @@ async function startDecoder(opts) {
2473
2557
  },
2474
2558
  audioTimeBase
2475
2559
  );
2476
- const samples = chunkCPZ7PXAM_cjs.libavFrameToInterleavedFloat32(f);
2560
+ const samples = chunkL7A3ECI2_cjs.libavFrameToInterleavedFloat32(f);
2477
2561
  if (samples) {
2478
2562
  opts.audio.schedule(samples.data, samples.channels, samples.sampleRate);
2479
2563
  audioFramesDecoded++;
@@ -2621,6 +2705,9 @@ async function startDecoder(opts) {
2621
2705
  (err) => console.error("[avbridge] decoder pump failed (post-seek):", err)
2622
2706
  );
2623
2707
  },
2708
+ bufferedUntilSec() {
2709
+ return bufferedUntilSec;
2710
+ },
2624
2711
  stats() {
2625
2712
  return {
2626
2713
  decoderType: "libav-wasm",
@@ -2708,6 +2795,14 @@ async function createFallbackSession(ctx, target, transport) {
2708
2795
  get: () => ctx.duration ?? NaN
2709
2796
  });
2710
2797
  }
2798
+ Object.defineProperty(target, "playbackRate", {
2799
+ configurable: true,
2800
+ get: () => audio.getPlaybackRate(),
2801
+ set: (v) => {
2802
+ audio.setPlaybackRate(v);
2803
+ target.dispatchEvent(new Event("ratechange"));
2804
+ }
2805
+ });
2711
2806
  Object.defineProperty(target, "readyState", {
2712
2807
  configurable: true,
2713
2808
  get: () => {
@@ -2720,6 +2815,13 @@ async function createFallbackSession(ctx, target, transport) {
2720
2815
  configurable: true,
2721
2816
  get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
2722
2817
  });
2818
+ Object.defineProperty(target, "buffered", {
2819
+ configurable: true,
2820
+ get: () => {
2821
+ const end = handles.bufferedUntilSec();
2822
+ return makeTimeRanges(end > 0 ? [[0, end]] : []);
2823
+ }
2824
+ });
2723
2825
  async function waitForBuffer() {
2724
2826
  const start = performance.now();
2725
2827
  let firstFrameAtMs = 0;
@@ -2759,6 +2861,7 @@ async function createFallbackSession(ctx, target, transport) {
2759
2861
  }
2760
2862
  async function doSeek(timeSec) {
2761
2863
  const wasPlaying = audio.isPlaying();
2864
+ target.dispatchEvent(new Event("seeking"));
2762
2865
  await audio.pause().catch(() => {
2763
2866
  });
2764
2867
  await handles.seek(timeSec).catch(
@@ -2770,7 +2873,14 @@ async function createFallbackSession(ctx, target, transport) {
2770
2873
  await waitForBuffer();
2771
2874
  await audio.start();
2772
2875
  }
2876
+ target.dispatchEvent(new Event("seeked"));
2773
2877
  }
2878
+ queueMicrotask(() => {
2879
+ try {
2880
+ target.dispatchEvent(new Event("loadedmetadata"));
2881
+ } catch {
2882
+ }
2883
+ });
2774
2884
  return {
2775
2885
  strategy: "fallback",
2776
2886
  async play() {
@@ -2824,6 +2934,7 @@ async function createFallbackSession(ctx, target, transport) {
2824
2934
  delete target.muted;
2825
2935
  delete target.readyState;
2826
2936
  delete target.seekable;
2937
+ delete target.playbackRate;
2827
2938
  } catch {
2828
2939
  }
2829
2940
  },
@@ -2962,7 +3073,7 @@ var UnifiedPlayer = class _UnifiedPlayer {
2962
3073
  const bootstrapStart = performance.now();
2963
3074
  try {
2964
3075
  chunkG4APZMCP_cjs.dbg.info("bootstrap", "start");
2965
- const ctx = await chunkG4APZMCP_cjs.dbg.timed("probe", "probe", 3e3, () => chunkZCUXHW55_cjs.probe(this.options.source, this.transport));
3076
+ const ctx = await chunkG4APZMCP_cjs.dbg.timed("probe", "probe", 3e3, () => chunkBYGZN4Z5_cjs.probe(this.options.source, this.transport));
2966
3077
  chunkG4APZMCP_cjs.dbg.info(
2967
3078
  "probe",
2968
3079
  `container=${ctx.container} video=${ctx.videoTracks[0]?.codec ?? "-"} audio=${ctx.audioTracks[0]?.codec ?? "-"} probedBy=${ctx.probedBy}`
@@ -3432,5 +3543,5 @@ exports.NATIVE_VIDEO_CODECS = NATIVE_VIDEO_CODECS;
3432
3543
  exports.UnifiedPlayer = UnifiedPlayer;
3433
3544
  exports.classifyContext = classifyContext;
3434
3545
  exports.createPlayer = createPlayer;
3435
- //# sourceMappingURL=chunk-YX4AGLNF.cjs.map
3436
- //# sourceMappingURL=chunk-YX4AGLNF.cjs.map
3546
+ //# sourceMappingURL=chunk-NQULEIA3.cjs.map
3547
+ //# sourceMappingURL=chunk-NQULEIA3.cjs.map