@remotion/media-parser 4.0.286 → 4.0.288

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 (243) hide show
  1. package/dist/containers/flac/get-channel-count.d.ts +1 -1
  2. package/dist/containers/flac/get-seeking-byte.d.ts +6 -0
  3. package/dist/containers/flac/get-seeking-byte.js +26 -0
  4. package/dist/containers/flac/parse-meta.d.ts +6 -0
  5. package/dist/containers/flac/parse-meta.js +31 -0
  6. package/dist/containers/flac/seeking-hints.d.ts +15 -0
  7. package/dist/containers/flac/seeking-hints.js +19 -0
  8. package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.d.ts +2 -2
  9. package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.js +6 -3
  10. package/dist/containers/iso-base-media/collect-sample-positions-from-trak.js +7 -5
  11. package/dist/containers/iso-base-media/get-keyframes.js +1 -1
  12. package/dist/containers/iso-base-media/get-sample-positions-from-track.d.ts +2 -2
  13. package/dist/containers/iso-base-media/get-seeking-byte.d.ts +15 -0
  14. package/dist/containers/iso-base-media/{get-seeking-from-mp4.js → get-seeking-byte.js} +16 -2
  15. package/dist/containers/iso-base-media/mdat/mdat.js +13 -5
  16. package/dist/containers/iso-base-media/mdat/postprocess-bytes.d.ts +5 -0
  17. package/dist/containers/iso-base-media/mdat/postprocess-bytes.js +25 -0
  18. package/dist/containers/iso-base-media/process-box.js +5 -3
  19. package/dist/containers/iso-base-media/{get-seeking-info-from-mp4.d.ts → seeking-hints.d.ts} +8 -3
  20. package/dist/containers/iso-base-media/seeking-hints.js +53 -0
  21. package/dist/containers/iso-base-media/should-group-audio-samples.d.ts +6 -0
  22. package/dist/containers/iso-base-media/should-group-audio-samples.js +16 -0
  23. package/dist/containers/iso-base-media/traversal.d.ts +4 -2
  24. package/dist/containers/iso-base-media/traversal.js +6 -5
  25. package/dist/containers/m3u/iterate-over-segment-files.js +23 -20
  26. package/dist/containers/riff/parse-video-section.js +1 -1
  27. package/dist/containers/transport-stream/handle-aac-packet.js +4 -1
  28. package/dist/containers/transport-stream/handle-avc-packet.js +4 -1
  29. package/dist/containers/transport-stream/seeking-hints.d.ts +9 -0
  30. package/dist/containers/transport-stream/seeking-hints.js +26 -0
  31. package/dist/containers/wav/get-seeking-byte.d.ts +2 -2
  32. package/dist/containers/wav/get-seeking-byte.js +2 -2
  33. package/dist/containers/wav/seeking-hints.d.ts +12 -0
  34. package/dist/containers/wav/seeking-hints.js +25 -0
  35. package/dist/containers/webm/seek/get-seeking-byte.d.ts +3 -5
  36. package/dist/containers/webm/seek/get-seeking-byte.js +5 -5
  37. package/dist/containers/webm/seek/seeking-hints.d.ts +10 -0
  38. package/dist/containers/webm/seek/seeking-hints.js +28 -0
  39. package/dist/controller/media-parser-controller.d.ts +3 -0
  40. package/dist/controller/media-parser-controller.js +15 -0
  41. package/dist/download-and-parse-media.js +2 -1
  42. package/dist/emit-available-info.js +1 -1
  43. package/dist/esm/index.mjs +491 -208
  44. package/dist/esm/node-writer.mjs +1 -2
  45. package/dist/esm/node.mjs +1 -2
  46. package/dist/esm/server-worker.mjs +46 -1
  47. package/dist/esm/universal.mjs +2 -4
  48. package/dist/esm/web.mjs +1 -2
  49. package/dist/esm/worker-server-entry.mjs +527 -215
  50. package/dist/esm/worker-web-entry.mjs +526 -213
  51. package/dist/esm/worker.mjs +46 -1
  52. package/dist/{forward-controller.d.ts → forward-controller-pause-resume-abort.d.ts} +1 -1
  53. package/dist/{forward-controller.js → forward-controller-pause-resume-abort.js} +3 -3
  54. package/dist/get-audio-codec.d.ts +1 -0
  55. package/dist/get-audio-codec.js +15 -4
  56. package/dist/get-dimensions.js +1 -1
  57. package/dist/get-duration.js +3 -2
  58. package/dist/get-fps.js +1 -0
  59. package/dist/get-is-hdr.js +2 -2
  60. package/dist/get-keyframes.js +1 -1
  61. package/dist/get-sample-positions-from-mp4.d.ts +4 -1
  62. package/dist/get-sample-positions-from-mp4.js +3 -1
  63. package/dist/get-sample-positions.d.ts +2 -0
  64. package/dist/get-sample-positions.js +2 -0
  65. package/dist/get-seeking-byte.d.ts +7 -5
  66. package/dist/get-seeking-byte.js +13 -12
  67. package/dist/{get-seeking-info.d.ts → get-seeking-hints.d.ts} +7 -3
  68. package/dist/get-seeking-hints.js +35 -0
  69. package/dist/get-tracks.d.ts +4 -4
  70. package/dist/get-tracks.js +8 -6
  71. package/dist/get-video-codec.js +2 -2
  72. package/dist/has-all-info.js +1 -1
  73. package/dist/index.d.ts +31 -3
  74. package/dist/internal-parse-media.js +16 -1
  75. package/dist/iterator/buffer-iterator.js +3 -4
  76. package/dist/metadata/metadata-from-iso.js +1 -0
  77. package/dist/options.d.ts +2 -0
  78. package/dist/parse-media-on-worker-entry.js +51 -1
  79. package/dist/parse-media.js +2 -1
  80. package/dist/samples-from-moof.d.ts +2 -2
  81. package/dist/samples-from-moof.js +7 -8
  82. package/dist/seeking-hints.d.ts +39 -0
  83. package/dist/set-seeking-hints.d.ts +6 -0
  84. package/dist/set-seeking-hints.js +27 -0
  85. package/dist/state/audio-sample-map.d.ts +11 -0
  86. package/dist/state/audio-sample-map.js +21 -0
  87. package/dist/state/has-tracks-section.js +3 -1
  88. package/dist/state/iso-base-media/cached-sample-positions.js +1 -1
  89. package/dist/state/iso-base-media/iso-state.d.ts +18 -2
  90. package/dist/state/iso-base-media/iso-state.js +4 -0
  91. package/dist/state/iso-base-media/lazy-mfra-load.d.ts +3 -0
  92. package/dist/state/iso-base-media/lazy-mfra-load.js +13 -0
  93. package/dist/state/iso-base-media/moov-box.d.ts +7 -2
  94. package/dist/state/iso-base-media/moov-box.js +1 -1
  95. package/dist/state/iso-base-media/precomputed-moof.d.ts +11 -0
  96. package/dist/state/iso-base-media/precomputed-moof.js +28 -0
  97. package/dist/state/iso-base-media/precomputed-tfra.d.ts +6 -0
  98. package/dist/state/iso-base-media/precomputed-tfra.js +17 -0
  99. package/dist/state/keyframes.d.ts +2 -0
  100. package/dist/state/keyframes.js +17 -9
  101. package/dist/state/matroska/lazy-cues-fetch.d.ts +7 -1
  102. package/dist/state/matroska/lazy-cues-fetch.js +21 -0
  103. package/dist/state/matroska/webm.d.ts +7 -0
  104. package/dist/state/matroska/webm.js +9 -1
  105. package/dist/state/parser-state.d.ts +31 -3
  106. package/dist/state/samples-observed/slow-duration-fps.js +0 -3
  107. package/dist/state/transport-stream/observed-pes-header.d.ts +2 -0
  108. package/dist/state/transport-stream/observed-pes-header.js +22 -12
  109. package/dist/state/transport-stream/pts-start-offset.d.ts +4 -1
  110. package/dist/state/transport-stream/pts-start-offset.js +1 -1
  111. package/dist/state/transport-stream/transport-stream.d.ts +5 -1
  112. package/dist/version.d.ts +1 -1
  113. package/dist/version.js +1 -1
  114. package/dist/with-resolvers.d.ts +5 -0
  115. package/dist/work-on-seek-request.js +8 -5
  116. package/dist/worker/{forward-controller.js → forward-controller-to-worker.js} +17 -0
  117. package/dist/worker/serialize-error.d.ts +6 -1
  118. package/dist/worker/serialize-error.js +2 -1
  119. package/dist/worker/worker-types.d.ts +12 -2
  120. package/dist/worker-server.js +16 -5
  121. package/package.json +3 -3
  122. package/dist/containers/iso-base-media/get-mfra-atom.d.ts +0 -9
  123. package/dist/containers/iso-base-media/get-mfra-atom.js +0 -12
  124. package/dist/containers/iso-base-media/get-seeking-from-mp4.d.ts +0 -11
  125. package/dist/containers/iso-base-media/get-seeking-info-from-mp4.js +0 -25
  126. package/dist/containers/iso-base-media/mfra/mfra.d.ts +0 -2
  127. package/dist/containers/iso-base-media/mfra/mfra.js +0 -11
  128. package/dist/containers/transport-stream/get-seeking-info.d.ts +0 -4
  129. package/dist/containers/transport-stream/get-seeking-info.js +0 -17
  130. package/dist/containers/transport-stream/next-pes-header-store.d.ts +0 -6
  131. package/dist/containers/transport-stream/next-pes-header-store.js +0 -18
  132. package/dist/containers/transport-stream/start-offset.d.ts +0 -4
  133. package/dist/containers/transport-stream/start-offset.js +0 -13
  134. package/dist/containers/wav/get-seeking-info.d.ts +0 -7
  135. package/dist/containers/wav/get-seeking-info.js +0 -20
  136. package/dist/containers/wav/parse-video-section.d.ts +0 -5
  137. package/dist/containers/wav/parse-video-section.js +0 -41
  138. package/dist/containers/webm/cues/fetch-web-cues.d.ts +0 -12
  139. package/dist/containers/webm/cues/fetch-web-cues.js +0 -32
  140. package/dist/containers/webm/cues/format-cues.d.ts +0 -8
  141. package/dist/containers/webm/cues/format-cues.js +0 -41
  142. package/dist/containers/webm/cues/get-seeking-byte.d.ts +0 -14
  143. package/dist/containers/webm/cues/get-seeking-byte.js +0 -91
  144. package/dist/containers/webm/fetch-web-cues.d.ts +0 -12
  145. package/dist/containers/webm/fetch-web-cues.js +0 -29
  146. package/dist/containers/webm/get-seeking-byte.d.ts +0 -14
  147. package/dist/containers/webm/get-seeking-byte.js +0 -91
  148. package/dist/containers/webm/get-seeking-info.d.ts +0 -3
  149. package/dist/containers/webm/get-seeking-info.js +0 -17
  150. package/dist/containers/webm/seek/get-seeking-info.d.ts +0 -3
  151. package/dist/containers/webm/seek/get-seeking-info.js +0 -17
  152. package/dist/emitter.d.ts +0 -33
  153. package/dist/emitter.js +0 -65
  154. package/dist/get-sample-positions-from-lpcm.d.ts +0 -3
  155. package/dist/get-sample-positions-from-lpcm.js +0 -46
  156. package/dist/get-seeking-info.js +0 -35
  157. package/dist/media-parser-controller.d.ts +0 -21
  158. package/dist/media-parser-controller.js +0 -38
  159. package/dist/pause-signal.d.ts +0 -11
  160. package/dist/pause-signal.js +0 -38
  161. package/dist/readers/state/aac-state.d.ts +0 -13
  162. package/dist/readers/state/aac-state.js +0 -17
  163. package/dist/readers/state/can-skip-tracks.d.ts +0 -16
  164. package/dist/readers/state/can-skip-tracks.js +0 -60
  165. package/dist/readers/state/current-reader.d.ts +0 -6
  166. package/dist/readers/state/current-reader.js +0 -13
  167. package/dist/readers/state/emitted-fields.d.ts +0 -1
  168. package/dist/readers/state/emitted-fields.js +0 -37
  169. package/dist/readers/state/flac-state.d.ts +0 -4
  170. package/dist/readers/state/flac-state.js +0 -13
  171. package/dist/readers/state/has-tracks-section.d.ts +0 -14
  172. package/dist/readers/state/has-tracks-section.js +0 -37
  173. package/dist/readers/state/images.d.ts +0 -9
  174. package/dist/readers/state/images.js +0 -14
  175. package/dist/readers/state/iso-base-media/cached-sample-positions.d.ts +0 -12
  176. package/dist/readers/state/iso-base-media/cached-sample-positions.js +0 -46
  177. package/dist/readers/state/iso-base-media/iso-state.d.ts +0 -24
  178. package/dist/readers/state/iso-base-media/iso-state.js +0 -20
  179. package/dist/readers/state/iso-base-media/lazy-mfra-load.d.ts +0 -13
  180. package/dist/readers/state/iso-base-media/lazy-mfra-load.js +0 -29
  181. package/dist/readers/state/iso-base-media/moov-box.d.ts +0 -5
  182. package/dist/readers/state/iso-base-media/moov-box.js +0 -13
  183. package/dist/readers/state/keyframes.d.ts +0 -6
  184. package/dist/readers/state/keyframes.js +0 -15
  185. package/dist/readers/state/m3u-state.d.ts +0 -44
  186. package/dist/readers/state/m3u-state.js +0 -124
  187. package/dist/readers/state/may-skip-video-data.d.ts +0 -4
  188. package/dist/readers/state/may-skip-video-data.js +0 -18
  189. package/dist/readers/state/mp3.d.ts +0 -15
  190. package/dist/readers/state/mp3.js +0 -19
  191. package/dist/readers/state/need-samples-for-fields.d.ts +0 -6
  192. package/dist/readers/state/need-samples-for-fields.js +0 -39
  193. package/dist/readers/state/parser-state.d.ts +0 -252
  194. package/dist/readers/state/parser-state.js +0 -124
  195. package/dist/readers/state/riff.d.ts +0 -10
  196. package/dist/readers/state/riff.js +0 -32
  197. package/dist/readers/state/sample-callbacks.d.ts +0 -44
  198. package/dist/readers/state/sample-callbacks.js +0 -118
  199. package/dist/readers/state/seek-infinite-loop.d.ts +0 -5
  200. package/dist/readers/state/seek-infinite-loop.js +0 -22
  201. package/dist/readers/state/slow-duration-fps.d.ts +0 -11
  202. package/dist/readers/state/slow-duration-fps.js +0 -86
  203. package/dist/readers/state/structure.d.ts +0 -15
  204. package/dist/readers/state/structure.js +0 -78
  205. package/dist/readers/state/timings.d.ts +0 -8
  206. package/dist/readers/state/timings.js +0 -13
  207. package/dist/readers/state/transport-stream/last-emitted-sample.d.ts +0 -6
  208. package/dist/readers/state/transport-stream/last-emitted-sample.js +0 -16
  209. package/dist/readers/state/transport-stream/next-pes-header-store.d.ts +0 -6
  210. package/dist/readers/state/transport-stream/next-pes-header-store.js +0 -18
  211. package/dist/readers/state/transport-stream/start-offset.d.ts +0 -4
  212. package/dist/readers/state/transport-stream/start-offset.js +0 -13
  213. package/dist/readers/state/transport-stream/transport-stream.d.ts +0 -19
  214. package/dist/readers/state/transport-stream/transport-stream.js +0 -25
  215. package/dist/readers/state/video-section.d.ts +0 -33
  216. package/dist/readers/state/video-section.js +0 -65
  217. package/dist/readers/state/webm.d.ts +0 -28
  218. package/dist/readers/state/webm.js +0 -109
  219. package/dist/seek-signal.d.ts +0 -19
  220. package/dist/seek-signal.js +0 -24
  221. package/dist/seeking-info.d.ts +0 -31
  222. package/dist/server-worker.module.d.ts +0 -2
  223. package/dist/server-worker.module.js +0 -12
  224. package/dist/state/matroska/lazy-seek-fetch.d.ts +0 -1
  225. package/dist/state/matroska/lazy-seek-fetch.js +0 -5
  226. package/dist/state/matroska.d.ts +0 -0
  227. package/dist/state/matroska.js +0 -1
  228. package/dist/state/slow-duration-fps.d.ts +0 -11
  229. package/dist/state/slow-duration-fps.js +0 -86
  230. package/dist/state/transport-stream/start-offset.d.ts +0 -5
  231. package/dist/state/transport-stream/start-offset.js +0 -13
  232. package/dist/state/transport-stream.d.ts +0 -8
  233. package/dist/state/transport-stream.js +0 -11
  234. package/dist/state/uml.d.ts +0 -32
  235. package/dist/state/uml.js +0 -52
  236. package/dist/state/webm.d.ts +0 -30
  237. package/dist/state/webm.js +0 -109
  238. package/dist/state/work-on-seek-request-options.d.ts +0 -3
  239. package/dist/state/work-on-seek-request-options.js +0 -26
  240. package/dist/worker.module.d.ts +0 -4
  241. package/dist/worker.module.js +0 -12
  242. /package/dist/{seeking-info.js → seeking-hints.js} +0 -0
  243. /package/dist/worker/{forward-controller.d.ts → forward-controller-to-worker.d.ts} +0 -0
