@remotion/media-parser 4.0.249 → 4.0.250

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 (121) hide show
  1. package/dist/boxes/iso-base-media/continue-mdat-routine.d.ts +14 -0
  2. package/dist/boxes/iso-base-media/continue-mdat-routine.js +74 -0
  3. package/dist/boxes/iso-base-media/get-children.d.ts +2 -8
  4. package/dist/boxes/iso-base-media/get-children.js +14 -30
  5. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +3 -23
  6. package/dist/boxes/iso-base-media/mdat/mdat.js +80 -130
  7. package/dist/boxes/iso-base-media/moov/moov.d.ts +1 -6
  8. package/dist/boxes/iso-base-media/moov/moov.js +5 -14
  9. package/dist/boxes/iso-base-media/parse-all-children.d.ts +8 -0
  10. package/dist/boxes/iso-base-media/parse-all-children.js +20 -0
  11. package/dist/boxes/iso-base-media/parse-boxes.d.ts +2 -10
  12. package/dist/boxes/iso-base-media/parse-boxes.js +33 -116
  13. package/dist/boxes/iso-base-media/parse-mdat-partially.d.ts +1 -4
  14. package/dist/boxes/iso-base-media/parse-mdat-partially.js +2 -11
  15. package/dist/boxes/iso-base-media/process-box.d.ts +1 -9
  16. package/dist/boxes/iso-base-media/process-box.js +49 -143
  17. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +1 -4
  18. package/dist/boxes/iso-base-media/stsd/mebx.js +5 -14
  19. package/dist/boxes/iso-base-media/stsd/samples.d.ts +4 -12
  20. package/dist/boxes/iso-base-media/stsd/samples.js +24 -66
  21. package/dist/boxes/iso-base-media/stsd/stsd.d.ts +1 -4
  22. package/dist/boxes/iso-base-media/stsd/stsd.js +2 -5
  23. package/dist/boxes/iso-base-media/trak/trak.d.ts +1 -6
  24. package/dist/boxes/iso-base-media/trak/trak.js +5 -14
  25. package/dist/boxes/iso-base-media/traversal.d.ts +0 -2
  26. package/dist/boxes/iso-base-media/traversal.js +1 -12
  27. package/dist/boxes/mp3/id3.d.ts +1 -3
  28. package/dist/boxes/mp3/id3.js +7 -5
  29. package/dist/boxes/mp3/parse-mp3.d.ts +2 -3
  30. package/dist/boxes/mp3/parse-mp3.js +3 -19
  31. package/dist/boxes/riff/expect-riff-box.d.ts +1 -9
  32. package/dist/boxes/riff/expect-riff-box.js +47 -25
  33. package/dist/boxes/riff/get-tracks-from-avi.d.ts +1 -1
  34. package/dist/boxes/riff/get-tracks-from-avi.js +6 -10
  35. package/dist/boxes/riff/parse-fmt-box.d.ts +3 -2
  36. package/dist/boxes/riff/parse-fmt-box.js +7 -5
  37. package/dist/boxes/riff/parse-list-box.d.ts +1 -3
  38. package/dist/boxes/riff/parse-list-box.js +16 -16
  39. package/dist/boxes/riff/parse-movi.d.ts +2 -5
  40. package/dist/boxes/riff/parse-movi.js +34 -56
  41. package/dist/boxes/riff/parse-riff-body.d.ts +2 -6
  42. package/dist/boxes/riff/parse-riff-body.js +15 -95
  43. package/dist/boxes/riff/parse-riff-box.d.ts +1 -4
  44. package/dist/boxes/riff/parse-riff-box.js +3 -7
  45. package/dist/boxes/riff/parse-riff-header.d.ts +7 -0
  46. package/dist/boxes/riff/parse-riff-header.js +23 -0
  47. package/dist/boxes/riff/parse-riff.d.ts +7 -0
  48. package/dist/boxes/riff/parse-riff.js +15 -0
  49. package/dist/boxes/riff/parse-strf.d.ts +4 -4
  50. package/dist/boxes/riff/parse-strf.js +4 -8
  51. package/dist/boxes/riff/parse-strh.js +11 -0
  52. package/dist/boxes/riff/parse-video-section.d.ts +6 -0
  53. package/dist/boxes/riff/parse-video-section.js +20 -0
  54. package/dist/boxes/riff/riff-box.d.ts +4 -5
  55. package/dist/boxes/riff/traversal.d.ts +1 -2
  56. package/dist/boxes/riff/traversal.js +1 -6
  57. package/dist/boxes/transport-stream/get-tracks.d.ts +2 -3
  58. package/dist/boxes/transport-stream/get-tracks.js +4 -3
  59. package/dist/boxes/transport-stream/parse-packet.d.ts +1 -7
  60. package/dist/boxes/transport-stream/parse-packet.js +3 -4
  61. package/dist/boxes/transport-stream/parse-stream-packet.d.ts +1 -5
  62. package/dist/boxes/transport-stream/parse-stream-packet.js +10 -12
  63. package/dist/boxes/transport-stream/parse-transport-stream.d.ts +1 -7
  64. package/dist/boxes/transport-stream/parse-transport-stream.js +7 -26
  65. package/dist/boxes/transport-stream/process-stream-buffers.d.ts +1 -2
  66. package/dist/boxes/transport-stream/process-stream-buffers.js +3 -3
  67. package/dist/boxes/webm/parse-ebml.js +3 -0
  68. package/dist/boxes/webm/parse-webm-header.d.ts +2 -4
  69. package/dist/boxes/webm/parse-webm-header.js +41 -25
  70. package/dist/boxes/webm/segments/parse-children.d.ts +2 -16
  71. package/dist/boxes/webm/segments/parse-children.js +7 -130
  72. package/dist/boxes/webm/segments.d.ts +4 -8
  73. package/dist/boxes/webm/segments.js +41 -123
  74. package/dist/buffer-iterator.d.ts +0 -3
  75. package/dist/buffer-iterator.js +6 -16
  76. package/dist/bun-reader.d.ts +1 -0
  77. package/dist/bun-reader.js +17 -0
  78. package/dist/emit-available-info.js +4 -4
  79. package/dist/esm/from-node.mjs +8 -9
  80. package/dist/esm/index.mjs +4224 -4950
  81. package/dist/file-types/detect-file-type.js +4 -2
  82. package/dist/get-audio-codec.d.ts +1 -1
  83. package/dist/get-audio-codec.js +2 -2
  84. package/dist/get-dimensions.js +1 -1
  85. package/dist/get-duration.js +1 -1
  86. package/dist/get-is-hdr.d.ts +1 -1
  87. package/dist/get-is-hdr.js +2 -2
  88. package/dist/get-tracks.d.ts +1 -1
  89. package/dist/get-tracks.js +14 -13
  90. package/dist/get-video-codec.d.ts +1 -1
  91. package/dist/get-video-codec.js +2 -2
  92. package/dist/index.d.ts +50 -24
  93. package/dist/index.js +1 -1
  94. package/dist/may-skip-video-data/may-skip-video-data.js +6 -2
  95. package/dist/parse-media.js +45 -30
  96. package/dist/parse-result.d.ts +1 -18
  97. package/dist/parse-video.d.ts +3 -17
  98. package/dist/parse-video.js +45 -32
  99. package/dist/readers/from-node.js +7 -8
  100. package/dist/state/can-skip-tracks.d.ts +8 -1
  101. package/dist/state/can-skip-tracks.js +38 -27
  102. package/dist/state/iso-base-media/cached-sample-positions.d.ts +15 -0
  103. package/dist/state/iso-base-media/cached-sample-positions.js +42 -0
  104. package/dist/state/iso-base-media/iso-state.d.ts +8 -0
  105. package/dist/state/iso-base-media/iso-state.js +15 -0
  106. package/dist/state/iso-state.d.ts +4 -0
  107. package/dist/state/iso-state.js +13 -0
  108. package/dist/state/parser-state.d.ts +49 -14
  109. package/dist/state/parser-state.js +11 -3
  110. package/dist/state/sample-callbacks.d.ts +5 -1
  111. package/dist/state/sample-callbacks.js +4 -1
  112. package/dist/state/transport-stream.d.ts +8 -0
  113. package/dist/state/transport-stream.js +11 -0
  114. package/dist/state/video-section.d.ts +16 -0
  115. package/dist/state/video-section.js +37 -0
  116. package/dist/state/webm.d.ts +15 -0
  117. package/dist/state/webm.js +32 -0
  118. package/dist/version.d.ts +1 -1
  119. package/dist/version.js +1 -1
  120. package/package.json +3 -3
  121. package/test.json +663 -0
