@remotion/media-parser 4.0.289 → 4.0.291

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 (167) hide show
  1. package/dist/containers/flac/get-channel-count.d.ts +1 -1
  2. package/dist/containers/iso-base-media/base-media-box.d.ts +0 -1
  3. package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.d.ts +4 -1
  4. package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.js +9 -5
  5. package/dist/containers/iso-base-media/find-keyframe-before-time.js +16 -11
  6. package/dist/containers/iso-base-media/find-track-to-seek.d.ts +14 -0
  7. package/dist/containers/iso-base-media/find-track-to-seek.js +39 -0
  8. package/dist/containers/iso-base-media/get-children.js +2 -2
  9. package/dist/containers/iso-base-media/get-keyframes.js +6 -1
  10. package/dist/containers/iso-base-media/get-mfra-seeking-box.d.ts +3 -1
  11. package/dist/containers/iso-base-media/get-mfra-seeking-box.js +5 -1
  12. package/dist/containers/iso-base-media/get-moov-atom.js +6 -3
  13. package/dist/containers/iso-base-media/get-sample-position-bounds.js +3 -1
  14. package/dist/containers/iso-base-media/get-sample-positions-from-track.js +1 -1
  15. package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.d.ts +14 -0
  16. package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +89 -0
  17. package/dist/containers/iso-base-media/get-seeking-byte.d.ts +3 -3
  18. package/dist/containers/iso-base-media/get-seeking-byte.js +32 -96
  19. package/dist/containers/iso-base-media/get-video-codec-from-iso-track.d.ts +1 -1
  20. package/dist/containers/iso-base-media/mdat/calculate-jump-marks.d.ts +6 -0
  21. package/dist/containers/iso-base-media/mdat/calculate-jump-marks.js +131 -0
  22. package/dist/containers/iso-base-media/mdat/mdat.d.ts +2 -2
  23. package/dist/containers/iso-base-media/mdat/mdat.js +18 -2
  24. package/dist/containers/iso-base-media/mfra/find-best-segment-from-tfra.d.ts +3 -3
  25. package/dist/containers/iso-base-media/mfra/find-best-segment-from-tfra.js +2 -2
  26. package/dist/containers/iso-base-media/mfra/get-mfra-atom.d.ts +5 -1
  27. package/dist/containers/iso-base-media/mfra/get-mfra-atom.js +3 -1
  28. package/dist/containers/iso-base-media/mfra/get-mfro-atom.d.ts +5 -1
  29. package/dist/containers/iso-base-media/mfra/get-mfro-atom.js +3 -1
  30. package/dist/containers/iso-base-media/parse-boxes.js +5 -2
  31. package/dist/containers/iso-base-media/process-box.d.ts +16 -5
  32. package/dist/containers/iso-base-media/process-box.js +206 -118
  33. package/dist/containers/iso-base-media/sample-positions.d.ts +25 -0
  34. package/dist/containers/iso-base-media/sample-positions.js +37 -0
  35. package/dist/containers/iso-base-media/seeking-hints.d.ts +1 -1
  36. package/dist/containers/iso-base-media/stsd/samples.js +1 -0
  37. package/dist/containers/iso-base-media/stsd/stsc.d.ts +1 -6
  38. package/dist/containers/iso-base-media/stsd/stsc.js +2 -5
  39. package/dist/containers/iso-base-media/stsd/stss.d.ts +1 -1
  40. package/dist/containers/iso-base-media/stsd/stss.js +2 -2
  41. package/dist/containers/iso-base-media/turn-sample-positions-into-array.d.ts +19 -0
  42. package/dist/containers/iso-base-media/turn-sample-positions-into-array.js +73 -0
  43. package/dist/containers/m3u/after-manifest-fetch.d.ts +5 -1
  44. package/dist/containers/m3u/after-manifest-fetch.js +3 -1
  45. package/dist/containers/m3u/first-sample-in-m3u-chunk.d.ts +13 -0
  46. package/dist/containers/m3u/first-sample-in-m3u-chunk.js +31 -0
  47. package/dist/containers/m3u/get-seeking-byte.d.ts +13 -0
  48. package/dist/containers/m3u/get-seeking-byte.js +32 -0
  49. package/dist/containers/m3u/get-streams.d.ts +1 -0
  50. package/dist/containers/m3u/get-streams.js +1 -0
  51. package/dist/containers/m3u/iterate-over-segment-files.d.ts +5 -3
  52. package/dist/containers/m3u/iterate-over-segment-files.js +11 -1
  53. package/dist/containers/m3u/parse-m3u-media-directive.js +1 -0
  54. package/dist/containers/m3u/parse-m3u.js +8 -0
  55. package/dist/containers/m3u/process-m3u-chunk.d.ts +12 -0
  56. package/dist/containers/m3u/process-m3u-chunk.js +274 -0
  57. package/dist/containers/m3u/run-over-m3u.js +7 -80
  58. package/dist/containers/m3u/sample-sorter.d.ts +1 -0
  59. package/dist/containers/m3u/sample-sorter.js +4 -1
  60. package/dist/containers/m3u/seek/get-chunk-to-seek-to.d.ts +5 -0
  61. package/dist/containers/m3u/seek/get-chunk-to-seek-to.js +14 -0
  62. package/dist/containers/m3u/seeking-hints.d.ts +2 -0
  63. package/dist/containers/m3u/seeking-hints.js +9 -0
  64. package/dist/containers/m3u/select-stream.d.ts +2 -1
  65. package/dist/containers/m3u/select-stream.js +7 -2
  66. package/dist/containers/m3u/types.d.ts +1 -0
  67. package/dist/containers/mp3/get-duration.d.ts +5 -0
  68. package/dist/containers/riff/seek/fetch-idx1.d.ts +3 -1
  69. package/dist/containers/riff/seek/fetch-idx1.js +3 -1
  70. package/dist/containers/transport-stream/handle-aac-packet.d.ts +2 -2
  71. package/dist/containers/transport-stream/handle-avc-packet.d.ts +2 -2
  72. package/dist/containers/transport-stream/process-audio.d.ts +2 -2
  73. package/dist/containers/transport-stream/process-stream-buffers.d.ts +3 -3
  74. package/dist/containers/transport-stream/process-video.d.ts +2 -2
  75. package/dist/containers/wav/get-duration-from-wav.d.ts +0 -1
  76. package/dist/containers/webm/get-sample-from-block.d.ts +12 -2
  77. package/dist/containers/webm/get-sample-from-block.js +40 -9
  78. package/dist/containers/webm/parse-ebml.js +28 -10
  79. package/dist/containers/webm/seek/fetch-web-cues.d.ts +3 -1
  80. package/dist/containers/webm/seek/fetch-web-cues.js +3 -1
  81. package/dist/containers/webm/state-for-processing.d.ts +2 -2
  82. package/dist/controller/media-parser-controller.d.ts +1 -1
  83. package/dist/controller/media-parser-controller.js +6 -2
  84. package/dist/controller/seek-signal.d.ts +1 -5
  85. package/dist/download-and-parse-media.js +1 -1
  86. package/dist/esm/index.mjs +1400 -611
  87. package/dist/esm/node.mjs +23 -3
  88. package/dist/esm/server-worker.mjs +8 -1
  89. package/dist/esm/universal.mjs +168 -15
  90. package/dist/esm/web.mjs +145 -13
  91. package/dist/esm/worker-server-entry.mjs +1467 -635
  92. package/dist/esm/worker-web-entry.mjs +1439 -634
  93. package/dist/esm/worker.mjs +8 -1
  94. package/dist/get-audio-codec.js +3 -0
  95. package/dist/get-duration.js +2 -1
  96. package/dist/get-fps.js +2 -1
  97. package/dist/get-sample-positions-from-mp4.js +10 -5
  98. package/dist/get-sample-positions.js +4 -4
  99. package/dist/get-seeking-byte.d.ts +5 -3
  100. package/dist/get-seeking-byte.js +19 -10
  101. package/dist/get-seeking-hints.d.ts +3 -3
  102. package/dist/get-seeking-hints.js +18 -13
  103. package/dist/get-tracks.d.ts +9 -1
  104. package/dist/get-tracks.js +13 -6
  105. package/dist/index.d.ts +21 -5
  106. package/dist/init-video.js +3 -2
  107. package/dist/internal-parse-media.js +13 -4
  108. package/dist/iterator/buffer-iterator.js +5 -3
  109. package/dist/metadata/metadata-from-iso.js +2 -1
  110. package/dist/options.d.ts +6 -1
  111. package/dist/parse-loop.js +22 -6
  112. package/dist/parse-media-on-worker-entry.js +1 -0
  113. package/dist/parse-media.js +1 -1
  114. package/dist/parse-result.d.ts +2 -2
  115. package/dist/perform-seek.d.ts +3 -1
  116. package/dist/perform-seek.js +3 -1
  117. package/dist/readers/fetch/get-body-and-reader.js +17 -2
  118. package/dist/readers/from-fetch.d.ts +17 -1
  119. package/dist/readers/from-fetch.js +68 -13
  120. package/dist/readers/from-node.js +24 -2
  121. package/dist/readers/from-web-file.js +3 -0
  122. package/dist/readers/reader.d.ts +19 -2
  123. package/dist/readers/universal.js +9 -0
  124. package/dist/readers/web.js +6 -0
  125. package/dist/register-track.d.ts +3 -3
  126. package/dist/seek-backwards.d.ts +3 -1
  127. package/dist/seek-backwards.js +4 -1
  128. package/dist/seek-forwards.d.ts +3 -1
  129. package/dist/seek-forwards.js +3 -1
  130. package/dist/seeking-hints.d.ts +4 -1
  131. package/dist/set-seeking-hints.js +4 -0
  132. package/dist/skip.d.ts +5 -0
  133. package/dist/skip.js +6 -1
  134. package/dist/state/can-skip-tracks.d.ts +1 -0
  135. package/dist/state/can-skip-tracks.js +10 -6
  136. package/dist/state/iso-base-media/cached-sample-positions.d.ts +15 -1
  137. package/dist/state/iso-base-media/cached-sample-positions.js +9 -4
  138. package/dist/state/iso-base-media/iso-state.d.ts +5 -1
  139. package/dist/state/iso-base-media/iso-state.js +2 -1
  140. package/dist/state/iso-base-media/lazy-mfra-load.d.ts +3 -1
  141. package/dist/state/iso-base-media/lazy-mfra-load.js +2 -1
  142. package/dist/state/keyframes.js +1 -0
  143. package/dist/state/m3u-state.d.ts +15 -4
  144. package/dist/state/m3u-state.js +20 -0
  145. package/dist/state/matroska/lazy-cues-fetch.d.ts +3 -1
  146. package/dist/state/matroska/lazy-cues-fetch.js +2 -1
  147. package/dist/state/matroska/webm.d.ts +3 -1
  148. package/dist/state/matroska/webm.js +2 -1
  149. package/dist/state/mp3.d.ts +16 -5
  150. package/dist/state/mp3.js +7 -5
  151. package/dist/state/parser-state.d.ts +31 -15
  152. package/dist/state/parser-state.js +19 -5
  153. package/dist/state/riff/lazy-idx1-fetch.d.ts +5 -3
  154. package/dist/state/riff/lazy-idx1-fetch.js +2 -1
  155. package/dist/state/riff.d.ts +5 -3
  156. package/dist/state/riff.js +2 -1
  157. package/dist/state/sample-callbacks.d.ts +3 -2
  158. package/dist/state/sample-callbacks.js +3 -3
  159. package/dist/version.d.ts +1 -1
  160. package/dist/version.js +1 -1
  161. package/dist/work-on-seek-request.d.ts +6 -3
  162. package/dist/work-on-seek-request.js +13 -13
  163. package/dist/worker/forward-controller-to-worker.js +1 -1
  164. package/dist/worker/serialize-error.js +26 -3
  165. package/dist/worker/worker-types.d.ts +7 -1
  166. package/dist/worker-server.js +2 -2
  167. package/package.json +3 -3