@@ -242,8 +242,7 @@ var fetchReadContent = async ({
242
242
  });
243
243
  if (controller) {
244
244
  controller._internals.signal.addEventListener("abort", () => {
245
- reader.reader.cancel().catch(() => {
246
- });
245
+ reader.reader.cancel().catch(() => {});
247
246
  }, { once: true });
248
247
  }
249
248
  return {
@@ -537,6 +536,19 @@ var mediaParserController = () => {
537
536
  }
538
537
  await pauseSignal.waitUntilResume();
539
538
  };
539
+ let seekingHintResolution = null;
540
+ const getSeekingHints = () => {
541
+ if (!seekingHintResolution) {
542
+ throw new Error("The mediaParserController() was not yet used in a parseMedia() call");
543
+ }
544
+ return seekingHintResolution();
545
+ };
546
+ const attachSeekingHintResolution = (callback) => {
547
+ if (seekingHintResolution) {
548
+ throw new Error("The mediaParserController() was used in multiple parseMedia() calls. Create a separate controller for each call.");
549
+ }
550
+ seekingHintResolution = callback;
551
+ };
540
552
  return {
541
553
  abort: (reason) => {
542
554
  abortController.abort(reason);
@@ -547,12 +559,14 @@ var mediaParserController = () => {
547
559
  resume: pauseSignal.resume,
548
560
  addEventListener: emitter.addEventListener,
549
561
  removeEventListener: emitter.removeEventListener,
562
+ getSeekingHints,
550
563
  _internals: {
551
564
  signal: abortController.signal,
552
565
  checkForAbortAndPause,
553
566
  seekSignal,
554
567
  markAsReadyToEmitEvents: emitter.markAsReady,
555
- performedSeeksSignal
568
+ performedSeeksSignal,
569
+ attachSeekingHintResolution
556
570
  }
557
571
  };
558
572
  };
@@ -634,6 +648,29 @@ var m3uHasStreams = (state) => {
634
648
  return state.m3u.hasFinishedManifest();
635
649
  };
636
650
 
651
+ // src/state/iso-base-media/precomputed-moof.ts
652
+ var precomputedMoofState = () => {
653
+ let moofBoxes = [];
654
+ return {
655
+ getMoofBoxes: () => moofBoxes,
656
+ setMoofBoxes: (boxes) => {
657
+ moofBoxes = boxes;
658
+ }
659
+ };
660
+ };
661
+ var toMoofBox = (box) => {
662
+ if (box.type !== "regular-box") {
663
+ throw new Error("expected regular bpx");
664
+ }
665
+ return {
666
+ offset: box.offset,
667
+ trafBoxes: box.children.filter((c) => c.type === "regular-box" && c.boxType === "traf")
668
+ };
669
+ };
670
+ var deduplicateMoofBoxesByOffset = (moofBoxes) => {
671
+ return moofBoxes.filter((m, i, arr) => i === arr.findIndex((t) => t.offset === m.offset));
672
+ };
673
+
637
674
  // src/containers/iso-base-media/traversal.ts
638
675
  var getMoovFromFromIsoStructure = (structure) => {
639
676
  const moovBox = structure.boxes.find((s) => s.type === "moov-box");
@@ -645,11 +682,12 @@ var getMoovFromFromIsoStructure = (structure) => {
645
682
  var getMoovBoxFromState = ({
646
683
  structureState,
647
684
  isoState,
648
- mp4HeaderSegment
685
+ mp4HeaderSegment,
686
+ mayUsePrecomputed
649
687
  }) => {
650
- const got = isoState.moov.getMoovBox();
651
- if (got) {
652
- return got;
688
+ const got = isoState.moov.getMoovBoxAndPrecomputed();
689
+ if (got && (mayUsePrecomputed || !got.precomputed)) {
690
+ return got.moovBox;
653
691
  }
654
692
  if (mp4HeaderSegment) {
655
693
  return getMoovFromFromIsoStructure(mp4HeaderSegment);
@@ -659,7 +697,7 @@ var getMoovBoxFromState = ({
659
697
  };
660
698
  var getMoofBoxes = (main) => {
661
699
  const moofBoxes = main.filter((s) => s.type === "regular-box" && s.boxType === "moof");
662
- return moofBoxes;
700
+ return moofBoxes.map((m) => toMoofBox(m));
663
701
  };
664
702
  var getMvhdBox = (moovBox) => {
665
703
  const mvHdBox = moovBox.children.find((s) => s.type === "mvhd-box");
@@ -931,7 +969,8 @@ var getFpsFromIsoMaseMedia = (state) => {
931
969
  const moovBox = getMoovBoxFromState({
932
970
  structureState: state.structure,
933
971
  isoState: state.iso,
934
- mp4HeaderSegment: state.mp4HeaderSegment
972
+ mp4HeaderSegment: state.mp4HeaderSegment,
973
+ mayUsePrecomputed: true
935
974
  });
936
975
  if (!moovBox) {
937
976
  return null;
@@ -2089,6 +2128,40 @@ var detectFileType = (data) => {
2089
2128
  return { type: "unknown" };
2090
2129
  };
2091
2130
 
2131
+ // src/log.ts
2132
+ var logLevels = ["trace", "verbose", "info", "warn", "error"];
2133
+ var getNumberForLogLevel = (level) => {
2134
+ return logLevels.indexOf(level);
2135
+ };
2136
+ var isEqualOrBelowLogLevel = (currentLevel, level) => {
2137
+ return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
2138
+ };
2139
+ var Log = {
2140
+ trace: (logLevel, ...args) => {
2141
+ if (isEqualOrBelowLogLevel(logLevel, "trace")) {
2142
+ return console.log(...args);
2143
+ }
2144
+ },
2145
+ verbose: (logLevel, ...args) => {
2146
+ if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
2147
+ return console.log(...args);
2148
+ }
2149
+ },
2150
+ info: (logLevel, ...args) => {
2151
+ if (isEqualOrBelowLogLevel(logLevel, "info")) {
2152
+ return console.log(...args);
2153
+ }
2154
+ },
2155
+ warn: (logLevel, ...args) => {
2156
+ if (isEqualOrBelowLogLevel(logLevel, "warn")) {
2157
+ return console.warn(...args);
2158
+ }
2159
+ },
2160
+ error: (...args) => {
2161
+ return console.error(...args);
2162
+ }
2163
+ };
2164
+
2092
2165
  // src/iterator/buffer-manager.ts
2093
2166
  var bufferManager = ({
2094
2167
  initialData,
@@ -2292,8 +2365,7 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
2292
2365
  };
2293
2366
  const getPaddedFourByteNumber = () => {
2294
2367
  let lastInt = 128;
2295
- while (lastInt = getUint8(), lastInt === 128) {
2296
- }
2368
+ while (lastInt = getUint8(), lastInt === 128) {}
2297
2369
  return lastInt;
2298
2370
  };
2299
2371
  const getUint32 = () => {
@@ -2361,11 +2433,11 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
2361
2433
  return (1 << zerosCount) - 1 + suffix;
2362
2434
  };
2363
2435
  const peekB = (length) => {
2364
- console.log([...getSlice(length)].map((b) => b.toString(16).padStart(2, "0")));
2436
+ Log.info("info", [...getSlice(length)].map((b) => b.toString(16).padStart(2, "0")));
2365
2437
  counter.decrement(length);
2366
2438
  };
2367
2439
  const peekD = (length) => {
2368
- console.log([...getSlice(length)].map((b) => b));
2440
+ Log.info("info", [...getSlice(length)].map((b) => b.toString(16).padStart(2, "0")));
2369
2441
  counter.decrement(length);
2370
2442
  };
2371
2443
  const leb128 = () => {
@@ -2702,11 +2774,11 @@ var parseAv1PrivateData = (data, colrAtom) => {
2702
2774
 
2703
2775
  // src/get-video-codec.ts
2704
2776
  var getVideoCodec = (state) => {
2705
- const track = getTracks(state);
2777
+ const track = getTracks(state, true);
2706
2778
  return track.videoTracks[0]?.codecWithoutConfig ?? null;
2707
2779
  };
2708
2780
  var hasVideoCodec = (state) => {
2709
- return getHasTracks(state);
2781
+ return getHasTracks(state, true);
2710
2782
  };
2711
2783
  var getVideoPrivateData = (trakBox) => {
2712
2784
  const videoSample = getStsdVideoConfig(trakBox);
@@ -3951,14 +4023,15 @@ var matroskaHasTracks = ({
3951
4023
  };
3952
4024
 
3953
4025
  // src/get-tracks.ts
3954
- var isoBaseMediaHasTracks = (state) => {
4026
+ var isoBaseMediaHasTracks = (state, mayUsePrecomputed) => {
3955
4027
  return Boolean(getMoovBoxFromState({
3956
4028
  structureState: state.structure,
3957
4029
  isoState: state.iso,
3958
- mp4HeaderSegment: state.mp4HeaderSegment
4030
+ mp4HeaderSegment: state.mp4HeaderSegment,
4031
+ mayUsePrecomputed
3959
4032
  }));
3960
4033
  };
3961
- var getHasTracks = (state) => {
4034
+ var getHasTracks = (state, mayUsePrecomputed) => {
3962
4035
  const structure = state.structure.getStructure();
3963
4036
  if (structure.type === "matroska") {
3964
4037
  return matroskaHasTracks({
@@ -3967,7 +4040,7 @@ var getHasTracks = (state) => {
3967
4040
  });
3968
4041
  }
3969
4042
  if (structure.type === "iso-base-media") {
3970
- return isoBaseMediaHasTracks(state);
4043
+ return isoBaseMediaHasTracks(state, mayUsePrecomputed);
3971
4044
  }
3972
4045
  if (structure.type === "riff") {
3973
4046
  return hasAllTracksFromAvi(state);
@@ -4039,11 +4112,12 @@ var getTracksFromMoovBox = (moovBox) => {
4039
4112
  otherTracks
4040
4113
  };
4041
4114
  };
4042
- var getTracksFromIsoBaseMedia = (state) => {
4115
+ var getTracksFromIsoBaseMedia = (state, mayUsePrecomputed) => {
4043
4116
  const moovBox = getMoovBoxFromState({
4044
4117
  structureState: state.structure,
4045
4118
  isoState: state.iso,
4046
- mp4HeaderSegment: state.mp4HeaderSegment
4119
+ mp4HeaderSegment: state.mp4HeaderSegment,
4120
+ mayUsePrecomputed
4047
4121
  });
4048
4122
  if (!moovBox) {
4049
4123
  return {
@@ -4065,13 +4139,13 @@ var defaultGetTracks = (parserState) => {
4065
4139
  videoTracks: tracks2.filter((t) => t.type === "video")
4066
4140
  };
4067
4141
  };
4068
- var getTracks = (state) => {
4142
+ var getTracks = (state, mayUsePrecomputed) => {
4069
4143
  const structure = state.structure.getStructure();
4070
4144
  if (structure.type === "matroska") {
4071
4145
  return getCategorizedTracksFromMatroska(state);
4072
4146
  }
4073
4147
  if (structure.type === "iso-base-media") {
4074
- return getTracksFromIsoBaseMedia(state);
4148
+ return getTracksFromIsoBaseMedia(state, mayUsePrecomputed);
4075
4149
  }
4076
4150
  if (structure.type === "riff") {
4077
4151
  return getTracksFromAvi(structure, state);
@@ -4087,7 +4161,7 @@ var getTracks = (state) => {
4087
4161
 
4088
4162
  // src/get-audio-codec.ts
4089
4163
  var getAudioCodec = (parserState) => {
4090
- const tracks2 = getTracks(parserState);
4164
+ const tracks2 = getTracks(parserState, true);
4091
4165
  const allTracks = tracks2.audioTracks.length + tracks2.otherTracks.length + tracks2.videoTracks.length;
4092
4166
  if (allTracks === 0) {
4093
4167
  throw new Error("No tracks yet");
@@ -4102,7 +4176,7 @@ var getAudioCodec = (parserState) => {
4102
4176
  return null;
4103
4177
  };
4104
4178
  var hasAudioCodec = (state) => {
4105
- return getHasTracks(state);
4179
+ return getHasTracks(state, true);
4106
4180
  };
4107
4181
  var getCodecSpecificatorFromEsdsBox = ({
4108
4182
  child
@@ -4224,6 +4298,9 @@ var isLpcmAudioCodec = (trak) => {
4224
4298
  var isIn24AudioCodec = (trak) => {
4225
4299
  return getAudioCodecFromTrak(trak)?.format === "in24";
4226
4300
  };
4301
+ var isTwosAudioCodec = (trak) => {
4302
+ return getAudioCodecFromTrak(trak)?.format === "twos";
4303
+ };
4227
4304
  var getAudioCodecStringFromTrak = (trak) => {
4228
4305
  const codec = getAudioCodecFromTrak(trak);
4229
4306
  if (!codec) {
@@ -4235,10 +4312,16 @@ var getAudioCodecStringFromTrak = (trak) => {
4235
4312
  description: codec.description
4236
4313
  };
4237
4314
  }
4315
+ if (codec.format === "twos") {
4316
+ return {
4317
+ codecString: "pcm-s16",
4318
+ description: codec.description
4319
+ };
4320
+ }
4238
4321
  if (codec.format === "in24") {
4239
4322
  return {
4240
4323
  codecString: "pcm-s24",
4241
- description: undefined
4324
+ description: codec.description
4242
4325
  };
4243
4326
  }
4244
4327
  const codecStringWithoutMp3Exception = [
@@ -4338,7 +4421,7 @@ var getDimensions = (state) => {
4338
4421
  if (structure && isAudioStructure(structure)) {
4339
4422
  return null;
4340
4423
  }
4341
- const { videoTracks } = getTracks(state);
4424
+ const { videoTracks } = getTracks(state, true);
4342
4425
  if (!videoTracks.length) {
4343
4426
  return null;
4344
4427
  }
@@ -4418,7 +4501,9 @@ var getSamplesFromTraf = (trafSegment, moofOffset) => {
4418
4501
  duration: duration2,
4419
4502
  isKeyframe: keyframe,
4420
4503
  size,
4421
- chunk: 0
4504
+ chunk: 0,
4505
+ bigEndian: false,
4506
+ chunkSize: null
4422
4507
  };
4423
4508
  samples.push(samplePosition);
4424
4509
  offset += size;
@@ -4431,13 +4516,12 @@ var getSamplesFromMoof = ({
4431
4516
  moofBox,
4432
4517
  trackId
4433
4518
  }) => {
4434
- if (moofBox.type !== "regular-box") {
4435
- throw new Error("Expected moof-box");
4436
- }
4437
- const trafs = moofBox.children.filter((c) => c.type === "regular-box" && c.boxType === "traf");
4438
- const mapped = trafs.map((traf) => {
4519
+ const mapped = moofBox.trafBoxes.map((traf) => {
4439
4520
  const tfhdBox = getTfhdBox(traf);
4440
- return tfhdBox?.trackId === trackId ? getSamplesFromTraf(traf, moofBox.offset) : [];
4521
+ if (!tfhdBox || tfhdBox.trackId !== trackId) {
4522
+ return [];
4523
+ }
4524
+ return getSamplesFromTraf(traf, moofBox.offset);
4441
4525
  });
4442
4526
  return mapped.flat(1);
4443
4527
  };
@@ -4449,10 +4533,13 @@ var collectSamplePositionsFromMoofBoxes = ({
4449
4533
  tkhdBox
4450
4534
  }) => {
4451
4535
  const isComplete = tfraBoxes.length > 0 && tfraBoxes.every((t) => t.entries.length === moofBoxes.length);
4452
- const samplePositions_ = moofBoxes.map((m) => {
4453
- return getSamplesFromMoof({ moofBox: m, trackId: tkhdBox.trackId });
4536
+ const samplePositions = moofBoxes.map((m) => {
4537
+ return getSamplesFromMoof({
4538
+ moofBox: m,
4539
+ trackId: tkhdBox.trackId
4540
+ });
4454
4541
  });
4455
- return { samplePositions: samplePositions_, isComplete };
4542
+ return { samplePositions, isComplete };
4456
4543
  };
4457
4544
 
4458
4545
  // src/get-sample-positions.ts
@@ -4501,7 +4588,9 @@ var getSamplePositions = ({
4501
4588
  dts,
4502
4589
  cts,
4503
4590
  duration: delta,
4504
- chunk: i
4591
+ chunk: i,
4592
+ bigEndian: false,
4593
+ chunkSize: null
4505
4594
  });
4506
4595
  dts += delta;
4507
4596
  offsetInThisChunk += size;
@@ -4511,7 +4600,10 @@ var getSamplePositions = ({
4511
4600
  };
4512
4601
 
4513
4602
  // src/get-sample-positions-from-mp4.ts
4514
- var getGroupedSamplesPositionsFromMp4 = (trakBox) => {
4603
+ var getGroupedSamplesPositionsFromMp4 = ({
4604
+ trakBox,
4605
+ bigEndian
4606
+ }) => {
4515
4607
  const stscBox = getStscBox(trakBox);
4516
4608
  const stszBox = getStszBox(trakBox);
4517
4609
  const stcoBox = getStcoBox(trakBox);
@@ -4543,20 +4635,37 @@ var getGroupedSamplesPositionsFromMp4 = (trakBox) => {
4543
4635
  offset: Number(entry),
4544
4636
  size: stszBox.sampleSize * stscEntry.samplesPerChunk,
4545
4637
  duration: stscEntry.samplesPerChunk,
4546
- isKeyframe: true
4638
+ isKeyframe: true,
4639
+ bigEndian,
4640
+ chunkSize: stszBox.sampleSize
4547
4641
  });
4548
4642
  timestamp += stscEntry.samplesPerChunk;
4549
4643
  }
4550
4644
  return samples;
4551
4645
  };
4552
4646
 
4647
+ // src/containers/iso-base-media/should-group-audio-samples.ts
4648
+ var shouldGroupAudioSamples = (trakBox) => {
4649
+ const isLpcm = isLpcmAudioCodec(trakBox);
4650
+ const isIn24 = isIn24AudioCodec(trakBox);
4651
+ const isTwos = isTwosAudioCodec(trakBox);
4652
+ if (isLpcm || isIn24 || isTwos) {
4653
+ return {
4654
+ bigEndian: isTwos || isIn24
4655
+ };
4656
+ }
4657
+ return null;
4658
+ };
4659
+
4553
4660
  // src/containers/iso-base-media/collect-sample-positions-from-trak.ts
4554
4661
  var collectSamplePositionsFromTrak = (trakBox) => {
4555
- const isLpcm = isLpcmAudioCodec(trakBox);
4662
+ const shouldGroupSamples = shouldGroupAudioSamples(trakBox);
4556
4663
  const timescaleAndDuration = getTimescaleAndDuration(trakBox);
4557
- const isIn24 = isIn24AudioCodec(trakBox);
4558
- if (isLpcm || isIn24) {
4559
- return getGroupedSamplesPositionsFromMp4(trakBox);
4664
+ if (shouldGroupSamples) {
4665
+ return getGroupedSamplesPositionsFromMp4({
4666
+ trakBox,
4667
+ bigEndian: shouldGroupSamples.bigEndian
4668
+ });
4560
4669
  }
4561
4670
  const stszBox = getStszBox(trakBox);
4562
4671
  const stcoBox = getStcoBox(trakBox);
@@ -4820,7 +4929,8 @@ var getDurationFromIsoBaseMedia = (parserState) => {
4820
4929
  const moovBox = getMoovBoxFromState({
4821
4930
  structureState: parserState.structure,
4822
4931
  isoState: parserState.iso,
4823
- mp4HeaderSegment: parserState.mp4HeaderSegment
4932
+ mp4HeaderSegment: parserState.mp4HeaderSegment,
4933
+ mayUsePrecomputed: true
4824
4934
  });
4825
4935
  if (!moovBox) {
4826
4936
  return null;
@@ -4837,7 +4947,7 @@ var getDurationFromIsoBaseMedia = (parserState) => {
4837
4947
  if (mvhdBox.durationInSeconds > 0) {
4838
4948
  return mvhdBox.durationInSeconds;
4839
4949
  }
4840
- const tracks2 = getTracks(parserState);
4950
+ const tracks2 = getTracks(parserState, true);
4841
4951
  const allTracks = [
4842
4952
  ...tracks2.videoTracks,
4843
4953
  ...tracks2.audioTracks,
@@ -4901,7 +5011,7 @@ var hasDuration = (parserState) => {
4901
5011
  if (structure === null) {
4902
5012
  return false;
4903
5013
  }
4904
- return getHasTracks(parserState);
5014
+ return getHasTracks(parserState, true);
4905
5015
  };
4906
5016
  var hasSlowDuration = (parserState) => {
4907
5017
  try {
@@ -4916,16 +5026,16 @@ var isVideoTrackHdr = (track) => {
4916
5026
  return track.color.matrixCoefficients === "bt2020" && track.color.transferCharacteristics === "arib-std-b67" && track.color.primaries === "bt2020";
4917
5027
  };
4918
5028
  var getIsHdr = (state) => {
4919
- const { videoTracks } = getTracks(state);
5029
+ const { videoTracks } = getTracks(state, true);
4920
5030
  return videoTracks.some((track) => isVideoTrackHdr(track));
4921
5031
  };
4922
5032
  var hasHdr = (state) => {
4923
- return getHasTracks(state);
5033
+ return getHasTracks(state, true);
4924
5034
  };
4925
5035
 
4926
5036
  // src/containers/iso-base-media/get-keyframes.ts
4927
5037
  var getKeyframesFromIsoBaseMedia = (state) => {
4928
- const { videoTracks } = getTracksFromIsoBaseMedia(state);
5038
+ const { videoTracks } = getTracksFromIsoBaseMedia(state, true);
4929
5039
  const structure = state.structure.getIsoStructure();
4930
5040
  const moofBoxes = getMoofBoxes(structure.boxes);
4931
5041
  const tfraBoxes = getTfraBoxes(structure);
@@ -4966,7 +5076,7 @@ var getKeyframes = (state) => {
4966
5076
  var hasKeyframes = (parserState) => {
4967
5077
  const structure = parserState.structure.getStructure();
4968
5078
  if (structure.type === "iso-base-media") {
4969
- return getHasTracks(parserState);
5079
+ return getHasTracks(parserState, true);
4970
5080
  }
4971
5081
  return true;
4972
5082
  };
@@ -5079,7 +5189,8 @@ var getMetadataFromIsoBase = (state) => {
5079
5189
  const moov = getMoovBoxFromState({
5080
5190
  structureState: state.structure,
5081
5191
  isoState: state.iso,
5082
- mp4HeaderSegment: state.mp4HeaderSegment
5192
+ mp4HeaderSegment: state.mp4HeaderSegment,
5193
+ mayUsePrecomputed: true
5083
5194
  });
5084
5195
  if (!moov) {
5085
5196
  return [];
@@ -5290,40 +5401,6 @@ var hasSampleRate = (state) => {
5290
5401
  return state.callbacks.tracks.hasAllTracks();
5291
5402
  };
5292
5403
 
5293
- // src/log.ts
5294
- var logLevels = ["trace", "verbose", "info", "warn", "error"];
5295
- var getNumberForLogLevel = (level) => {
5296
- return logLevels.indexOf(level);
5297
- };
5298
- var isEqualOrBelowLogLevel = (currentLevel, level) => {
5299
- return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
5300
- };
5301
- var Log = {
5302
- trace: (logLevel, ...args) => {
5303
- if (isEqualOrBelowLogLevel(logLevel, "trace")) {
5304
- return console.log(...args);
5305
- }
5306
- },
5307
- verbose: (logLevel, ...args) => {
5308
- if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
5309
- return console.log(...args);
5310
- }
5311
- },
5312
- info: (logLevel, ...args) => {
5313
- if (isEqualOrBelowLogLevel(logLevel, "info")) {
5314
- return console.log(...args);
5315
- }
5316
- },
5317
- warn: (logLevel, ...args) => {
5318
- if (isEqualOrBelowLogLevel(logLevel, "warn")) {
5319
- return console.warn(...args);
5320
- }
5321
- },
5322
- error: (...args) => {
5323
- return console.error(...args);
5324
- }
5325
- };
5326
-
5327
5404
  // src/state/video-section.ts
5328
5405
  var isByteInMediaSection = ({
5329
5406
  position,
@@ -5466,13 +5543,15 @@ var findBestSegmentFromTfra = ({
5466
5543
  };
5467
5544
  };
5468
5545
 
5469
- // src/containers/iso-base-media/get-seeking-from-mp4.ts
5546
+ // src/containers/iso-base-media/get-seeking-byte.ts
5470
5547
  var getSeekingByteFromIsoBaseMedia = async ({
5471
5548
  info,
5472
5549
  time,
5473
5550
  logLevel,
5474
5551
  currentPosition,
5475
- isoState
5552
+ isoState,
5553
+ mp4HeaderSegment,
5554
+ structure
5476
5555
  }) => {
5477
5556
  const tracks2 = getTracksFromMoovBox(info.moovBox);
5478
5557
  const allTracks = [
@@ -5480,6 +5559,18 @@ var getSeekingByteFromIsoBaseMedia = async ({
5480
5559
  ...tracks2.audioTracks,
5481
5560
  ...tracks2.otherTracks
5482
5561
  ];
5562
+ const hasMoov = Boolean(getMoovBoxFromState({
5563
+ mp4HeaderSegment,
5564
+ structureState: structure,
5565
+ isoState,
5566
+ mayUsePrecomputed: false
5567
+ }));
5568
+ if (!hasMoov) {
5569
+ Log.trace(logLevel, "No moov box found, must wait");
5570
+ return {
5571
+ type: "valid-but-must-wait"
5572
+ };
5573
+ }
5483
5574
  const firstVideoTrack = allTracks.find((t) => t.type === "video");
5484
5575
  if (!firstVideoTrack) {
5485
5576
  throw new Error("No video track found");
@@ -5515,7 +5606,7 @@ var getSeekingByteFromIsoBaseMedia = async ({
5515
5606
  }
5516
5607
  }
5517
5608
  }
5518
- const atom = await isoState.mfra.triggerLoad();
5609
+ const atom = await (info.mfraAlreadyLoaded ? Promise.resolve(info.mfraAlreadyLoaded) : isoState.mfra.triggerLoad());
5519
5610
  if (atom) {
5520
5611
  const moofOffset = findBestSegmentFromTfra({
5521
5612
  mfra: atom,
@@ -5586,12 +5677,12 @@ var getSeekingByteFromWav = ({
5586
5677
  time
5587
5678
  }) => {
5588
5679
  const bytesPerSecond = info.sampleRate * info.blockAlign;
5589
- const durationInSeconds = info.mediaSections.size / bytesPerSecond;
5680
+ const durationInSeconds = info.mediaSection.size / bytesPerSecond;
5590
5681
  const timeRoundedDown = Math.floor(Math.min(time, durationInSeconds - 0.0000001) * WAVE_SAMPLES_PER_SECOND) / WAVE_SAMPLES_PER_SECOND;
5591
5682
  const byteOffset = bytesPerSecond * timeRoundedDown;
5592
5683
  return Promise.resolve({
5593
5684
  type: "do-seek",
5594
- byte: byteOffset + info.mediaSections.start
5685
+ byte: byteOffset + info.mediaSection.start
5595
5686
  });
5596
5687
  };
5597
5688
 
@@ -5652,8 +5743,7 @@ var getSeekingByteFromMatroska = async ({
5652
5743
  webmState,
5653
5744
  info,
5654
5745
  logLevel,
5655
- mediaSection,
5656
- keyframes
5746
+ mediaSection
5657
5747
  }) => {
5658
5748
  if (!info.track) {
5659
5749
  Log.trace(logLevel, "No video track found, cannot seek yet");
@@ -5661,9 +5751,9 @@ var getSeekingByteFromMatroska = async ({
5661
5751
  type: "valid-but-must-wait"
5662
5752
  };
5663
5753
  }
5664
- const cuesResponse = await webmState.cues.getLoadedCues();
5754
+ const cuesResponse = info.loadedCues ?? await webmState.cues.getLoadedCues();
5665
5755
  const byteFromObservedKeyframe = findKeyframeBeforeTime2({
5666
- keyframes: keyframes.getKeyframes(),
5756
+ keyframes: info.keyframes,
5667
5757
  time
5668
5758
  });
5669
5759
  const byteFromCues = getByteFromCues({
@@ -6114,7 +6204,10 @@ var handleAvcPacket = async ({
6114
6204
  const dimensions = getDimensionsFromSps(spsAndPps.sps.spsData);
6115
6205
  const sampleAspectRatio = getSampleAspectRatioFromSps(spsAndPps.sps.spsData);
6116
6206
  const startOffset = makeSamplesStartAtZero ? Math.min(streamBuffer.pesHeader.pts, streamBuffer.pesHeader.dts ?? Infinity) : 0;
6117
- transportStream.startOffset.setOffset(programId, startOffset);
6207
+ transportStream.startOffset.setOffset({
6208
+ trackId: programId,
6209
+ newOffset: startOffset
6210
+ });
6118
6211
  const track = {
6119
6212
  m3uStreamFormat: null,
6120
6213
  rotation: 0,
@@ -6178,20 +6271,30 @@ var handleAvcPacket = async ({
6178
6271
  var makeObservedPesHeader = () => {
6179
6272
  const pesHeaders = [];
6180
6273
  const confirmedAsKeyframe = [];
6274
+ const addPesHeader = (pesHeader) => {
6275
+ if (pesHeaders.find((p) => p.offset === pesHeader.offset)) {
6276
+ return;
6277
+ }
6278
+ pesHeaders.push(pesHeader);
6279
+ };
6280
+ const markPtsAsKeyframe = (pts) => {
6281
+ confirmedAsKeyframe.push(pts);
6282
+ };
6283
+ const getPesKeyframeHeaders = () => {
6284
+ return pesHeaders.filter((p) => confirmedAsKeyframe.includes(p.pts));
6285
+ };
6286
+ const setPesKeyframesFromSeekingHints = (hints) => {
6287
+ for (const pesHeader of hints.observedPesHeaders) {
6288
+ addPesHeader(pesHeader);
6289
+ markPtsAsKeyframe(pesHeader.pts);
6290
+ }
6291
+ };
6181
6292
  const state = {
6182
6293
  pesHeaders,
6183
- addPesHeader: (pesHeader) => {
6184
- if (pesHeaders.find((p) => p.offset === pesHeader.offset)) {
6185
- return;
6186
- }
6187
- pesHeaders.push(pesHeader);
6188
- },
6189
- markPtsAsKeyframe: (pts) => {
6190
- confirmedAsKeyframe.push(pts);
6191
- },
6192
- getPesKeyframeHeaders: () => {
6193
- return pesHeaders.filter((p) => confirmedAsKeyframe.includes(p.pts));
6194
- }
6294
+ addPesHeader,
6295
+ markPtsAsKeyframe,
6296
+ getPesKeyframeHeaders,
6297
+ setPesKeyframesFromSeekingHints
6195
6298
  };
6196
6299
  return state;
6197
6300
  };
@@ -6213,34 +6316,36 @@ var getSeekingByte = ({
6213
6316
  transportStream,
6214
6317
  webmState,
6215
6318
  mediaSection,
6216
- keyframes
6319
+ mp4HeaderSegment,
6320
+ structure
6217
6321
  }) => {
6218
- if (info.type === "iso-base-media-seeking-info") {
6322
+ if (info.type === "iso-base-media-seeking-hints") {
6219
6323
  return getSeekingByteFromIsoBaseMedia({
6220
6324
  info,
6221
6325
  time,
6222
6326
  logLevel,
6223
6327
  currentPosition,
6224
- isoState
6328
+ isoState,
6329
+ mp4HeaderSegment,
6330
+ structure
6225
6331
  });
6226
6332
  }
6227
- if (info.type === "wav-seeking-info") {
6333
+ if (info.type === "wav-seeking-hints") {
6228
6334
  return getSeekingByteFromWav({
6229
6335
  info,
6230
6336
  time
6231
6337
  });
6232
6338
  }
6233
- if (info.type === "webm-seeking-info") {
6339
+ if (info.type === "webm-seeking-hints") {
6234
6340
  return getSeekingByteFromMatroska({
6235
6341
  info,
6236
6342
  time,
6237
6343
  webmState,
6238
6344
  logLevel,
6239
- mediaSection,
6240
- keyframes
6345
+ mediaSection
6241
6346
  });
6242
6347
  }
6243
- if (info.type === "transport-stream-seeking-info") {
6348
+ if (info.type === "transport-stream-seeking-hints") {
6244
6349
  const lastKeyframeBeforeTimeInSeconds = getLastKeyFrameBeforeTimeInSeconds({
6245
6350
  observedPesHeaders: info.observedPesHeaders,
6246
6351
  timeInSeconds: time,
@@ -6256,8 +6361,22 @@ var getSeekingByte = ({
6256
6361
  throw new Error(`Unknown seeking info type: ${info}`);
6257
6362
  };
6258
6363
 
6259
- // src/containers/iso-base-media/get-seeking-info-from-mp4.ts
6260
- var getSeekingInfoFromMp4 = ({
6364
+ // src/state/iso-base-media/precomputed-tfra.ts
6365
+ var precomputedTfraState = () => {
6366
+ let tfraBoxes = [];
6367
+ return {
6368
+ getTfraBoxes: () => tfraBoxes,
6369
+ setTfraBoxes: (boxes) => {
6370
+ tfraBoxes = boxes;
6371
+ }
6372
+ };
6373
+ };
6374
+ var deduplicateTfraBoxesByOffset = (tfraBoxes) => {
6375
+ return tfraBoxes.filter((m, i, arr) => i === arr.findIndex((t) => t.offset === m.offset));
6376
+ };
6377
+
6378
+ // src/containers/iso-base-media/seeking-hints.ts
6379
+ var getSeekingHintsFromMp4 = ({
6261
6380
  structureState,
6262
6381
  isoState,
6263
6382
  mp4HeaderSegment,
@@ -6267,37 +6386,57 @@ var getSeekingInfoFromMp4 = ({
6267
6386
  const moovAtom = getMoovBoxFromState({
6268
6387
  isoState,
6269
6388
  mp4HeaderSegment,
6270
- structureState
6389
+ structureState,
6390
+ mayUsePrecomputed: true
6271
6391
  });
6272
- const moofBoxes = getMoofBoxes(structure.boxes);
6273
- const tfraBoxes = getTfraBoxes(structure);
6392
+ const moofBoxes = deduplicateMoofBoxesByOffset([
6393
+ ...isoState.moof.getMoofBoxes(),
6394
+ ...getMoofBoxes(structure.boxes)
6395
+ ]);
6396
+ const tfraBoxes = deduplicateTfraBoxesByOffset([
6397
+ ...isoState.tfra.getTfraBoxes(),
6398
+ ...getTfraBoxes(structure)
6399
+ ]);
6274
6400
  if (!moovAtom) {
6275
6401
  return null;
6276
6402
  }
6277
6403
  return {
6278
- type: "iso-base-media-seeking-info",
6404
+ type: "iso-base-media-seeking-hints",
6279
6405
  moovBox: moovAtom,
6280
6406
  moofBoxes,
6281
6407
  tfraBoxes,
6282
- mediaSections: mediaSectionState2.getMediaSections()
6408
+ mediaSections: mediaSectionState2.getMediaSections(),
6409
+ mfraAlreadyLoaded: isoState.mfra.getIfAlreadyLoaded()
6283
6410
  };
6284
6411
  };
6412
+ var setSeekingHintsForMp4 = ({}) => {};
6285
6413
 
6286
- // src/containers/transport-stream/get-seeking-info.ts
6287
- var getSeekingInfoFromTransportStream = (transportStream, tracksState) => {
6414
+ // src/containers/transport-stream/seeking-hints.ts
6415
+ var getSeekingHintsFromTransportStream = (transportStream, tracksState) => {
6288
6416
  const firstVideoTrack = tracksState.getTracks().find((t) => t.type === "video");
6289
6417
  if (!firstVideoTrack) {
6290
- throw new Error("No video track found");
6418
+ return null;
6291
6419
  }
6292
6420
  return {
6293
- type: "transport-stream-seeking-info",
6421
+ type: "transport-stream-seeking-hints",
6294
6422
  observedPesHeaders: transportStream.observedPesHeaders.getPesKeyframeHeaders(),
6295
- ptsStartOffset: transportStream.startOffset.getOffset(firstVideoTrack.trackId)
6423
+ ptsStartOffset: transportStream.startOffset.getOffset(firstVideoTrack.trackId),
6424
+ firstVideoTrackId: firstVideoTrack.trackId
6296
6425
  };
6297
6426
  };
6427
+ var setSeekingHintsForTransportStream = ({
6428
+ hints,
6429
+ state
6430
+ }) => {
6431
+ state.transportStream.observedPesHeaders.setPesKeyframesFromSeekingHints(hints);
6432
+ state.transportStream.startOffset.setOffset({
6433
+ trackId: hints.firstVideoTrackId,
6434
+ newOffset: hints.ptsStartOffset
6435
+ });
6436
+ };
6298
6437
 
6299
- // src/containers/wav/get-seeking-info.ts
6300
- var getSeekingInfoFromWav = ({
6438
+ // src/containers/wav/seeking-hints.ts
6439
+ var getSeekingHintsFromWav = ({
6301
6440
  structure,
6302
6441
  mediaSectionState: mediaSectionState2
6303
6442
  }) => {
@@ -6310,41 +6449,62 @@ var getSeekingInfoFromWav = ({
6310
6449
  return null;
6311
6450
  }
6312
6451
  return {
6313
- type: "wav-seeking-info",
6452
+ type: "wav-seeking-hints",
6314
6453
  sampleRate: fmtBox.sampleRate,
6315
6454
  blockAlign: fmtBox.blockAlign,
6316
- mediaSections: mediaSection[0]
6455
+ mediaSection: mediaSection[0]
6317
6456
  };
6318
6457
  };
6458
+ var setSeekingHintsForWav = ({
6459
+ hints,
6460
+ state
6461
+ }) => {
6462
+ state.mediaSection.addMediaSection(hints.mediaSection);
6463
+ };
6319
6464
 
6320
- // src/containers/webm/seek/get-seeking-info.ts
6321
- var getSeekingInfoFromMatroska = (tracksState) => {
6465
+ // src/containers/webm/seek/seeking-hints.ts
6466
+ var getSeekingHintsFromMatroska = (tracksState, keyframesState, webmState) => {
6322
6467
  const tracks2 = tracksState.getTracks();
6323
6468
  const firstVideoTrack = tracks2.find((track) => track.type === "video");
6469
+ const keyframes = keyframesState.getKeyframes();
6470
+ const loadedCues = webmState.cues.getIfAlreadyLoaded();
6324
6471
  return {
6325
- type: "webm-seeking-info",
6472
+ type: "webm-seeking-hints",
6326
6473
  track: firstVideoTrack ? {
6327
6474
  timescale: firstVideoTrack.timescale,
6328
6475
  trackId: firstVideoTrack.trackId
6329
- } : null
6476
+ } : null,
6477
+ keyframes,
6478
+ loadedCues,
6479
+ timestampMap: webmState.getTimeStampMapForSeekingHints()
6330
6480
  };
6331
6481
  };
6482
+ var setSeekingHintsForWebm = ({
6483
+ hints,
6484
+ state
6485
+ }) => {
6486
+ state.webm.cues.setFromSeekingHints(hints);
6487
+ state.keyframes.setFromSeekingHints(hints);
6488
+ state.webm.setTimeStampMapForSeekingHints(hints.timestampMap);
6489
+ };
6332
6490
 
6333
- // src/get-seeking-info.ts
6334
- var getSeekingInfo = ({
6491
+ // src/get-seeking-hints.ts
6492
+ var getSeekingHints = ({
6335
6493
  structureState,
6336
6494
  mp4HeaderSegment,
6337
6495
  mediaSectionState: mediaSectionState2,
6338
6496
  isoState,
6339
6497
  transportStream,
6340
- tracksState
6498
+ tracksState,
6499
+ keyframesState,
6500
+ webmState
6341
6501
  }) => {
6342
6502
  const structure = structureState.getStructureOrNull();
6343
6503
  if (!structure) {
6344
6504
  return null;
6345
6505
  }
6346
6506
  if (structure.type === "iso-base-media") {
6347
- return getSeekingInfoFromMp4({
6507
+ return getSeekingHintsFromMp4({
6348
6508
  structureState,
6349
6509
  isoState,
6350
6510
  mp4HeaderSegment,
@@ -6352,16 +6512,16 @@ var getSeekingInfo = ({
6352
6512
  });
6353
6513
  }
6354
6514
  if (structure.type === "wav") {
6355
- return getSeekingInfoFromWav({
6515
+ return getSeekingHintsFromWav({
6356
6516
  structure,
6357
6517
  mediaSectionState: mediaSectionState2
6358
6518
  });
6359
6519
  }
6360
6520
  if (structure.type === "matroska") {
6361
- return getSeekingInfoFromMatroska(tracksState);
6521
+ return getSeekingHintsFromMatroska(tracksState, keyframesState, webmState);
6362
6522
  }
6363
6523
  if (structure.type === "transport-stream") {
6364
- return getSeekingInfoFromTransportStream(transportStream, tracksState);
6524
+ return getSeekingHintsFromTransportStream(transportStream, tracksState);
6365
6525
  }
6366
6526
  throw new Error(`Seeking is not supported for this format: ${structure.type}`);
6367
6527
  };
@@ -6590,22 +6750,24 @@ var turnSeekIntoByte = async ({
6590
6750
  if (seek2.timeInSeconds < 0) {
6591
6751
  throw new Error(`Cannot seek to a negative time: ${JSON.stringify(seek2)}`);
6592
6752
  }
6593
- const seekingInfo = getSeekingInfo({
6753
+ const seekingHints = getSeekingHints({
6594
6754
  structureState,
6595
6755
  mp4HeaderSegment,
6596
6756
  mediaSectionState: mediaSectionState2,
6597
6757
  isoState,
6598
6758
  transportStream,
6599
- tracksState
6759
+ tracksState,
6760
+ keyframesState: keyframes,
6761
+ webmState
6600
6762
  });
6601
- if (!seekingInfo) {
6763
+ if (!seekingHints) {
6602
6764
  Log.trace(logLevel, "No seeking info, cannot seek yet");
6603
6765
  return {
6604
6766
  type: "valid-but-must-wait"
6605
6767
  };
6606
6768
  }
6607
6769
  const seekingByte = await getSeekingByte({
6608
- info: seekingInfo,
6770
+ info: seekingHints,
6609
6771
  time: seek2.timeInSeconds,
6610
6772
  logLevel,
6611
6773
  currentPosition: iterator.counter.getOffset(),
@@ -6613,7 +6775,8 @@ var turnSeekIntoByte = async ({
6613
6775
  transportStream,
6614
6776
  webmState,
6615
6777
  mediaSection: mediaSectionState2,
6616
- keyframes
6778
+ mp4HeaderSegment,
6779
+ structure: structureState
6617
6780
  });
6618
6781
  return seekingByte;
6619
6782
  }
@@ -6889,7 +7052,7 @@ var emitAvailableInfo = async ({
6889
7052
  }
6890
7053
  if (key === "tracks") {
6891
7054
  if (!emittedFields.tracks && hasInfo.tracks) {
6892
- const { videoTracks, audioTracks } = getTracks(state);
7055
+ const { videoTracks, audioTracks } = getTracks(state, true);
6893
7056
  await callbackFunctions.onTracks?.({ videoTracks, audioTracks });
6894
7057
  if (fieldsInReturnValue.tracks) {
6895
7058
  returnValue.tracks = { videoTracks, audioTracks };
@@ -7131,7 +7294,7 @@ var getAvailableInfo = ({
7131
7294
  return Boolean(structure && hasAudioCodec(state));
7132
7295
  }
7133
7296
  if (key === "tracks") {
7134
- return Boolean(structure && getHasTracks(state));
7297
+ return Boolean(structure && getHasTracks(state, true));
7135
7298
  }
7136
7299
  if (key === "keyframes") {
7137
7300
  return Boolean(structure && hasKeyframes(state));
@@ -7766,7 +7929,7 @@ var parseFlac = ({
7766
7929
 
7767
7930
  // src/state/iso-base-media/cached-sample-positions.ts
7768
7931
  var calculateFlatSamples = (state) => {
7769
- const tracks2 = getTracks(state);
7932
+ const tracks2 = getTracks(state, true);
7770
7933
  const allTracks = [
7771
7934
  ...tracks2.videoTracks,
7772
7935
  ...tracks2.audioTracks,
@@ -7859,7 +8022,9 @@ var makeTracksSectionState = (canSkipTracksState, src) => {
7859
8022
  addTrack: (track) => {
7860
8023
  tracks2.push(track);
7861
8024
  },
7862
- getTracks: () => tracks2,
8025
+ getTracks: () => {
8026
+ return tracks2;
8027
+ },
7863
8028
  ensureHasTracksAtEnd: (fields) => {
7864
8029
  if (canSkipTracksState.canSkipTracks()) {
7865
8030
  return;
@@ -9620,7 +9785,7 @@ var processBox = async ({
9620
9785
  iterator.discard(boxSize - 8);
9621
9786
  return null;
9622
9787
  }
9623
- if (isoState && isoState.moov.getMoovBox()) {
9788
+ if (isoState && isoState.moov.getMoovBoxAndPrecomputed() && !isoState.moov.getMoovBoxAndPrecomputed()?.precomputed) {
9624
9789
  Log.verbose(logLevel, "Moov box already parsed, skipping");
9625
9790
  iterator.discard(boxSize - 8);
9626
9791
  return null;
@@ -9836,6 +10001,27 @@ var getMoovAtom = async ({
9836
10001
  return moov;
9837
10002
  };
9838
10003
 
10004
+ // src/containers/iso-base-media/mdat/postprocess-bytes.ts
10005
+ var postprocessBytes = ({
10006
+ bytes,
10007
+ bigEndian,
10008
+ chunkSize
10009
+ }) => {
10010
+ if (!bigEndian) {
10011
+ return bytes;
10012
+ }
10013
+ if (chunkSize === null) {
10014
+ return bytes;
10015
+ }
10016
+ const newBuffer = new Uint8Array(bytes);
10017
+ for (let i = 0;i < newBuffer.length; i += chunkSize) {
10018
+ const slice = newBuffer.slice(i, i + chunkSize);
10019
+ slice.reverse();
10020
+ newBuffer.set(slice, i);
10021
+ }
10022
+ return newBuffer;
10023
+ };
10024
+
9839
10025
  // src/containers/iso-base-media/mdat/mdat.ts
9840
10026
  var parseMdatSection = async (state) => {
9841
10027
  const mediaSection = getCurrentMediaSection({
@@ -9849,13 +10035,16 @@ var parseMdatSection = async (state) => {
9849
10035
  if (maySkipVideoData({ state })) {
9850
10036
  return makeSkip(endOfMdat);
9851
10037
  }
9852
- const alreadyHas = getHasTracks(state);
9853
- if (!alreadyHas) {
10038
+ const alreadyHasMoov = getHasTracks(state, true);
10039
+ if (!alreadyHasMoov) {
9854
10040
  const moov = await getMoovAtom({
9855
10041
  endOfMdat,
9856
10042
  state
9857
10043
  });
9858
- state.iso.moov.setMoovBox(moov);
10044
+ state.iso.moov.setMoovBox({
10045
+ moovBox: moov,
10046
+ precomputed: false
10047
+ });
9859
10048
  state.callbacks.tracks.setIsDone(state.logLevel);
9860
10049
  state.structure.getIsoStructure().boxes.push(moov);
9861
10050
  return parseMdatSection(state);
@@ -9879,8 +10068,12 @@ var parseMdatSection = async (state) => {
9879
10068
  if (iterator.bytesRemaining() < samplesWithIndex.samplePosition.size) {
9880
10069
  return null;
9881
10070
  }
9882
- const bytes = iterator.getSlice(samplesWithIndex.samplePosition.size);
9883
- const { cts, dts, duration: duration2, isKeyframe, offset } = samplesWithIndex.samplePosition;
10071
+ const { cts, dts, duration: duration2, isKeyframe, offset, bigEndian, chunkSize } = samplesWithIndex.samplePosition;
10072
+ const bytes = postprocessBytes({
10073
+ bytes: iterator.getSlice(samplesWithIndex.samplePosition.size),
10074
+ bigEndian,
10075
+ chunkSize
10076
+ });
9884
10077
  if (samplesWithIndex.track.type === "audio") {
9885
10078
  await emitAudioSample({
9886
10079
  trackId: samplesWithIndex.track.trackId,
@@ -10258,8 +10451,8 @@ var parseM3uManifest = ({
10258
10451
  return Promise.resolve(null);
10259
10452
  };
10260
10453
 
10261
- // src/forward-controller.ts
10262
- var forwardMediaParserController = ({
10454
+ // src/forward-controller-pause-resume-abort.ts
10455
+ var forwardMediaParserControllerPauseResume = ({
10263
10456
  parentController,
10264
10457
  childController
10265
10458
  }) => {
@@ -10331,7 +10524,8 @@ var parseMedia = (options) => {
10331
10524
  onError: () => ({ action: "fail" }),
10332
10525
  acknowledgeRemotionLicense: Boolean(options.acknowledgeRemotionLicense),
10333
10526
  apiName: "parseMedia()",
10334
- makeSamplesStartAtZero: options.makeSamplesStartAtZero ?? true
10527
+ makeSamplesStartAtZero: options.makeSamplesStartAtZero ?? true,
10528
+ seekingHints: options.seekingHints ?? null
10335
10529
  });
10336
10530
  };
10337
10531
 
@@ -10373,28 +10567,29 @@ var iteratorOverSegmentFiles = async ({
10373
10567
  const playlist = getPlaylist(structure, playlistUrl);
10374
10568
  const chunks = getChunks(playlist);
10375
10569
  let resolver = onInitialProgress;
10376
- let rejector = (_e) => {
10377
- };
10378
- const childController = mediaParserController();
10379
- const forwarded = forwardMediaParserController({
10380
- childController,
10381
- parentController
10382
- });
10383
- const makeContinuationFn = () => {
10384
- return {
10385
- continue() {
10386
- const { promise, reject, resolve } = withResolvers();
10387
- resolver = resolve;
10388
- rejector = reject;
10389
- childController.resume();
10390
- return promise;
10391
- },
10392
- abort() {
10393
- childController.abort();
10394
- }
10395
- };
10396
- };
10570
+ let rejector = (_e) => {};
10397
10571
  for (const chunk of chunks) {
10572
+ resolver = onInitialProgress;
10573
+ rejector = (_e) => {};
10574
+ const childController = mediaParserController();
10575
+ const forwarded = forwardMediaParserControllerPauseResume({
10576
+ childController,
10577
+ parentController
10578
+ });
10579
+ const makeContinuationFn = () => {
10580
+ return {
10581
+ continue() {
10582
+ const { promise, reject, resolve } = withResolvers();
10583
+ resolver = resolve;
10584
+ rejector = reject;
10585
+ childController.resume();
10586
+ return promise;
10587
+ },
10588
+ abort() {
10589
+ childController.abort();
10590
+ }
10591
+ };
10592
+ };
10398
10593
  const isLastChunk = chunk === chunks[chunks.length - 1];
10399
10594
  await childController._internals.checkForAbortAndPause();
10400
10595
  const src = readerInterface.createAdjacentFileSource(chunk.url, playlistUrl);
@@ -11428,7 +11623,7 @@ var parseMediaSection = async (state) => {
11428
11623
  await parseMovi({
11429
11624
  state
11430
11625
  });
11431
- const tracks2 = getTracks(state);
11626
+ const tracks2 = getTracks(state, false);
11432
11627
  if (!tracks2.videoTracks.some((t) => t.codec === TO_BE_OVERRIDDEN_LATER) && !state.callbacks.tracks.getIsDone()) {
11433
11628
  state.callbacks.tracks.setIsDone(state.logLevel);
11434
11629
  }
@@ -11799,7 +11994,10 @@ var handleAacPacket = async ({
11799
11994
  });
11800
11995
  if (!isTrackRegistered) {
11801
11996
  const startOffset = makeSamplesStartAtZero ? Math.min(streamBuffer.pesHeader.pts, streamBuffer.pesHeader.dts ?? Infinity) : 0;
11802
- transportStream.startOffset.setOffset(programId, startOffset);
11997
+ transportStream.startOffset.setOffset({
11998
+ trackId: programId,
11999
+ newOffset: startOffset
12000
+ });
11803
12001
  const track = {
11804
12002
  type: "audio",
11805
12003
  codecPrivate: codecPrivate2,
@@ -13312,6 +13510,30 @@ var warnIfRemotionLicenseNotAcknowledged = ({
13312
13510
  Log.warn(logLevel, `Pass \`acknowledgeRemotionLicense: true\` to \`${apiName}\` function to make this message disappear.`);
13313
13511
  };
13314
13512
 
13513
+ // src/set-seeking-hints.ts
13514
+ var setSeekingHints = ({
13515
+ hints,
13516
+ state
13517
+ }) => {
13518
+ if (hints.type === "iso-base-media-seeking-hints") {
13519
+ setSeekingHintsForMp4({ hints, state });
13520
+ return;
13521
+ }
13522
+ if (hints.type === "wav-seeking-hints") {
13523
+ setSeekingHintsForWav({ hints, state });
13524
+ return;
13525
+ }
13526
+ if (hints.type === "transport-stream-seeking-hints") {
13527
+ setSeekingHintsForTransportStream({ hints, state });
13528
+ return;
13529
+ }
13530
+ if (hints.type === "webm-seeking-hints") {
13531
+ setSeekingHintsForWebm({ hints, state });
13532
+ return;
13533
+ }
13534
+ throw new Error(`Unknown seeking hints type: ${hints}`);
13535
+ };
13536
+
13315
13537
  // src/get-fields-from-callbacks.ts
13316
13538
  var getFieldsFromCallback = ({
13317
13539
  fields,
@@ -13542,6 +13764,7 @@ var lazyMfraLoad = ({
13542
13764
  logLevel
13543
13765
  }) => {
13544
13766
  let prom = null;
13767
+ let result = null;
13545
13768
  const triggerLoad = () => {
13546
13769
  if (prom) {
13547
13770
  return prom;
@@ -13555,12 +13778,24 @@ var lazyMfraLoad = ({
13555
13778
  logLevel
13556
13779
  }).then((boxes) => {
13557
13780
  Log.verbose(logLevel, "Lazily found mfra atom.");
13781
+ result = boxes;
13558
13782
  return boxes;
13559
13783
  });
13560
13784
  return prom;
13561
13785
  };
13786
+ const getIfAlreadyLoaded = () => {
13787
+ if (result) {
13788
+ return result;
13789
+ }
13790
+ return null;
13791
+ };
13792
+ const setFromSeekingHints = (hints) => {
13793
+ result = hints.mfraAlreadyLoaded;
13794
+ };
13562
13795
  return {
13563
- triggerLoad
13796
+ triggerLoad,
13797
+ getIfAlreadyLoaded,
13798
+ setFromSeekingHints
13564
13799
  };
13565
13800
  };
13566
13801
 
@@ -13571,7 +13806,7 @@ var moovState = () => {
13571
13806
  setMoovBox: (moov) => {
13572
13807
  moovBox = moov;
13573
13808
  },
13574
- getMoovBox: () => moovBox
13809
+ getMoovBoxAndPrecomputed: () => moovBox
13575
13810
  };
13576
13811
  };
13577
13812
 
@@ -13592,24 +13827,34 @@ var isoBaseMediaState = ({
13592
13827
  readerInterface,
13593
13828
  src,
13594
13829
  logLevel
13595
- })
13830
+ }),
13831
+ moof: precomputedMoofState(),
13832
+ tfra: precomputedTfraState()
13596
13833
  };
13597
13834
  };
13598
13835
 
13599
13836
  // src/state/keyframes.ts
13600
13837
  var keyframesState = () => {
13601
13838
  const keyframes = [];
13602
- return {
13603
- addKeyframe: (keyframe) => {
13604
- if (keyframes.find((k) => k.positionInBytes === keyframe.positionInBytes)) {
13605
- return;
13606
- }
13607
- keyframes.push(keyframe);
13608
- },
13609
- getKeyframes: () => {
13610
- return keyframes;
13839
+ const addKeyframe = (keyframe) => {
13840
+ if (keyframes.find((k) => k.positionInBytes === keyframe.positionInBytes)) {
13841
+ return;
13842
+ }
13843
+ keyframes.push(keyframe);
13844
+ };
13845
+ const getKeyframes2 = () => {
13846
+ return keyframes;
13847
+ };
13848
+ const setFromSeekingHints = (hints) => {
13849
+ for (const keyframe of hints.keyframes) {
13850
+ addKeyframe(keyframe);
13611
13851
  }
13612
13852
  };
13853
+ return {
13854
+ addKeyframe,
13855
+ getKeyframes: getKeyframes2,
13856
+ setFromSeekingHints
13857
+ };
13613
13858
  };
13614
13859
 
13615
13860
  // src/containers/m3u/sample-sorter.ts
@@ -13885,6 +14130,7 @@ var lazyCuesFetch = ({
13885
14130
  }) => {
13886
14131
  let prom = null;
13887
14132
  let sOffset = null;
14133
+ let result = null;
13888
14134
  const triggerLoad = (position, segmentOffset) => {
13889
14135
  if (prom) {
13890
14136
  return prom;
@@ -13902,6 +14148,7 @@ var lazyCuesFetch = ({
13902
14148
  src
13903
14149
  }).then((cues) => {
13904
14150
  Log.verbose(logLevel, "Cues loaded");
14151
+ result = cues;
13905
14152
  return cues;
13906
14153
  });
13907
14154
  return prom;
@@ -13922,9 +14169,27 @@ var lazyCuesFetch = ({
13922
14169
  segmentOffset: sOffset
13923
14170
  };
13924
14171
  };
14172
+ const getIfAlreadyLoaded = () => {
14173
+ if (result) {
14174
+ if (!sOffset) {
14175
+ throw new Error("Segment offset not set");
14176
+ }
14177
+ return {
14178
+ cues: result,
14179
+ segmentOffset: sOffset
14180
+ };
14181
+ }
14182
+ return null;
14183
+ };
14184
+ const setFromSeekingHints = (hints) => {
14185
+ result = hints.loadedCues?.cues ?? null;
14186
+ sOffset = hints.loadedCues?.segmentOffset ?? null;
14187
+ };
13925
14188
  return {
13926
14189
  triggerLoad,
13927
- getLoadedCues
14190
+ getLoadedCues,
14191
+ getIfAlreadyLoaded,
14192
+ setFromSeekingHints
13928
14193
  };
13929
14194
  };
13930
14195
 
@@ -13954,7 +14219,7 @@ var webmState = ({
13954
14219
  trackTimescale: trackTimescale?.value ?? null
13955
14220
  };
13956
14221
  };
13957
- const timestampMap = new Map;
14222
+ let timestampMap = new Map;
13958
14223
  const getTimestampOffsetForByteOffset = (byteOffset) => {
13959
14224
  const entries = Array.from(timestampMap.entries());
13960
14225
  const sortedByByteOffset = entries.sort((a, b) => {
@@ -13996,12 +14261,20 @@ var webmState = ({
13996
14261
  readerInterface,
13997
14262
  src
13998
14263
  });
14264
+ const getTimeStampMapForSeekingHints = () => {
14265
+ return timestampMap;
14266
+ };
14267
+ const setTimeStampMapForSeekingHints = (newTimestampMap) => {
14268
+ timestampMap = newTimestampMap;
14269
+ };
13999
14270
  return {
14000
14271
  cues,
14001
14272
  onTrackEntrySegment,
14002
14273
  getTrackInfoByNumber: (id) => trackEntries[id],
14003
14274
  setTimestampOffset,
14004
14275
  getTimestampOffsetForByteOffset,
14276
+ getTimeStampMapForSeekingHints,
14277
+ setTimeStampMapForSeekingHints,
14005
14278
  getTimescale,
14006
14279
  setTimescale,
14007
14280
  addSegment: (seg) => {
@@ -14231,9 +14504,6 @@ var samplesObservedState = () => {
14231
14504
  const timeBetweenSamplesAudio = startingTimestampDifferenceAudio / (audioSamples.size - 1);
14232
14505
  audioDuration = timeBetweenSamplesAudio * audioSamples.size;
14233
14506
  }
14234
- if (videoDuration === null && audioDuration === null) {
14235
- throw new Error("No samples");
14236
- }
14237
14507
  return Math.max(videoDuration ?? 0, audioDuration ?? 0);
14238
14508
  };
14239
14509
  const addVideoSample = (videoSample) => {
@@ -14365,7 +14635,7 @@ var ptsStartOffsetStore = () => {
14365
14635
  const offsets = {};
14366
14636
  return {
14367
14637
  getOffset: (trackId) => offsets[trackId] || 0,
14368
- setOffset: (trackId, newOffset) => {
14638
+ setOffset: ({ newOffset, trackId }) => {
14369
14639
  offsets[trackId] = newOffset;
14370
14640
  }
14371
14641
  };
@@ -14526,8 +14796,7 @@ var throttledStateUpdate = ({
14526
14796
  return {
14527
14797
  get: () => currentState,
14528
14798
  update: null,
14529
- stopAndGetLastProgress: () => {
14530
- }
14799
+ stopAndGetLastProgress: () => {}
14531
14800
  };
14532
14801
  }
14533
14802
  let lastUpdated = null;
@@ -14538,8 +14807,7 @@ var throttledStateUpdate = ({
14538
14807
  updateFn(currentState);
14539
14808
  lastUpdated = currentState;
14540
14809
  };
14541
- let cleanup = () => {
14542
- };
14810
+ let cleanup = () => {};
14543
14811
  if (everyMilliseconds > 0) {
14544
14812
  const interval = setInterval(() => {
14545
14813
  callUpdateIfChanged();
@@ -14590,6 +14858,7 @@ var internalParseMedia = async function({
14590
14858
  selectM3uAssociatedPlaylists: selectM3uAssociatedPlaylistsFn,
14591
14859
  mp4HeaderSegment,
14592
14860
  makeSamplesStartAtZero,
14861
+ seekingHints,
14593
14862
  ...more
14594
14863
  }) {
14595
14864
  controller._internals.markAsReadyToEmitEvents();
@@ -14638,6 +14907,19 @@ var internalParseMedia = async function({
14638
14907
  initialReaderInstance: readerInstance,
14639
14908
  makeSamplesStartAtZero
14640
14909
  });
14910
+ if (seekingHints) {
14911
+ setSeekingHints({ hints: seekingHints, state });
14912
+ }
14913
+ controller._internals.attachSeekingHintResolution(() => Promise.resolve(getSeekingHints({
14914
+ tracksState: state.callbacks.tracks,
14915
+ keyframesState: state.keyframes,
14916
+ webmState: state.webm,
14917
+ structureState: state.structure,
14918
+ mp4HeaderSegment: state.mp4HeaderSegment,
14919
+ mediaSectionState: state.mediaSection,
14920
+ isoState: state.iso,
14921
+ transportStream: state.transportStream
14922
+ })));
14641
14923
  if (!hasAudioTrackHandlers && !hasVideoTrackHandlers && Object.values(state.fields).every((v) => !v) && mode === "query") {
14642
14924
  Log.warn(logLevel, new Error("Warning - No `fields` and no `on*` callbacks were passed to `parseMedia()`. Specify the data you would like to retrieve."));
14643
14925
  }
@@ -14665,7 +14947,7 @@ var internalParseMedia = async function({
14665
14947
  return state.returnValue;
14666
14948
  };
14667
14949
 
14668
- // src/worker/forward-controller.ts
14950
+ // src/worker/forward-controller-to-worker.ts
14669
14951
  var forwardMediaParserControllerToWorker = (controller) => {
14670
14952
  return (message) => {
14671
14953
  if (message.type === "request-pause") {
@@ -14676,6 +14958,20 @@ var forwardMediaParserControllerToWorker = (controller) => {
14676
14958
  controller._experimentalSeek(message.payload);
14677
14959
  return;
14678
14960
  }
14961
+ if (message.type === "request-get-seeking-hints") {
14962
+ controller.getSeekingHints().then((hints) => {
14963
+ postMessage({
14964
+ type: "response-get-seeking-hints",
14965
+ payload: hints
14966
+ });
14967
+ }).catch((error) => {
14968
+ postMessage({
14969
+ type: "response-error",
14970
+ payload: error
14971
+ });
14972
+ });
14973
+ return;
14974
+ }
14679
14975
  if (message.type === "request-resume") {
14680
14976
  controller.resume();
14681
14977
  return;
@@ -14691,7 +14987,11 @@ var forwardMediaParserControllerToWorker = (controller) => {
14691
14987
  };
14692
14988
 
14693
14989
  // src/worker/serialize-error.ts
14694
- var serializeError = (error, logLevel) => {
14990
+ var serializeError = ({
14991
+ error,
14992
+ logLevel,
14993
+ seekingHints
14994
+ }) => {
14695
14995
  if (error instanceof IsAGifError) {
14696
14996
  return {
14697
14997
  type: "response-error",
@@ -14732,7 +15032,8 @@ var serializeError = (error, logLevel) => {
14732
15032
  type: "response-error",
14733
15033
  errorName: "MediaParserAbortError",
14734
15034
  errorMessage: error.message,
14735
- errorStack: error.stack ?? ""
15035
+ errorStack: error.stack ?? "",
15036
+ seekingHints
14736
15037
  };
14737
15038
  }
14738
15039
  if (error.name !== "Error") {
@@ -14784,7 +15085,9 @@ var startParsing = async (message, reader) => {
14784
15085
  acknowledgeRemotionLicense,
14785
15086
  logLevel: userLogLevel,
14786
15087
  progressIntervalInMs,
14787
- mp4HeaderSegment
15088
+ mp4HeaderSegment,
15089
+ seekingHints,
15090
+ makeSamplesStartAtZero
14788
15091
  } = payload;
14789
15092
  const {
14790
15093
  postAudioCodec,
@@ -15068,14 +15371,24 @@ var startParsing = async (message, reader) => {
15068
15371
  };
15069
15372
  } : null,
15070
15373
  onDiscardedData: null,
15071
- makeSamplesStartAtZero: true
15374
+ makeSamplesStartAtZero: makeSamplesStartAtZero ?? true,
15375
+ seekingHints: seekingHints ?? null
15072
15376
  });
15073
15377
  post({
15074
15378
  type: "response-done",
15075
- payload: ret
15379
+ payload: ret,
15380
+ seekingHints: await controller.getSeekingHints()
15076
15381
  });
15077
15382
  } catch (e) {
15078
- post(serializeError(e, logLevel));
15383
+ let seekingHintsRes = null;
15384
+ try {
15385
+ seekingHintsRes = await controller.getSeekingHints();
15386
+ } catch {}
15387
+ post(serializeError({
15388
+ error: e,
15389
+ logLevel,
15390
+ seekingHints: seekingHintsRes
15391
+ }));
15079
15392
  }
15080
15393
  };
15081
15394
  var onMessageForWorker = forwardMediaParserControllerToWorker(controller);