@@ -43,10 +43,12 @@ const isTransportStream = (data) => {
43
43
  exports.isTransportStream = isTransportStream;
44
44
  const isMp3 = (data) => {
45
45
  const mpegPattern = new Uint8Array([0xff, 0xf3, 0xe4, 0x64]);
46
- const id3v3Pattern = new Uint8Array([73, 68, 51, 3]);
47
- const id3v2Pattern = new Uint8Array([73, 68, 51, 2]);
46
+ const id3v4Pattern = new Uint8Array([0x49, 0x44, 0x33, 4]);
47
+ const id3v3Pattern = new Uint8Array([0x49, 0x44, 0x33, 3]);
48
+ const id3v2Pattern = new Uint8Array([0x49, 0x44, 0x33, 2]);
48
49
  const subarray = data.subarray(0, 4);
49
50
  return ((0, exports.matchesPattern)(mpegPattern)(subarray) ||
51
+ (0, exports.matchesPattern)(id3v4Pattern)(subarray) ||
50
52
  (0, exports.matchesPattern)(id3v3Pattern)(subarray) ||
51
53
  (0, exports.matchesPattern)(id3v2Pattern)(subarray));
52
54
  };
@@ -3,7 +3,7 @@ import type { TrakBox } from './boxes/iso-base-media/trak/trak';
3
3
  import { type MediaParserAudioCodec } from './get-tracks';
4
4
  import type { Structure } from './parse-result';
5
5
  import type { ParserState } from './state/parser-state';
6
- export declare const getAudioCodec: (boxes: Structure, parserState: ParserState) => MediaParserAudioCodec | null;
6
+ export declare const getAudioCodec: (parserState: ParserState) => MediaParserAudioCodec | null;
7
7
  export declare const hasAudioCodec: (boxes: Structure, state: ParserState) => boolean;
8
8
  type AudioCodecInfo = {
9
9
  format: string;
@@ -4,8 +4,8 @@ exports.getAudioCodecFromTrack = exports.getAudioCodecStringFromTrak = exports.g
4
4
  const traversal_1 = require("./boxes/iso-base-media/traversal");
5
5
  const get_fps_1 = require("./get-fps");
6
6
  const get_tracks_1 = require("./get-tracks");
7
- const getAudioCodec = (boxes, parserState) => {
8
- const tracks = (0, get_tracks_1.getTracks)(boxes, parserState);
7
+ const getAudioCodec = (parserState) => {
8
+ const tracks = (0, get_tracks_1.getTracks)(parserState);
9
9
  const allTracks = tracks.audioTracks.length +
10
10
  tracks.otherTracks.length +
11
11
  tracks.videoTracks.length;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hasDimensions = exports.getDimensions = void 0;
4
4
  const get_tracks_1 = require("./get-tracks");
5
5
  const getDimensions = (boxes, state) => {
6
- const { videoTracks } = (0, get_tracks_1.getTracks)(boxes, state);
6
+ const { videoTracks } = (0, get_tracks_1.getTracks)(state);
7
7
  if (!videoTracks.length) {
8
8
  if (boxes.type === 'mp3') {
9
9
  return null;
@@ -51,7 +51,7 @@ const getDurationFromIsoBaseMedia = (structure, parserState) => {
51
51
  if (mvhdBox.durationInSeconds > 0) {
52
52
  return mvhdBox.durationInSeconds;
53
53
  }
54
- const tracks = (0, get_tracks_1.getTracks)(structure, parserState);
54
+ const tracks = (0, get_tracks_1.getTracks)(parserState);
55
55
  const allTracks = [
56
56
  ...tracks.videoTracks,
57
57
  ...tracks.audioTracks,
@@ -1,4 +1,4 @@
1
1
  import type { Structure } from './parse-result';
2
2
  import type { ParserState } from './state/parser-state';
3
- export declare const getIsHdr: (boxes: Structure, state: ParserState) => boolean;
3
+ export declare const getIsHdr: (state: ParserState) => boolean;
4
4
  export declare const hasHdr: (boxes: Structure, state: ParserState) => boolean;
@@ -7,8 +7,8 @@ const isVideoTrackHdr = (track) => {
7
7
  track.color.transferCharacteristics === 'arib-std-b67' &&
8
8
  track.color.primaries === 'bt2020');
9
9
  };
10
- const getIsHdr = (boxes, state) => {
11
- const { videoTracks } = (0, get_tracks_1.getTracks)(boxes, state);
10
+ const getIsHdr = (state) => {
11
+ const { videoTracks } = (0, get_tracks_1.getTracks)(state);
12
12
  return videoTracks.some((track) => isVideoTrackHdr(track));
13
13
  };
14
14
  exports.getIsHdr = getIsHdr;
@@ -63,5 +63,5 @@ export declare const getTracksFromIsoBaseMedia: (segments: IsoBaseMediaBox[]) =>
63
63
  audioTracks: AudioTrack[];
64
64
  otherTracks: OtherTrack[];
65
65
  };
66
- export declare const getTracks: (segments: Structure, state: ParserState) => AllTracks;
66
+ export declare const getTracks: (state: ParserState) => AllTracks;
67
67
  export {};
@@ -38,10 +38,10 @@ const getHasTracks = (structure, state) => {
38
38
  return (0, exports.isoBaseMediaHasTracks)(structure);
39
39
  }
40
40
  if (structure.type === 'riff') {
41
- return (0, get_tracks_from_avi_1.hasAllTracksFromAvi)(structure, state);
41
+ return (0, get_tracks_from_avi_1.hasAllTracksFromAvi)(state);
42
42
  }
43
43
  if (structure.type === 'transport-stream') {
44
- return (0, get_tracks_1.hasAllTracksFromTransportStream)(structure, state);
44
+ return (0, get_tracks_1.hasAllTracksFromTransportStream)(state);
45
45
  }
46
46
  if (structure.type === 'mp3') {
47
47
  return state.callbacks.tracks.getTracks().length > 0;
@@ -110,22 +110,23 @@ const getTracksFromIsoBaseMedia = (segments) => {
110
110
  };
111
111
  };
112
112
  exports.getTracksFromIsoBaseMedia = getTracksFromIsoBaseMedia;
113
- const getTracks = (segments, state) => {
114
- if (segments.type === 'matroska') {
115
- return getTracksFromMa(segments.boxes, state);
113
+ const getTracks = (state) => {
114
+ const structure = state.structure.getStructure();
115
+ if (structure.type === 'matroska') {
116
+ return getTracksFromMa(structure.boxes, state);
116
117
  }
117
- if (segments.type === 'iso-base-media') {
118
- return (0, exports.getTracksFromIsoBaseMedia)(segments.boxes);
118
+ if (structure.type === 'iso-base-media') {
119
+ return (0, exports.getTracksFromIsoBaseMedia)(structure.boxes);
119
120
  }
120
- if (segments.type === 'riff') {
121
- return (0, get_tracks_from_avi_1.getTracksFromAvi)(segments, state);
121
+ if (structure.type === 'riff') {
122
+ return (0, get_tracks_from_avi_1.getTracksFromAvi)(structure, state);
122
123
  }
123
- if (segments.type === 'transport-stream') {
124
- return (0, get_tracks_1.getTracksFromTransportStream)(segments, state);
124
+ if (structure.type === 'transport-stream') {
125
+ return (0, get_tracks_1.getTracksFromTransportStream)(state);
125
126
  }
126
- if (segments.type === 'mp3') {
127
+ if (structure.type === 'mp3') {
127
128
  return (0, get_tracks_from_mp3_1.getTracksFromMp3)(state);
128
129
  }
129
- throw new Error(`Unknown container${segments}`);
130
+ throw new Error(`Unknown container${structure}`);
130
131
  };
131
132
  exports.getTracks = getTracks;
@@ -2,7 +2,7 @@ import type { TrakBox } from './boxes/iso-base-media/trak/trak';
2
2
  import { type MediaParserVideoCodec, type VideoTrackColorParams } from './get-tracks';
3
3
  import type { Structure } from './parse-result';
4
4
  import type { ParserState } from './state/parser-state';
5
- export declare const getVideoCodec: (boxes: Structure, state: ParserState) => MediaParserVideoCodec | null;
5
+ export declare const getVideoCodec: (state: ParserState) => MediaParserVideoCodec | null;
6
6
  export declare const hasVideoCodec: (boxes: Structure, state: ParserState) => boolean;
7
7
  export declare const getVideoPrivateData: (trakBox: TrakBox) => Uint8Array | null;
8
8
  export declare const getIsoBmColrConfig: (trakBox: TrakBox) => VideoTrackColorParams | null;
@@ -5,9 +5,9 @@ const color_1 = require("./boxes/avc/color");
5
5
  const av1_codec_private_1 = require("./boxes/webm/av1-codec-private");
6
6
  const get_sample_aspect_ratio_1 = require("./get-sample-aspect-ratio");
7
7
  const get_tracks_1 = require("./get-tracks");
8
- const getVideoCodec = (boxes, state) => {
8
+ const getVideoCodec = (state) => {
9
9
  var _a, _b;
10
- const track = (0, get_tracks_1.getTracks)(boxes, state);
10
+ const track = (0, get_tracks_1.getTracks)(state);
11
11
  return (_b = (_a = track.videoTracks[0]) === null || _a === void 0 ? void 0 : _a.codecWithoutConfig) !== null && _b !== void 0 ? _b : null;
12
12
  };
13
13
  exports.getVideoCodec = getVideoCodec;
package/dist/index.d.ts CHANGED
@@ -665,7 +665,6 @@ export declare const MediaParserInternals: {
665
665
  peekB: (length: number) => void;
666
666
  peekD: (length: number) => void;
667
667
  getBits: (bits: number) => number;
668
- byteLength: () => number;
669
668
  bytesRemaining: () => number;
670
669
  leb128: () => number;
671
670
  removeBytesRead: () => void;
@@ -705,8 +704,6 @@ export declare const MediaParserInternals: {
705
704
  getInt32Le: () => number;
706
705
  getInt32: () => number;
707
706
  destroy: () => void;
708
- disallowDiscard: () => void;
709
- allowDiscard: () => void;
710
707
  startBox: (size: number) => {
711
708
  discardRest: () => void;
712
709
  expectNoMoreBytes: () => void;
@@ -716,15 +713,13 @@ export declare const MediaParserInternals: {
716
713
  returnToCheckpoint: () => void;
717
714
  };
718
715
  };
719
- parseStsd: ({ iterator, offset, size, state, signal, fields, }: {
716
+ parseStsd: ({ iterator, offset, size, state, }: {
720
717
  iterator: import("./buffer-iterator").BufferIterator;
721
718
  offset: number;
722
719
  size: number;
723
720
  state: import("./state/parser-state").ParserState;
724
- signal: AbortSignal | null;
725
- fields: import("./options").Options<import("./options").ParseMediaFields>;
726
721
  }) => Promise<import("./boxes/iso-base-media/stsd/stsd").StsdBox>;
727
- makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHandlers, signal, getIterator, fields, onAudioTrack, onVideoTrack, supportsContentRange, contentLength, }: {
722
+ makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHandlers, signal, getIterator, fields, onAudioTrack, onVideoTrack, supportsContentRange, contentLength, logLevel, }: {
728
723
  hasAudioTrackHandlers: boolean;
729
724
  hasVideoTrackHandlers: boolean;
730
725
  signal: AbortSignal | undefined;
@@ -734,6 +729,7 @@ export declare const MediaParserInternals: {
734
729
  onAudioTrack: import("./webcodec-sample-types").OnAudioTrack | null;
735
730
  onVideoTrack: import("./webcodec-sample-types").OnVideoTrack | null;
736
731
  contentLength: number | null;
732
+ logLevel: LogLevel;
737
733
  }) => {
738
734
  riff: {
739
735
  getAvcProfile: () => import("./state/parser-state").SpsAndPps | null;
@@ -742,6 +738,38 @@ export declare const MediaParserInternals: {
742
738
  getNextTrackIndex: () => number;
743
739
  incrementNextTrackIndex: () => void;
744
740
  };
741
+ transportStream: {
742
+ nextPesHeaderStore: {
743
+ setNextPesHeader: (pesHeader: import("./boxes/transport-stream/parse-pes").PacketPes) => void;
744
+ getNextPesHeader: () => import("./boxes/transport-stream/parse-pes").PacketPes;
745
+ };
746
+ streamBuffers: Map<number, import("./boxes/transport-stream/process-stream-buffers").TransportStreamPacketBuffer>;
747
+ };
748
+ webm: {
749
+ onTrackEntrySegment: import("./boxes/webm/segments").OnTrackEntrySegment;
750
+ getTrackInfoByNumber: (id: number) => import("./boxes/webm/segments/track-entry").TrackInfo;
751
+ setTimestampOffset: (byteOffset: number, timestamp: number) => void;
752
+ getTimestampOffsetForByteOffset: (byteOffset: number) => number | undefined;
753
+ timescale: null;
754
+ getTimescale: () => number;
755
+ setTimescale: (newTimescale: number) => void;
756
+ addSegment: (seg: Omit<import("./state/webm").SegmentSection, "index">) => void;
757
+ addCluster: (cluster: import("./state/webm").ClusterSection) => void;
758
+ isInsideSegment: (iterator: import("./buffer-iterator").BufferIterator) => import("./state/webm").SegmentSection | null;
759
+ isInsideCluster: (iterator: import("./buffer-iterator").BufferIterator) => import("./state/webm").ClusterSection | null;
760
+ };
761
+ iso: {
762
+ getShouldReturnToVideoSectionAfterEnd: () => boolean;
763
+ setShouldReturnToVideoSectionAfterEnd: (value: boolean) => void;
764
+ flatSamples: {
765
+ getSamples: () => import("./state/iso-base-media/cached-sample-positions").FlatSample[] | null;
766
+ setSamples: (samples: import("./state/iso-base-media/cached-sample-positions").FlatSample[]) => void;
767
+ };
768
+ };
769
+ mp3Info: {
770
+ getMp3Info: () => import("./state/mp3").Mp3Info | null;
771
+ setMp3Info: (info: import("./state/mp3").Mp3Info) => void;
772
+ };
745
773
  callbacks: {
746
774
  registerVideoSampleCallback: (id: number, callback: import("./webcodec-sample-types").OnVideoSample | null) => Promise<void>;
747
775
  onAudioSample: (trackId: number, audioSample: import("./webcodec-sample-types").AudioOrVideoSample) => Promise<void>;
@@ -760,6 +788,8 @@ export declare const MediaParserInternals: {
760
788
  };
761
789
  audioSampleCallbacks: Record<number, import("./webcodec-sample-types").OnAudioSample>;
762
790
  videoSampleCallbacks: Record<number, import("./webcodec-sample-types").OnVideoSample>;
791
+ hasAudioTrackHandlers: boolean;
792
+ hasVideoTrackHandlers: boolean;
763
793
  };
764
794
  getInternalStats: () => import("./state/parser-state").InternalStats;
765
795
  getSkipBytes: () => number;
@@ -776,15 +806,6 @@ export declare const MediaParserInternals: {
776
806
  onAudioTrack: import("./webcodec-sample-types").OnAudioTrack | null;
777
807
  onVideoTrack: import("./webcodec-sample-types").OnVideoTrack | null;
778
808
  supportsContentRange: boolean;
779
- webm: {
780
- onTrackEntrySegment: import("./boxes/webm/segments").OnTrackEntrySegment;
781
- getTrackInfoByNumber: (id: number) => import("./boxes/webm/segments/track-entry").TrackInfo;
782
- setTimestampOffset: (byteOffset: number, timestamp: number) => void;
783
- getTimestampOffsetForByteOffset: (byteOffset: number) => number | undefined;
784
- timescale: null;
785
- getTimescale: () => number;
786
- setTimescale: (newTimescale: number) => void;
787
- };
788
809
  emittedFields: import("./options").AllOptions<import("./options").ParseMediaFields>;
789
810
  fields: Partial<import("./options").AllOptions<import("./options").ParseMediaFields>>;
790
811
  slowDurationAndFps: {
@@ -794,22 +815,27 @@ export declare const MediaParserInternals: {
794
815
  getFps: () => number;
795
816
  getSlowNumberOfFrames: () => number;
796
817
  };
797
- mp3Info: {
798
- getMp3Info: () => import("./state/mp3").Mp3Info | null;
799
- setMp3Info: (info: import("./state/mp3").Mp3Info) => void;
800
- };
801
818
  contentLength: number | null;
802
819
  images: {
803
820
  images: import("./state/images").MediaParserEmbeddedImage[];
804
821
  addImage: (image: import("./state/images").MediaParserEmbeddedImage) => void;
805
822
  };
823
+ videoSection: {
824
+ setVideoSection: (section: {
825
+ start: number;
826
+ size: number;
827
+ }) => void;
828
+ getVideoSection: () => {
829
+ start: number;
830
+ size: number;
831
+ };
832
+ isInVideoSectionState: (iterator: import("./buffer-iterator").BufferIterator) => "no-section-defined" | "in-section" | "outside-section";
833
+ };
834
+ logLevel: "trace" | "verbose" | "info" | "warn" | "error";
806
835
  };
807
- processSample: ({ iterator, state: options, signal, logLevel, fields, }: {
836
+ processSample: ({ iterator, state, }: {
808
837
  iterator: import("./buffer-iterator").BufferIterator;
809
838
  state: import("./state/parser-state").ParserState;
810
- signal: AbortSignal | null;
811
- logLevel: LogLevel;
812
- fields: import("./options").Options<import("./options").ParseMediaFields>;
813
839
  }) => Promise<{
814
840
  sample: import("./boxes/iso-base-media/stsd/samples").Sample | null;
815
841
  }>;
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ exports.MediaParserInternals = {
29
29
  getArrayBufferIterator: buffer_iterator_1.getArrayBufferIterator,
30
30
  parseStsd: stsd_1.parseStsd,
31
31
  makeParserState: parser_state_1.makeParserState,
32
- processSample: samples_1.processSample,
32
+ processSample: samples_1.processIsoFormatBox,
33
33
  parseFtyp: ftyp_1.parseFtyp,
34
34
  parseEbml: parse_ebml_1.parseEbml,
35
35
  parseMvhd: mvhd_1.parseMvhd,
@@ -3,9 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.maySkipVideoData = void 0;
4
4
  const need_samples_for_fields_1 = require("./need-samples-for-fields");
5
5
  const maySkipVideoData = ({ state }) => {
6
- return (state.callbacks.tracks.hasAllTracks() &&
6
+ const hasAllTracksAndNoCallbacks = state.callbacks.tracks.hasAllTracks() &&
7
7
  Object.values(state.callbacks.videoSampleCallbacks).length === 0 &&
8
- Object.values(state.callbacks.audioSampleCallbacks).length === 0 &&
8
+ Object.values(state.callbacks.audioSampleCallbacks).length === 0;
9
+ const hasNoTrackHandlers = !state.callbacks.hasAudioTrackHandlers &&
10
+ !state.callbacks.hasVideoTrackHandlers;
11
+ const noCallbacksNeeded = hasNoTrackHandlers || hasAllTracksAndNoCallbacks;
12
+ return (noCallbacksNeeded &&
9
13
  !(0, need_samples_for_fields_1.needsToIterateOverSamples)({
10
14
  emittedFields: state.emittedFields,
11
15
  fields: state.fields,
@@ -20,6 +20,9 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
20
20
  });
21
21
  const { reader, contentLength, name, contentType, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
22
22
  const iterator = (0, buffer_iterator_1.getArrayBufferIterator)(new Uint8Array([]), contentLength !== null && contentLength !== void 0 ? contentLength : 1000000000);
23
+ if (contentLength === null) {
24
+ throw new Error('Media was passed with no content length. This is currently not supported. Ensure the media has a "Content-Length" HTTP header.');
25
+ }
23
26
  const supportsContentRange = readerSupportsContentRange &&
24
27
  !(typeof process !== 'undefined' &&
25
28
  typeof process.env !== 'undefined' &&
@@ -34,6 +37,7 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
34
37
  onVideoTrack: onVideoTrack !== null && onVideoTrack !== void 0 ? onVideoTrack : null,
35
38
  supportsContentRange,
36
39
  contentLength,
40
+ logLevel,
37
41
  });
38
42
  let currentReader = reader;
39
43
  const returnValue = {};
@@ -72,12 +76,15 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
72
76
  }
73
77
  return true;
74
78
  }
79
+ if (iterator.counter.getOffset() === contentLength) {
80
+ log_1.Log.verbose(logLevel, 'Reached end of file');
81
+ return true;
82
+ }
75
83
  return false;
76
84
  };
77
85
  triggerInfoEmit();
78
- let didProgress = false;
79
- while (!checkIfDone() &&
80
- (parseResult === null || parseResult.status === 'incomplete')) {
86
+ let iterationWithThisOffset = 0;
87
+ while (!checkIfDone()) {
81
88
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
82
89
  throw new Error('Aborted');
83
90
  }
@@ -92,7 +99,7 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
92
99
  await fetchMoreData();
93
100
  }
94
101
  const hasBigBuffer = iterator.bytesRemaining() > 100000;
95
- if (!didProgress || !hasBigBuffer) {
102
+ if (iterationWithThisOffset > 0 || !hasBigBuffer) {
96
103
  await fetchMoreData();
97
104
  }
98
105
  (_a = throttledState.update) === null || _a === void 0 ? void 0 : _a.call(throttledState, () => ({
@@ -103,40 +110,48 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
103
110
  totalBytes: contentLength,
104
111
  }));
105
112
  triggerInfoEmit();
106
- if (parseResult && parseResult.status === 'incomplete') {
107
- log_1.Log.trace(logLevel, 'Continuing parsing of file, currently at position', iterator.counter.getOffset());
108
- parseResult = await parseResult.continueParsing();
109
- }
110
- else {
111
- parseResult = await (0, parse_video_1.parseVideo)({
112
- iterator,
113
- state,
114
- signal: signal !== null && signal !== void 0 ? signal : null,
115
- logLevel,
116
- fields,
117
- mimeType: contentType,
118
- contentLength,
119
- name,
120
- });
113
+ if (iterationWithThisOffset > 300) {
114
+ throw new Error('Infinite loop detected. The parser is not progressing. This is likely a bug in the parser.');
121
115
  }
122
- if (parseResult.status === 'incomplete' && parseResult.skipTo !== null) {
116
+ log_1.Log.trace(logLevel, `Continuing parsing of file, currently at position ${iterator.counter.getOffset()}/${contentLength}`);
117
+ parseResult = await (0, parse_video_1.parseVideo)({
118
+ iterator,
119
+ state,
120
+ mimeType: contentType,
121
+ contentLength,
122
+ name,
123
+ });
124
+ if (parseResult.skipTo !== null) {
123
125
  state.increaseSkippedBytes(parseResult.skipTo - iterator.counter.getOffset());
124
126
  }
125
- if (parseResult.status === 'incomplete' && parseResult.skipTo !== null) {
126
- if (!supportsContentRange) {
127
- throw new Error('Content-Range header is not supported by the reader, but was asked to seek');
128
- }
127
+ if (parseResult.skipTo !== null) {
129
128
  if (parseResult.skipTo === contentLength) {
130
129
  log_1.Log.verbose(logLevel, 'Skipped to end of file, not fetching.');
131
130
  break;
132
131
  }
133
- log_1.Log.verbose(logLevel, `Skipping over video data from position ${iterator.counter.getOffset()} -> ${parseResult.skipTo}`);
134
- currentReader.abort();
135
- const { reader: newReader } = await readerInterface.read(src, parseResult.skipTo, signal);
136
- currentReader = newReader;
137
- iterator.skipTo(parseResult.skipTo, true);
132
+ const skippingAhead = parseResult.skipTo > iterator.counter.getOffset();
133
+ if (!skippingAhead && !supportsContentRange) {
134
+ throw new Error('Content-Range header is not supported by the reader, but was asked to seek');
135
+ }
136
+ if (skippingAhead &&
137
+ iterator.counter.getOffset() + iterator.bytesRemaining() >=
138
+ parseResult.skipTo) {
139
+ log_1.Log.verbose(logLevel, `Skipping over video data from position ${iterator.counter.getOffset()} -> ${parseResult.skipTo}. Data already fetched`);
140
+ iterator.discard(parseResult.skipTo - iterator.counter.getOffset());
141
+ }
142
+ else {
143
+ log_1.Log.verbose(logLevel, `Skipping over video data from position ${iterator.counter.getOffset()} -> ${parseResult.skipTo}. Re-reading because this portion is not available`);
144
+ currentReader.abort();
145
+ const { reader: newReader } = await readerInterface.read(src, parseResult.skipTo, signal);
146
+ currentReader = newReader;
147
+ iterator.skipTo(parseResult.skipTo, true);
148
+ }
149
+ }
150
+ const didProgress = iterator.counter.getOffset() > offsetBefore;
151
+ if (!didProgress) {
152
+ iterationWithThisOffset++;
138
153
  }
139
- didProgress = iterator.counter.getOffset() > offsetBefore;
154
+ iterator.removeBytesRead();
140
155
  }
141
156
  log_1.Log.verbose(logLevel, 'Finished parsing file');
142
157
  // Force assign
@@ -1,7 +1,6 @@
1
1
  import type { BaseBox } from './boxes/iso-base-media/base-type';
2
2
  import type { EsdsBox } from './boxes/iso-base-media/esds/esds';
3
3
  import type { FtypBox } from './boxes/iso-base-media/ftyp';
4
- import type { MdatBox } from './boxes/iso-base-media/mdat/mdat';
5
4
  import type { MdhdBox } from './boxes/iso-base-media/mdhd';
6
5
  import type { HdlrBox } from './boxes/iso-base-media/meta/hdlr';
7
6
  import type { IlstBox } from './boxes/iso-base-media/meta/ilst';
@@ -38,7 +37,7 @@ export interface RegularBox extends BaseBox {
38
37
  offset: number;
39
38
  type: 'regular-box';
40
39
  }
41
- export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | IlstBox | EsdsBox | MdatBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | HdlrBox | ColorParameterBox | TfdtBox | TfhdBox;
40
+ 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;
42
41
  type Mp3Id3Header = {
43
42
  type: 'id3-header';
44
43
  versionMajor: number;
@@ -71,25 +70,9 @@ export type Mp3Structure = {
71
70
  };
72
71
  export type Structure = IsoBaseMediaStructure | RiffStructure | MatroskaStructure | TransportStreamStructure | Mp3Structure;
73
72
  export type ParseResult = {
74
- status: 'done';
75
- } | {
76
- status: 'incomplete';
77
73
  skipTo: number | null;
78
- continueParsing: () => Promise<ParseResult>;
79
74
  };
80
75
  export type MatroskaParseResult = {
81
- status: 'done';
82
- } | {
83
- status: 'incomplete';
84
76
  skipTo: number | null;
85
- continueParsing: () => Promise<MatroskaParseResult>;
86
- };
87
- export type ExpectSegmentParseResult = {
88
- status: 'done';
89
- segment: MatroskaSegment;
90
- } | {
91
- status: 'incomplete';
92
- segment: MatroskaSegment | null;
93
- continueParsing: () => Promise<ExpectSegmentParseResult>;
94
77
  };
95
78
  export {};
@@ -1,27 +1,13 @@
1
1
  import type { BufferIterator } from './buffer-iterator';
2
- import { type LogLevel } from './log';
3
- import type { Options, ParseMediaFields } from './options';
4
2
  import type { IsoBaseMediaBox, ParseResult } from './parse-result';
5
3
  import type { ParserState } from './state/parser-state';
6
- export type PartialMdatBox = {
7
- type: 'partial-mdat-box';
8
- boxSize: number;
9
- fileOffset: number;
10
- };
11
4
  export type BoxAndNext = {
12
- type: 'complete';
13
- box: IsoBaseMediaBox;
14
- size: number;
5
+ box: IsoBaseMediaBox | null;
15
6
  skipTo: number | null;
16
- } | {
17
- type: 'incomplete';
18
- } | PartialMdatBox;
19
- export declare const parseVideo: ({ iterator, state, signal, logLevel, fields, mimeType, contentLength, name, }: {
7
+ };
8
+ export declare const parseVideo: ({ iterator, state, mimeType, contentLength, name, }: {
20
9
  iterator: BufferIterator;
21
10
  state: ParserState;
22
- signal: AbortSignal | null;
23
- logLevel: LogLevel;
24
- fields: Options<ParseMediaFields>;
25
11
  mimeType: string | null;
26
12
  contentLength: number | null;
27
13
  name: string | null;
@@ -3,72 +3,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseVideo = void 0;
4
4
  const parse_boxes_1 = require("./boxes/iso-base-media/parse-boxes");
5
5
  const parse_mp3_1 = require("./boxes/mp3/parse-mp3");
6
- const parse_box_1 = require("./boxes/riff/parse-box");
7
- const next_pes_header_store_1 = require("./boxes/transport-stream/next-pes-header-store");
6
+ const parse_riff_1 = require("./boxes/riff/parse-riff");
8
7
  const parse_transport_stream_1 = require("./boxes/transport-stream/parse-transport-stream");
9
8
  const parse_webm_header_1 = require("./boxes/webm/parse-webm-header");
10
9
  const errors_1 = require("./errors");
11
10
  const log_1 = require("./log");
12
- const parseVideo = ({ iterator, state, signal, logLevel, fields, mimeType, contentLength, name, }) => {
13
- if (iterator.bytesRemaining() === 0) {
14
- return Promise.reject(new Error('no bytes'));
15
- }
11
+ const initVideo = ({ iterator, state, mimeType, name, contentLength, }) => {
16
12
  const fileType = iterator.detectFileType();
17
13
  if (fileType.type === 'riff') {
18
- log_1.Log.verbose(logLevel, 'Detected RIFF container');
14
+ log_1.Log.verbose(state.logLevel, 'Detected RIFF container');
19
15
  state.structure.setStructure({
20
16
  type: 'riff',
21
17
  boxes: [],
22
18
  });
23
- return Promise.resolve((0, parse_box_1.parseRiff)({ iterator, state, fields }));
19
+ return;
24
20
  }
25
21
  if (fileType.type === 'iso-base-media') {
26
- log_1.Log.verbose(logLevel, 'Detected ISO Base Media container');
27
- const initialBoxes = [];
22
+ log_1.Log.verbose(state.logLevel, 'Detected ISO Base Media container');
28
23
  state.structure.setStructure({
29
24
  type: 'iso-base-media',
30
- boxes: initialBoxes,
31
- });
32
- return (0, parse_boxes_1.parseIsoBaseMediaBoxes)({
33
- iterator,
34
- maxBytes: Infinity,
35
- allowIncompleteBoxes: true,
36
- initialBoxes,
37
- state,
38
- signal,
39
- logLevel,
40
- fields,
25
+ boxes: [],
41
26
  });
27
+ return;
42
28
  }
43
29
  if (fileType.type === 'webm') {
44
- log_1.Log.verbose(logLevel, 'Detected Matroska container');
30
+ log_1.Log.verbose(state.logLevel, 'Detected Matroska container');
45
31
  state.structure.setStructure({
46
32
  boxes: [],
47
33
  type: 'matroska',
48
34
  });
49
- return (0, parse_webm_header_1.parseWebm)({ counter: iterator, state, fields });
35
+ return;
50
36
  }
51
37
  if (fileType.type === 'transport-stream') {
52
- log_1.Log.verbose(logLevel, 'Detected MPEG-2 Transport Stream');
38
+ log_1.Log.verbose(state.logLevel, 'Detected MPEG-2 Transport Stream');
53
39
  state.structure.setStructure({
54
40
  boxes: [],
55
41
  type: 'transport-stream',
56
42
  });
57
- return (0, parse_transport_stream_1.parseTransportStream)({
58
- iterator,
59
- state,
60
- streamBuffers: new Map(),
61
- fields,
62
- nextPesHeaderStore: (0, next_pes_header_store_1.makeNextPesHeaderStore)(),
63
- });
43
+ return;
64
44
  }
65
45
  if (fileType.type === 'mp3') {
46
+ log_1.Log.verbose(state.logLevel, 'Detected MP3');
66
47
  const structure = {
67
48
  boxes: [],
68
49
  type: 'mp3',
69
50
  };
70
51
  state.structure.setStructure(structure);
71
- return (0, parse_mp3_1.parseMp3)({ iterator, structure, state });
52
+ return;
72
53
  }
73
54
  if (fileType.type === 'wav') {
74
55
  return Promise.reject(new errors_1.IsAnUnsupportedAudioTypeError({
@@ -127,4 +108,36 @@ const parseVideo = ({ iterator, state, signal, logLevel, fields, mimeType, conte
127
108
  }
128
109
  return Promise.reject(new Error('Unknown video format ' + fileType));
129
110
  };
111
+ const parseVideo = async ({ iterator, state, mimeType, contentLength, name, }) => {
112
+ if (iterator.bytesRemaining() === 0) {
113
+ return Promise.reject(new Error('no bytes'));
114
+ }
115
+ const structure = state.structure.getStructureOrNull();
116
+ if (structure === null) {
117
+ await initVideo({ iterator, state, mimeType, name, contentLength });
118
+ return { skipTo: null };
119
+ }
120
+ if (structure.type === 'riff') {
121
+ return (0, parse_riff_1.parseRiff)({ iterator, state });
122
+ }
123
+ if (structure.type === 'mp3') {
124
+ return (0, parse_mp3_1.parseMp3)({ iterator, state });
125
+ }
126
+ if (structure.type === 'iso-base-media') {
127
+ return (0, parse_boxes_1.parseIsoBaseMedia)({
128
+ iterator,
129
+ state,
130
+ });
131
+ }
132
+ if (structure.type === 'matroska') {
133
+ return (0, parse_webm_header_1.parseWebm)({ iterator, state });
134
+ }
135
+ if (structure.type === 'transport-stream') {
136
+ return (0, parse_transport_stream_1.parseTransportStream)({
137
+ iterator,
138
+ state,
139
+ });
140
+ }
141
+ return Promise.reject(new Error('Unknown video format ' + structure));
142
+ };
130
143
  exports.parseVideo = parseVideo;