@@ -1,2 +1,2 @@
1
1
  import type { BufferIterator } from '../../iterator/buffer-iterator';
2
- export declare const getChannelCount: (iterator: BufferIterator) => 2 | 1 | 4 | 3 | 5 | 6 | 8 | 7;
2
+ export declare const getChannelCount: (iterator: BufferIterator) => 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
@@ -34,5 +34,4 @@ export interface RegularBox extends BaseBox {
34
34
  offset: number;
35
35
  type: 'regular-box';
36
36
  }
37
- export type BoxAndNext = IsoBaseMediaBox | null;
38
37
  export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | IlstBox | EsdsBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | HdlrBox | ColorParameterBox | TfdtBox | TfhdBox | TfraBox;
@@ -6,6 +6,9 @@ export declare const collectSamplePositionsFromMoofBoxes: ({ moofBoxes, tfraBoxe
6
6
  tfraBoxes: TfraBox[];
7
7
  tkhdBox: TkhdBox;
8
8
  }) => {
9
- samplePositions: import("../..").SamplePosition[][];
9
+ samplePositions: {
10
+ isLastFragment: boolean;
11
+ samples: import("../..").SamplePosition[];
12
+ }[];
10
13
  isComplete: boolean;
11
14
  };
@@ -5,11 +5,15 @@ const samples_from_moof_1 = require("../../samples-from-moof");
5
5
  const collectSamplePositionsFromMoofBoxes = ({ moofBoxes, tfraBoxes, tkhdBox, }) => {
6
6
  const isComplete = tfraBoxes.length > 0 &&
7
7
  tfraBoxes.every((t) => t.entries.length === moofBoxes.length);
8
- const samplePositions = moofBoxes.map((m) => {
9
- return (0, samples_from_moof_1.getSamplesFromMoof)({
10
- moofBox: m,
11
- trackId: tkhdBox.trackId,
12
- });
8
+ const samplePositions = moofBoxes.map((m, index) => {
9
+ const isLastFragment = index === moofBoxes.length - 1 && isComplete;
10
+ return {
11
+ isLastFragment,
12
+ samples: (0, samples_from_moof_1.getSamplesFromMoof)({
13
+ moofBox: m,
14
+ trackId: tkhdBox.trackId,
15
+ }),
16
+ };
13
17
  });
14
18
  return { samplePositions, isComplete };
15
19
  };
@@ -3,26 +3,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findKeyframeBeforeTime = void 0;
4
4
  const log_1 = require("../../log");
5
5
  const findKeyframeBeforeTime = ({ samplePositions, time, timescale, mediaSections, logLevel, }) => {
6
- let byte = 0;
7
- let sam = null;
6
+ let videoByte = 0;
7
+ let videoSample = null;
8
8
  for (const sample of samplePositions) {
9
9
  const ctsInSeconds = sample.cts / timescale;
10
10
  const dtsInSeconds = sample.dts / timescale;
11
- if ((ctsInSeconds <= time || dtsInSeconds <= time) &&
12
- byte <= sample.offset &&
13
- sample.isKeyframe) {
14
- byte = sample.offset;
15
- sam = sample;
11
+ if (!sample.isKeyframe) {
12
+ continue;
13
+ }
14
+ if (!(ctsInSeconds <= time || dtsInSeconds <= time)) {
15
+ continue;
16
+ }
17
+ if (videoByte <= sample.offset) {
18
+ videoByte = sample.offset;
19
+ videoSample = sample;
16
20
  }
17
21
  }
18
- if (!sam) {
22
+ if (!videoSample) {
19
23
  throw new Error('No sample found');
20
24
  }
21
- const mediaSection = mediaSections.find((section) => sam.offset >= section.start && sam.offset < section.start + section.size);
25
+ const mediaSection = mediaSections.find((section) => videoSample.offset >= section.start &&
26
+ videoSample.offset < section.start + section.size);
22
27
  if (!mediaSection) {
23
- log_1.Log.trace(logLevel, 'Found a sample, but the offset has not yet been marked as a video section yet. Not yet able to seek, but probably once we have started reading the next box.', sam);
28
+ log_1.Log.trace(logLevel, 'Found a sample, but the offset has not yet been marked as a video section yet. Not yet able to seek, but probably once we have started reading the next box.', videoSample);
24
29
  return null;
25
30
  }
26
- return sam.offset;
31
+ return videoSample.offset;
27
32
  };
28
33
  exports.findKeyframeBeforeTime = findKeyframeBeforeTime;
@@ -0,0 +1,14 @@
1
+ import type { SamplePosition } from '../../get-sample-positions';
2
+ import type { AudioTrack, OtherTrack, VideoTrack } from '../../get-tracks';
3
+ import type { IsoBaseMediaStructure } from '../../parse-result';
4
+ import type { StructureState } from '../../state/structure';
5
+ export declare const findAnyTrackWithSamplePositions: (allTracks: (VideoTrack | AudioTrack | OtherTrack)[], struc: IsoBaseMediaStructure) => {
6
+ track: VideoTrack | AudioTrack;
7
+ samplePositions: SamplePosition[];
8
+ } | null;
9
+ type TrackWithSamplePositions = {
10
+ track: VideoTrack | AudioTrack;
11
+ samplePositions: SamplePosition[];
12
+ };
13
+ export declare const findTrackToSeek: (allTracks: (VideoTrack | AudioTrack | OtherTrack)[], structure: StructureState) => TrackWithSamplePositions | null;
14
+ export {};
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findTrackToSeek = exports.findAnyTrackWithSamplePositions = void 0;
4
+ const get_sample_positions_from_track_1 = require("./get-sample-positions-from-track");
5
+ const traversal_1 = require("./traversal");
6
+ const findAnyTrackWithSamplePositions = (allTracks, struc) => {
7
+ for (const track of allTracks) {
8
+ if (track.type === 'video' || track.type === 'audio') {
9
+ const { samplePositions } = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)({
10
+ trakBox: track.trakBox,
11
+ moofBoxes: (0, traversal_1.getMoofBoxes)(struc.boxes),
12
+ tfraBoxes: (0, traversal_1.getTfraBoxes)(struc),
13
+ });
14
+ if (samplePositions.length === 0) {
15
+ continue;
16
+ }
17
+ return { track, samplePositions };
18
+ }
19
+ }
20
+ return null;
21
+ };
22
+ exports.findAnyTrackWithSamplePositions = findAnyTrackWithSamplePositions;
23
+ const findTrackToSeek = (allTracks, structure) => {
24
+ const firstVideoTrack = allTracks.find((t) => t.type === 'video');
25
+ const struc = structure.getIsoStructure();
26
+ if (!firstVideoTrack) {
27
+ return (0, exports.findAnyTrackWithSamplePositions)(allTracks, struc);
28
+ }
29
+ const { samplePositions } = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)({
30
+ trakBox: firstVideoTrack.trakBox,
31
+ moofBoxes: (0, traversal_1.getMoofBoxes)(struc.boxes),
32
+ tfraBoxes: (0, traversal_1.getTfraBoxes)(struc),
33
+ });
34
+ if (samplePositions.length === 0) {
35
+ return (0, exports.findAnyTrackWithSamplePositions)(allTracks, struc);
36
+ }
37
+ return { track: firstVideoTrack, samplePositions };
38
+ };
39
+ exports.findTrackToSeek = findTrackToSeek;
@@ -13,10 +13,10 @@ const getIsoBaseMediaChildren = async ({ size, iterator, logLevel, onlyIfMoovAto
13
13
  onlyIfMdatAtomExpected: null,
14
14
  contentLength,
15
15
  });
16
- if (!parsed) {
16
+ if (parsed.type !== 'box') {
17
17
  throw new Error('Expected box');
18
18
  }
19
- boxes.push(parsed);
19
+ boxes.push(parsed.box);
20
20
  }
21
21
  if (iterator.counter.getOffset() > size + initial) {
22
22
  throw new Error(`read too many bytes - size: ${size}, read: ${iterator.counter.getOffset() - initial}. initial offset: ${initial}`);
@@ -5,7 +5,12 @@ const get_tracks_1 = require("../../get-tracks");
5
5
  const get_sample_positions_from_track_1 = require("./get-sample-positions-from-track");
6
6
  const traversal_1 = require("./traversal");
7
7
  const getKeyframesFromIsoBaseMedia = (state) => {
8
- const { videoTracks } = (0, get_tracks_1.getTracksFromIsoBaseMedia)(state, true);
8
+ const { videoTracks } = (0, get_tracks_1.getTracksFromIsoBaseMedia)({
9
+ isoState: state.iso,
10
+ m3uPlaylistContext: state.m3uPlaylistContext,
11
+ structure: state.structure,
12
+ mayUsePrecomputed: true,
13
+ });
9
14
  const structure = state.structure.getIsoStructure();
10
15
  const moofBoxes = (0, traversal_1.getMoofBoxes)(structure.boxes);
11
16
  const tfraBoxes = (0, traversal_1.getTfraBoxes)(structure);
@@ -1,4 +1,5 @@
1
1
  import type { MediaParserController } from '../../controller/media-parser-controller';
2
+ import type { PrefetchCache } from '../../fetch';
2
3
  import type { LogLevel } from '../../log';
3
4
  import type { ParseMediaSrc } from '../../options';
4
5
  import type { ReaderInterface } from '../../readers/reader';
@@ -9,5 +10,6 @@ export type MfraSeekingBoxOptions = {
9
10
  readerInterface: ReaderInterface;
10
11
  src: ParseMediaSrc;
11
12
  logLevel: LogLevel;
13
+ prefetchCache: PrefetchCache;
12
14
  };
13
- export declare const getMfraSeekingBox: ({ contentLength, controller, readerInterface, src, logLevel, }: MfraSeekingBoxOptions) => Promise<IsoBaseMediaBox[] | null>;
15
+ export declare const getMfraSeekingBox: ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }: MfraSeekingBoxOptions) => Promise<IsoBaseMediaBox[] | null>;
@@ -4,12 +4,14 @@ exports.getMfraSeekingBox = void 0;
4
4
  const get_children_1 = require("./get-children");
5
5
  const get_mfra_atom_1 = require("./mfra/get-mfra-atom");
6
6
  const get_mfro_atom_1 = require("./mfra/get-mfro-atom");
7
- const getMfraSeekingBox = async ({ contentLength, controller, readerInterface, src, logLevel, }) => {
7
+ const getMfraSeekingBox = async ({ contentLength, controller, readerInterface, src, logLevel, prefetchCache, }) => {
8
8
  const parentSize = await (0, get_mfro_atom_1.getMfroAtom)({
9
9
  contentLength,
10
10
  controller,
11
11
  readerInterface,
12
12
  src,
13
+ logLevel,
14
+ prefetchCache,
13
15
  });
14
16
  if (!parentSize) {
15
17
  return null;
@@ -20,6 +22,8 @@ const getMfraSeekingBox = async ({ contentLength, controller, readerInterface, s
20
22
  readerInterface,
21
23
  src,
22
24
  parentSize,
25
+ logLevel,
26
+ prefetchCache,
23
27
  });
24
28
  mfraAtom.discard(8);
25
29
  return (0, get_children_1.getIsoBaseMediaChildren)({
@@ -10,7 +10,8 @@ const structure_1 = require("../../state/structure");
10
10
  const process_box_1 = require("./process-box");
11
11
  const traversal_1 = require("./traversal");
12
12
  const getMoovAtom = async ({ endOfMdat, state, }) => {
13
- const headerSegment = state.mp4HeaderSegment;
13
+ var _a;
14
+ const headerSegment = (_a = state.m3uPlaylistContext) === null || _a === void 0 ? void 0 : _a.mp4HeaderSegment;
14
15
  if (headerSegment) {
15
16
  const segment = (0, traversal_1.getMoovFromFromIsoStructure)(headerSegment);
16
17
  if (!segment) {
@@ -24,6 +25,8 @@ const getMoovAtom = async ({ endOfMdat, state, }) => {
24
25
  src: state.src,
25
26
  range: endOfMdat,
26
27
  controller: state.controller,
28
+ logLevel: state.logLevel,
29
+ prefetchCache: state.prefetchCache,
27
30
  });
28
31
  const onAudioTrack = state.onAudioTrack
29
32
  ? async ({ track, container }) => {
@@ -84,8 +87,8 @@ const getMoovAtom = async ({ endOfMdat, state, }) => {
84
87
  onlyIfMdatAtomExpected: null,
85
88
  contentLength: state.contentLength - endOfMdat,
86
89
  });
87
- if (box) {
88
- boxes.push(box);
90
+ if (box.type === 'box') {
91
+ boxes.push(box.box);
89
92
  }
90
93
  if (iterator.counter.getOffset() + endOfMdat > state.contentLength) {
91
94
  throw new Error('Read past end of file');
@@ -2,11 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSamplePositionBounds = void 0;
4
4
  const getSamplePositionBounds = (samplePositions, timescale) => {
5
+ var _a;
5
6
  let min = Infinity;
6
7
  let max = -Infinity;
7
8
  for (const samplePosition of samplePositions) {
8
9
  const timestampMin = Math.min(samplePosition.cts, samplePosition.dts);
9
- const timestampMax = Math.max(samplePosition.cts, samplePosition.dts);
10
+ const timestampMax = Math.max(samplePosition.cts, samplePosition.dts) +
11
+ ((_a = samplePosition.duration) !== null && _a !== void 0 ? _a : 0);
10
12
  if (timestampMin < min) {
11
13
  min = timestampMin;
12
14
  }
@@ -16,7 +16,7 @@ const getSamplePositionsFromTrack = ({ trakBox, moofBoxes, tfraBoxes, }) => {
16
16
  tkhdBox,
17
17
  });
18
18
  return {
19
- samplePositions: samplePositions.flat(1),
19
+ samplePositions: samplePositions.map((s) => s.samples).flat(1),
20
20
  isComplete,
21
21
  };
22
22
  }
@@ -0,0 +1,14 @@
1
+ import type { AudioTrack, OtherTrack, VideoTrack } from '../../get-tracks';
2
+ import type { LogLevel } from '../../log';
3
+ import type { IsoBaseMediaSeekingHints } from '../../seeking-hints';
4
+ import type { IsoBaseMediaState } from '../../state/iso-base-media/iso-state';
5
+ import type { SeekResolution } from '../../work-on-seek-request';
6
+ export declare const getSeekingByteFromFragmentedMp4: ({ info, time, logLevel, currentPosition, isoState, allTracks, isLastChunkInPlaylist, }: {
7
+ info: IsoBaseMediaSeekingHints;
8
+ time: number;
9
+ logLevel: LogLevel;
10
+ currentPosition: number;
11
+ isoState: IsoBaseMediaState;
12
+ allTracks: (VideoTrack | AudioTrack | OtherTrack)[];
13
+ isLastChunkInPlaylist: boolean;
14
+ }) => Promise<SeekResolution>;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSeekingByteFromFragmentedMp4 = void 0;
4
+ const log_1 = require("../../log");
5
+ const video_section_1 = require("../../state/video-section");
6
+ const collect_sample_positions_from_moof_boxes_1 = require("./collect-sample-positions-from-moof-boxes");
7
+ const find_keyframe_before_time_1 = require("./find-keyframe-before-time");
8
+ const get_sample_position_bounds_1 = require("./get-sample-position-bounds");
9
+ const find_best_segment_from_tfra_1 = require("./mfra/find-best-segment-from-tfra");
10
+ const traversal_1 = require("./traversal");
11
+ const getSeekingByteFromFragmentedMp4 = async ({ info, time, logLevel, currentPosition, isoState, allTracks, isLastChunkInPlaylist, }) => {
12
+ const firstVideoTrack = allTracks.find((t) => t.type === 'video');
13
+ // If there is both video and audio, seek based on video, but if not then audio is also okay
14
+ const firstTrack = firstVideoTrack !== null && firstVideoTrack !== void 0 ? firstVideoTrack : allTracks.find((t) => t.type === 'audio');
15
+ if (!firstTrack) {
16
+ throw new Error('no video and no audio tracks');
17
+ }
18
+ const tkhdBox = (0, traversal_1.getTkhdBox)(firstTrack.trakBox);
19
+ if (!tkhdBox) {
20
+ throw new Error('Expected tkhd box in trak box');
21
+ }
22
+ const { samplePositions: samplePositionsArray } = (0, collect_sample_positions_from_moof_boxes_1.collectSamplePositionsFromMoofBoxes)({
23
+ moofBoxes: info.moofBoxes,
24
+ tfraBoxes: info.tfraBoxes,
25
+ tkhdBox,
26
+ });
27
+ log_1.Log.trace(logLevel, 'Fragmented MP4 - Checking if we have seeking info for this time range');
28
+ for (const positions of samplePositionsArray) {
29
+ const { min, max } = (0, get_sample_position_bounds_1.getSamplePositionBounds)(positions.samples, firstTrack.timescale);
30
+ if (min <= time &&
31
+ (positions.isLastFragment || isLastChunkInPlaylist || time <= max)) {
32
+ log_1.Log.trace(logLevel, `Fragmented MP4 - Found that we have seeking info for this time range: ${min} <= ${time} <= ${max}`);
33
+ const kf = (0, find_keyframe_before_time_1.findKeyframeBeforeTime)({
34
+ samplePositions: positions.samples,
35
+ time,
36
+ timescale: firstTrack.timescale,
37
+ logLevel,
38
+ mediaSections: info.mediaSections,
39
+ });
40
+ if (kf) {
41
+ return {
42
+ type: 'do-seek',
43
+ byte: kf,
44
+ };
45
+ }
46
+ }
47
+ }
48
+ const atom = await (info.mfraAlreadyLoaded
49
+ ? Promise.resolve(info.mfraAlreadyLoaded)
50
+ : isoState.mfra.triggerLoad());
51
+ if (atom) {
52
+ const moofOffset = (0, find_best_segment_from_tfra_1.findBestSegmentFromTfra)({
53
+ mfra: atom,
54
+ time,
55
+ firstTrack,
56
+ timescale: firstTrack.timescale,
57
+ });
58
+ if (moofOffset !== null &&
59
+ !(moofOffset.start <= currentPosition && currentPosition < moofOffset.end)) {
60
+ log_1.Log.verbose(logLevel, `Fragmented MP4 - Found based on mfra information that we should seek to: ${moofOffset.start} ${moofOffset.end}`);
61
+ return {
62
+ type: 'intermediary-seek',
63
+ byte: moofOffset.start,
64
+ };
65
+ }
66
+ }
67
+ log_1.Log.trace(logLevel, 'Fragmented MP4 - No seeking info found for this time range.');
68
+ if ((0, video_section_1.isByteInMediaSection)({
69
+ position: currentPosition,
70
+ mediaSections: info.mediaSections,
71
+ }) !== 'in-section') {
72
+ return {
73
+ type: 'valid-but-must-wait',
74
+ };
75
+ }
76
+ log_1.Log.trace(logLevel, 'Fragmented MP4 - Inside the wrong video section, skipping to the end of the section');
77
+ const mediaSection = (0, video_section_1.getCurrentMediaSection)({
78
+ offset: currentPosition,
79
+ mediaSections: info.mediaSections,
80
+ });
81
+ if (!mediaSection) {
82
+ throw new Error('No video section defined');
83
+ }
84
+ return {
85
+ type: 'intermediary-seek',
86
+ byte: mediaSection.start + mediaSection.size,
87
+ };
88
+ };
89
+ exports.getSeekingByteFromFragmentedMp4 = getSeekingByteFromFragmentedMp4;
@@ -1,15 +1,15 @@
1
1
  import type { LogLevel } from '../../log';
2
- import type { IsoBaseMediaStructure } from '../../parse-result';
2
+ import type { M3uPlaylistContext } from '../../options';
3
3
  import type { IsoBaseMediaSeekingHints } from '../../seeking-hints';
4
4
  import type { IsoBaseMediaState } from '../../state/iso-base-media/iso-state';
5
5
  import type { StructureState } from '../../state/structure';
6
6
  import type { SeekResolution } from '../../work-on-seek-request';
7
- export declare const getSeekingByteFromIsoBaseMedia: ({ info, time, logLevel, currentPosition, isoState, mp4HeaderSegment, structure, }: {
7
+ export declare const getSeekingByteFromIsoBaseMedia: ({ info, time, logLevel, currentPosition, isoState, m3uPlaylistContext, structure, }: {
8
8
  info: IsoBaseMediaSeekingHints;
9
9
  time: number;
10
10
  logLevel: LogLevel;
11
11
  currentPosition: number;
12
12
  isoState: IsoBaseMediaState;
13
- mp4HeaderSegment: IsoBaseMediaStructure | null;
13
+ m3uPlaylistContext: M3uPlaylistContext | null;
14
14
  structure: StructureState;
15
15
  }) => Promise<SeekResolution>;
@@ -3,132 +3,68 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSeekingByteFromIsoBaseMedia = void 0;
4
4
  const get_tracks_1 = require("../../get-tracks");
5
5
  const log_1 = require("../../log");
6
- const video_section_1 = require("../../state/video-section");
7
- const collect_sample_positions_from_moof_boxes_1 = require("./collect-sample-positions-from-moof-boxes");
8
6
  const find_keyframe_before_time_1 = require("./find-keyframe-before-time");
9
- const get_sample_position_bounds_1 = require("./get-sample-position-bounds");
10
- const get_sample_positions_from_track_1 = require("./get-sample-positions-from-track");
11
- const find_best_segment_from_tfra_1 = require("./mfra/find-best-segment-from-tfra");
7
+ const find_track_to_seek_1 = require("./find-track-to-seek");
8
+ const get_seeking_byte_from_fragmented_mp4_1 = require("./get-seeking-byte-from-fragmented-mp4");
12
9
  const traversal_1 = require("./traversal");
13
- const getSeekingByteFromIsoBaseMedia = async ({ info, time, logLevel, currentPosition, isoState, mp4HeaderSegment, structure, }) => {
14
- const tracks = (0, get_tracks_1.getTracksFromMoovBox)(info.moovBox);
10
+ const getSeekingByteFromIsoBaseMedia = ({ info, time, logLevel, currentPosition, isoState, m3uPlaylistContext, structure, }) => {
11
+ var _a, _b;
12
+ const tracks = (0, get_tracks_1.getTracksFromIsoBaseMedia)({
13
+ isoState,
14
+ m3uPlaylistContext,
15
+ structure,
16
+ mayUsePrecomputed: false,
17
+ });
15
18
  const allTracks = [
16
19
  ...tracks.videoTracks,
17
20
  ...tracks.audioTracks,
18
21
  ...tracks.otherTracks,
19
22
  ];
20
23
  const hasMoov = Boolean((0, traversal_1.getMoovBoxFromState)({
21
- mp4HeaderSegment,
22
24
  structureState: structure,
23
25
  isoState,
24
26
  mayUsePrecomputed: false,
27
+ mp4HeaderSegment: (_a = m3uPlaylistContext === null || m3uPlaylistContext === void 0 ? void 0 : m3uPlaylistContext.mp4HeaderSegment) !== null && _a !== void 0 ? _a : null,
25
28
  }));
26
29
  if (!hasMoov) {
27
30
  log_1.Log.trace(logLevel, 'No moov box found, must wait');
28
- return {
31
+ return Promise.resolve({
29
32
  type: 'valid-but-must-wait',
30
- };
31
- }
32
- const firstVideoTrack = allTracks.find((t) => t.type === 'video');
33
- if (!firstVideoTrack) {
34
- throw new Error('No video track found');
33
+ });
35
34
  }
36
- const { timescale } = firstVideoTrack;
37
35
  if (info.moofBoxes.length > 0) {
38
- const tkhdBox = (0, traversal_1.getTkhdBox)(firstVideoTrack.trakBox);
39
- if (!tkhdBox) {
40
- throw new Error('Expected tkhd box in trak box');
41
- }
42
- const { samplePositions: samplePositionsArray } = (0, collect_sample_positions_from_moof_boxes_1.collectSamplePositionsFromMoofBoxes)({
43
- moofBoxes: info.moofBoxes,
44
- tfraBoxes: info.tfraBoxes,
45
- tkhdBox,
46
- });
47
- log_1.Log.trace(logLevel, 'Fragmented MP4 - Checking if we have seeking info for this time range');
48
- for (const positions of samplePositionsArray) {
49
- const { min, max } = (0, get_sample_position_bounds_1.getSamplePositionBounds)(positions, timescale);
50
- if (min <= time && time <= max) {
51
- log_1.Log.trace(logLevel, `Fragmented MP4 - Found that we have seeking info for this time range: ${min} <= ${time} <= ${max}`);
52
- const kf = (0, find_keyframe_before_time_1.findKeyframeBeforeTime)({
53
- samplePositions: positions,
54
- time,
55
- timescale,
56
- logLevel,
57
- mediaSections: info.mediaSections,
58
- });
59
- if (kf) {
60
- return {
61
- type: 'do-seek',
62
- byte: kf,
63
- };
64
- }
65
- }
66
- }
67
- const atom = await (info.mfraAlreadyLoaded
68
- ? Promise.resolve(info.mfraAlreadyLoaded)
69
- : isoState.mfra.triggerLoad());
70
- if (atom) {
71
- const moofOffset = (0, find_best_segment_from_tfra_1.findBestSegmentFromTfra)({
72
- mfra: atom,
73
- time,
74
- firstVideoTrack,
75
- timescale,
76
- });
77
- if (moofOffset !== null &&
78
- !(moofOffset.start <= currentPosition &&
79
- currentPosition < moofOffset.end)) {
80
- log_1.Log.verbose(logLevel, `Fragmented MP4 - Found based on mfra information that we should seek to: ${moofOffset.start} ${moofOffset.end}`);
81
- return {
82
- type: 'intermediary-seek',
83
- byte: moofOffset.start,
84
- };
85
- }
86
- }
87
- log_1.Log.trace(logLevel, 'Fragmented MP4 - No seeking info found for this time range.');
88
- if ((0, video_section_1.isByteInMediaSection)({
89
- position: currentPosition,
90
- mediaSections: info.mediaSections,
91
- }) !== 'in-section') {
92
- return {
93
- type: 'valid-but-must-wait',
94
- };
95
- }
96
- log_1.Log.trace(logLevel, 'Fragmented MP4 - Inside the wrong video section, skipping to the end of the section');
97
- const mediaSection = (0, video_section_1.getCurrentMediaSection)({
98
- offset: currentPosition,
99
- mediaSections: info.mediaSections,
36
+ return (0, get_seeking_byte_from_fragmented_mp4_1.getSeekingByteFromFragmentedMp4)({
37
+ info,
38
+ time,
39
+ logLevel,
40
+ currentPosition,
41
+ isoState,
42
+ allTracks,
43
+ isLastChunkInPlaylist: (_b = m3uPlaylistContext === null || m3uPlaylistContext === void 0 ? void 0 : m3uPlaylistContext.isLastChunkInPlaylist) !== null && _b !== void 0 ? _b : false,
100
44
  });
101
- if (!mediaSection) {
102
- throw new Error('No video section defined');
103
- }
104
- return {
105
- type: 'intermediary-seek',
106
- byte: mediaSection.start + mediaSection.size,
107
- };
108
45
  }
109
- const { samplePositions, isComplete } = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)({
110
- trakBox: firstVideoTrack.trakBox,
111
- moofBoxes: info.moofBoxes,
112
- tfraBoxes: info.tfraBoxes,
113
- });
114
- if (!isComplete) {
115
- throw new Error('Incomplete sample positions');
46
+ const trackWithSamplePositions = (0, find_track_to_seek_1.findTrackToSeek)(allTracks, structure);
47
+ if (!trackWithSamplePositions) {
48
+ return Promise.resolve({
49
+ type: 'valid-but-must-wait',
50
+ });
116
51
  }
52
+ const { track, samplePositions } = trackWithSamplePositions;
117
53
  const keyframe = (0, find_keyframe_before_time_1.findKeyframeBeforeTime)({
118
54
  samplePositions,
119
55
  time,
120
- timescale,
56
+ timescale: track.timescale,
121
57
  logLevel,
122
58
  mediaSections: info.mediaSections,
123
59
  });
124
60
  if (keyframe) {
125
- return {
61
+ return Promise.resolve({
126
62
  type: 'do-seek',
127
63
  byte: keyframe,
128
- };
64
+ });
129
65
  }
130
- return {
66
+ return Promise.resolve({
131
67
  type: 'invalid',
132
- };
68
+ });
133
69
  };
134
70
  exports.getSeekingByteFromIsoBaseMedia = getSeekingByteFromIsoBaseMedia;
@@ -1,2 +1,2 @@
1
1
  import type { TrakBox } from './trak/trak';
2
- export declare const getVideoCodecFromIsoTrak: (trakBox: TrakBox) => "h265" | "h264" | "av1" | "prores";
2
+ export declare const getVideoCodecFromIsoTrak: (trakBox: TrakBox) => "h264" | "av1" | "h265" | "prores";
@@ -0,0 +1,6 @@
1
+ import type { MinimalFlatSampleForTesting } from '../../../state/iso-base-media/cached-sample-positions';
2
+ export type JumpMark = {
3
+ afterSampleWithOffset: number;
4
+ jumpToOffset: number;
5
+ };
6
+ export declare const calculateJumpMarks: (samplePositionTracks: MinimalFlatSampleForTesting[][], endOfMdat: number) => JumpMark[];