@remotion/media-parser 4.0.241 → 4.0.242

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 (106) hide show
  1. package/dist/add-avc-profile-to-track.js +2 -2
  2. package/dist/boxes/avc/codec-private.js +2 -2
  3. package/dist/boxes/avc/create-sps-pps-data.d.ts +2 -0
  4. package/dist/boxes/avc/create-sps-pps-data.js +28 -0
  5. package/dist/boxes/iso-base-media/get-keyframes.d.ts +3 -0
  6. package/dist/boxes/iso-base-media/get-keyframes.js +30 -0
  7. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +3 -3
  8. package/dist/boxes/iso-base-media/mdat/mdat.js +9 -5
  9. package/dist/boxes/iso-base-media/moov/moov.d.ts +3 -3
  10. package/dist/boxes/iso-base-media/moov/moov.js +5 -4
  11. package/dist/boxes/iso-base-media/process-box.d.ts +9 -9
  12. package/dist/boxes/iso-base-media/process-box.js +48 -56
  13. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +3 -3
  14. package/dist/boxes/iso-base-media/stsd/mebx.js +5 -4
  15. package/dist/boxes/iso-base-media/stsd/samples.d.ts +5 -5
  16. package/dist/boxes/iso-base-media/stsd/samples.js +19 -16
  17. package/dist/boxes/iso-base-media/stsd/stsd.d.ts +3 -3
  18. package/dist/boxes/iso-base-media/stsd/stsd.js +2 -2
  19. package/dist/boxes/iso-base-media/trak/trak.d.ts +3 -3
  20. package/dist/boxes/iso-base-media/trak/trak.js +7 -6
  21. package/dist/boxes/riff/expect-riff-box.d.ts +3 -3
  22. package/dist/boxes/riff/expect-riff-box.js +5 -5
  23. package/dist/boxes/riff/get-tracks-from-avi.js +1 -1
  24. package/dist/boxes/riff/parse-box.d.ts +7 -7
  25. package/dist/boxes/riff/parse-box.js +29 -24
  26. package/dist/boxes/riff/parse-list-box.d.ts +3 -3
  27. package/dist/boxes/riff/parse-list-box.js +2 -2
  28. package/dist/boxes/riff/parse-movi.d.ts +5 -5
  29. package/dist/boxes/riff/parse-movi.js +35 -20
  30. package/dist/boxes/riff/parse-riff-box.d.ts +3 -3
  31. package/dist/boxes/riff/parse-riff-box.js +2 -2
  32. package/dist/boxes/transport-stream/get-tracks.js +1 -1
  33. package/dist/boxes/transport-stream/handle-aac-packet.d.ts +4 -3
  34. package/dist/boxes/transport-stream/handle-aac-packet.js +6 -4
  35. package/dist/boxes/transport-stream/handle-avc-packet.d.ts +4 -3
  36. package/dist/boxes/transport-stream/handle-avc-packet.js +8 -6
  37. package/dist/boxes/transport-stream/parse-packet.d.ts +3 -3
  38. package/dist/boxes/transport-stream/parse-packet.js +2 -2
  39. package/dist/boxes/transport-stream/parse-stream-packet.d.ts +3 -3
  40. package/dist/boxes/transport-stream/parse-stream-packet.js +14 -7
  41. package/dist/boxes/transport-stream/parse-transport-stream.d.ts +5 -6
  42. package/dist/boxes/transport-stream/parse-transport-stream.js +10 -9
  43. package/dist/boxes/transport-stream/process-stream-buffers.d.ts +6 -5
  44. package/dist/boxes/transport-stream/process-stream-buffers.js +18 -8
  45. package/dist/boxes/webm/ebml.d.ts +1 -1
  46. package/dist/boxes/webm/get-sample-from-block.d.ts +2 -2
  47. package/dist/boxes/webm/get-sample-from-block.js +8 -4
  48. package/dist/boxes/webm/parse-ebml.d.ts +4 -4
  49. package/dist/boxes/webm/parse-ebml.js +18 -18
  50. package/dist/boxes/webm/parse-webm-header.d.ts +5 -5
  51. package/dist/boxes/webm/parse-webm-header.js +6 -5
  52. package/dist/boxes/webm/segments/parse-children.d.ts +5 -5
  53. package/dist/boxes/webm/segments/parse-children.js +12 -13
  54. package/dist/boxes/webm/segments.d.ts +3 -3
  55. package/dist/boxes/webm/segments.js +13 -13
  56. package/dist/convert-audio-or-video-sample.js +2 -0
  57. package/dist/emit-available-info.d.ts +4 -5
  58. package/dist/emit-available-info.js +171 -57
  59. package/dist/esm/index.mjs +881 -490
  60. package/dist/get-duration.d.ts +1 -0
  61. package/dist/get-duration.js +14 -1
  62. package/dist/get-fields-from-callbacks.js +5 -0
  63. package/dist/get-fps.d.ts +1 -0
  64. package/dist/get-fps.js +17 -12
  65. package/dist/get-keyframes.d.ts +5 -0
  66. package/dist/get-keyframes.js +20 -0
  67. package/dist/get-tracks.d.ts +7 -1
  68. package/dist/get-tracks.js +15 -10
  69. package/dist/has-all-info.d.ts +2 -5
  70. package/dist/has-all-info.js +23 -4
  71. package/dist/index.d.ts +2 -1
  72. package/dist/may-skip-video-data/may-skip-video-data.d.ts +4 -0
  73. package/dist/may-skip-video-data/may-skip-video-data.js +14 -0
  74. package/dist/may-skip-video-data/need-samples-for-fields.d.ts +5 -0
  75. package/dist/may-skip-video-data/need-samples-for-fields.js +33 -0
  76. package/dist/options.d.ts +32 -0
  77. package/dist/parse-media.js +12 -40
  78. package/dist/parse-result.d.ts +2 -4
  79. package/dist/parse-video.d.ts +5 -5
  80. package/dist/parse-video.js +24 -10
  81. package/dist/register-track.d.ts +5 -5
  82. package/dist/register-track.js +12 -12
  83. package/dist/state/can-skip-tracks.js +5 -0
  84. package/dist/state/emitted-fields.d.ts +2 -0
  85. package/dist/state/emitted-fields.js +31 -0
  86. package/dist/state/has-tracks-section.d.ts +1 -0
  87. package/dist/state/keyframes.d.ts +6 -0
  88. package/dist/state/keyframes.js +15 -0
  89. package/dist/state/parser-state.d.ts +60 -29
  90. package/dist/state/parser-state.js +32 -150
  91. package/dist/state/riff.d.ts +10 -0
  92. package/dist/state/riff.js +32 -0
  93. package/dist/state/sample-callbacks.d.ts +31 -0
  94. package/dist/state/sample-callbacks.js +96 -0
  95. package/dist/state/slow-duration-fps.d.ts +8 -0
  96. package/dist/state/slow-duration-fps.js +36 -0
  97. package/dist/state/structure.d.ts +7 -0
  98. package/dist/state/structure.js +21 -0
  99. package/dist/state/tracks-and-samples.d.ts +0 -0
  100. package/dist/state/tracks-and-samples.js +1 -0
  101. package/dist/state/webm.d.ts +11 -0
  102. package/dist/state/webm.js +67 -0
  103. package/dist/version.d.ts +1 -1
  104. package/dist/version.js +1 -1
  105. package/dist/webcodec-sample-types.d.ts +2 -0
  106. package/package.json +3 -3
@@ -7,3 +7,4 @@ export declare const isMatroska: (boxes: AnySegment[]) => {
7
7
  } | undefined;
8
8
  export declare const getDuration: (structure: Structure, parserState: ParserState) => number | null;
9
9
  export declare const hasDuration: (structure: Structure, parserState: ParserState) => boolean;
10
+ export declare const hasSlowDuration: (structure: Structure, parserState: ParserState) => boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasDuration = exports.getDuration = exports.isMatroska = void 0;
3
+ exports.hasSlowDuration = exports.hasDuration = exports.getDuration = exports.isMatroska = void 0;
4
4
  const get_sample_positions_from_track_1 = require("./boxes/iso-base-media/get-sample-positions-from-track");
5
5
  const traversal_1 = require("./boxes/iso-base-media/traversal");
6
6
  const traversal_2 = require("./boxes/riff/traversal");
@@ -95,7 +95,20 @@ const getDuration = (structure, parserState) => {
95
95
  throw new Error('Has no duration ' + structure);
96
96
  };
97
97
  exports.getDuration = getDuration;
98
+ // `duration` just grabs from metadata, and otherwise returns null
99
+ // Therefore just checking if we have tracks
98
100
  const hasDuration = (structure, parserState) => {
99
101
  return (0, get_tracks_1.hasTracks)(structure, parserState);
100
102
  };
101
103
  exports.hasDuration = hasDuration;
104
+ // `slowDuration` does through everything, and therefore is false
105
+ // Unless it it somewhere in the metadata and is non-null
106
+ const hasSlowDuration = (structure, parserState) => {
107
+ try {
108
+ return (0, exports.getDuration)(structure, parserState) !== null;
109
+ }
110
+ catch (_a) {
111
+ return false;
112
+ }
113
+ };
114
+ exports.hasSlowDuration = hasSlowDuration;
@@ -20,6 +20,11 @@ const getFieldsFromCallback = ({ fields, callbacks, }) => {
20
20
  tracks: Boolean(callbacks.onTracks),
21
21
  unrotatedDimensions: Boolean(callbacks.onUnrotatedDimensions),
22
22
  videoCodec: Boolean(callbacks.onVideoCodec),
23
+ slowKeyframes: Boolean(callbacks.onSlowKeyframes),
24
+ slowDurationInSeconds: Boolean(callbacks.onSlowDurationInSeconds),
25
+ slowFps: Boolean(callbacks.onSlowFps),
26
+ slowNumberOfFrames: Boolean(callbacks.onSlowNumberOfFrames),
27
+ keyframes: Boolean(callbacks.onKeyframes),
23
28
  ...fields,
24
29
  };
25
30
  return newFields;
package/dist/get-fps.d.ts CHANGED
@@ -9,5 +9,6 @@ export declare const trakBoxContainsVideo: (trakBox: TrakBox) => boolean;
9
9
  export declare const getTimescaleAndDuration: (trakBox: TrakBox) => TimescaleAndDuration | null;
10
10
  export declare const getFpsFromMp4TrakBox: (trakBox: TrakBox) => number | null;
11
11
  export declare const getFps: (segments: Structure) => number | null;
12
+ export declare const hasFpsSuitedForSlowFps: (boxes: Structure) => boolean;
12
13
  export declare const hasFps: (boxes: Structure) => boolean;
13
14
  export {};
package/dist/get-fps.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasFps = exports.getFps = exports.getFpsFromMp4TrakBox = exports.getTimescaleAndDuration = exports.trakBoxContainsVideo = exports.trakBoxContainsAudio = void 0;
3
+ exports.hasFps = exports.hasFpsSuitedForSlowFps = exports.getFps = exports.getFpsFromMp4TrakBox = exports.getTimescaleAndDuration = exports.trakBoxContainsVideo = exports.trakBoxContainsAudio = void 0;
4
4
  const traversal_1 = require("./boxes/iso-base-media/traversal");
5
5
  const traversal_2 = require("./boxes/riff/traversal");
6
6
  const calculateFps = ({ sttsBox, timeScale, durationInSamples, }) => {
@@ -93,31 +93,36 @@ const getFps = (segments) => {
93
93
  if (segments.type === 'riff') {
94
94
  return getFpsFromAvi(segments);
95
95
  }
96
- // TODO: Matroska doesn't have fps
96
+ // People need to get it from slowFps
97
97
  if (segments.type === 'matroska') {
98
98
  return null;
99
99
  }
100
+ // People need to get it from slowFps
100
101
  if (segments.type === 'transport-stream') {
101
102
  return null;
102
103
  }
103
104
  throw new Error('Cannot get fps, not implemented');
104
105
  };
105
106
  exports.getFps = getFps;
106
- const hasFps = (boxes) => {
107
+ const hasFpsSuitedForSlowFps = (boxes) => {
107
108
  try {
108
- // Matroska and Transport stream has no FPS metadata
109
- // Not bothering to parse
110
- // Idea: `guaranteedFps` field
111
- if (boxes.type === 'matroska') {
112
- return true;
113
- }
114
- if (boxes.type === 'transport-stream') {
115
- return true;
116
- }
117
109
  return (0, exports.getFps)(boxes) !== null;
118
110
  }
119
111
  catch (_a) {
120
112
  return false;
121
113
  }
122
114
  };
115
+ exports.hasFpsSuitedForSlowFps = hasFpsSuitedForSlowFps;
116
+ const hasFps = (boxes) => {
117
+ // Matroska and Transport stream has no FPS metadata
118
+ // Not bothering to parse
119
+ // Users should use `slowFps` field
120
+ if (boxes.type === 'matroska') {
121
+ return true;
122
+ }
123
+ if (boxes.type === 'transport-stream') {
124
+ return true;
125
+ }
126
+ return (0, exports.hasFpsSuitedForSlowFps)(boxes);
127
+ };
123
128
  exports.hasFps = hasFps;
@@ -0,0 +1,5 @@
1
+ import type { MediaParserKeyframe } from './options';
2
+ import type { Structure } from './parse-result';
3
+ import type { ParserState } from './state/parser-state';
4
+ export declare const getKeyframes: (structure: Structure) => MediaParserKeyframe[] | null;
5
+ export declare const hasKeyframes: (structure: Structure, parserState: ParserState) => boolean;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasKeyframes = exports.getKeyframes = void 0;
4
+ const get_keyframes_1 = require("./boxes/iso-base-media/get-keyframes");
5
+ const get_tracks_1 = require("./get-tracks");
6
+ const getKeyframes = (structure) => {
7
+ if (structure.type === 'iso-base-media') {
8
+ return (0, get_keyframes_1.getKeyframesFromIsoBaseMedia)(structure);
9
+ }
10
+ return null;
11
+ };
12
+ exports.getKeyframes = getKeyframes;
13
+ const hasKeyframes = (structure, parserState) => {
14
+ if (structure.type === 'iso-base-media') {
15
+ return (0, get_tracks_1.hasTracks)(structure, parserState);
16
+ }
17
+ // Has, but will be null
18
+ return true;
19
+ };
20
+ exports.hasKeyframes = hasKeyframes;
@@ -2,7 +2,7 @@ import type { MatrixCoefficients, Primaries, TransferCharacteristics } from './b
2
2
  import type { MoovBox } from './boxes/iso-base-media/moov/moov';
3
3
  import type { TrakBox } from './boxes/iso-base-media/trak/trak';
4
4
  import type { AllTracks } from './boxes/riff/get-tracks-from-avi';
5
- import type { Structure } from './parse-result';
5
+ import type { IsoBaseMediaBox, IsoBaseMediaStructure, Structure } from './parse-result';
6
6
  import type { ParserState } from './state/parser-state';
7
7
  type SampleAspectRatio = {
8
8
  numerator: number;
@@ -56,6 +56,12 @@ export type OtherTrack = {
56
56
  };
57
57
  export type Track = VideoTrack | AudioTrack | OtherTrack;
58
58
  export declare const getNumberOfTracks: (moovBox: MoovBox) => number;
59
+ export declare const isoBaseMediaHasTracks: (structure: IsoBaseMediaStructure) => boolean;
59
60
  export declare const hasTracks: (structure: Structure, state: ParserState) => boolean;
61
+ export declare const getTracksFromIsoBaseMedia: (segments: IsoBaseMediaBox[]) => {
62
+ videoTracks: VideoTrack[];
63
+ audioTracks: AudioTrack[];
64
+ otherTracks: OtherTrack[];
65
+ };
60
66
  export declare const getTracks: (segments: Structure, state: ParserState) => AllTracks;
61
67
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTracks = exports.hasTracks = exports.getNumberOfTracks = void 0;
3
+ exports.getTracks = exports.getTracksFromIsoBaseMedia = exports.hasTracks = exports.isoBaseMediaHasTracks = exports.getNumberOfTracks = void 0;
4
4
  const make_track_1 = require("./boxes/iso-base-media/make-track");
5
5
  const traversal_1 = require("./boxes/iso-base-media/traversal");
6
6
  const get_tracks_from_avi_1 = require("./boxes/riff/get-tracks-from-avi");
@@ -15,6 +15,16 @@ const getNumberOfTracks = (moovBox) => {
15
15
  return mvHdBox.nextTrackId - 1;
16
16
  };
17
17
  exports.getNumberOfTracks = getNumberOfTracks;
18
+ const isoBaseMediaHasTracks = (structure) => {
19
+ const moovBox = (0, traversal_1.getMoovBox)(structure.boxes);
20
+ if (!moovBox) {
21
+ return false;
22
+ }
23
+ const numberOfTracks = (0, exports.getNumberOfTracks)(moovBox);
24
+ const tracks = (0, traversal_1.getTraks)(moovBox);
25
+ return tracks.length === numberOfTracks;
26
+ };
27
+ exports.isoBaseMediaHasTracks = isoBaseMediaHasTracks;
18
28
  const hasTracks = (structure, state) => {
19
29
  if (structure.type === 'matroska') {
20
30
  const mainSegment = (0, traversal_2.getMainSegment)(structure.boxes);
@@ -24,13 +34,7 @@ const hasTracks = (structure, state) => {
24
34
  return (0, traversal_2.getTracksSegment)(mainSegment) !== null;
25
35
  }
26
36
  if (structure.type === 'iso-base-media') {
27
- const moovBox = (0, traversal_1.getMoovBox)(structure.boxes);
28
- if (!moovBox) {
29
- return false;
30
- }
31
- const numberOfTracks = (0, exports.getNumberOfTracks)(moovBox);
32
- const tracks = (0, traversal_1.getTraks)(moovBox);
33
- return tracks.length === numberOfTracks;
37
+ return (0, exports.isoBaseMediaHasTracks)(structure);
34
38
  }
35
39
  if (structure.type === 'riff') {
36
40
  return (0, get_tracks_from_avi_1.hasAllTracksFromAvi)(structure, state);
@@ -49,7 +53,7 @@ const getTracksFromMa = (segments, state) => {
49
53
  if (!mainSegment) {
50
54
  throw new Error('No main segment found');
51
55
  }
52
- const matroskaTracks = (0, get_ready_tracks_1.getTracksFromMatroska)(mainSegment, state.getTimescale());
56
+ const matroskaTracks = (0, get_ready_tracks_1.getTracksFromMatroska)(mainSegment, state.webm.getTimescale());
53
57
  for (const track of matroskaTracks) {
54
58
  if (track.type === 'video') {
55
59
  videoTracks.push(track);
@@ -101,12 +105,13 @@ const getTracksFromIsoBaseMedia = (segments) => {
101
105
  otherTracks,
102
106
  };
103
107
  };
108
+ exports.getTracksFromIsoBaseMedia = getTracksFromIsoBaseMedia;
104
109
  const getTracks = (segments, state) => {
105
110
  if (segments.type === 'matroska') {
106
111
  return getTracksFromMa(segments.boxes, state);
107
112
  }
108
113
  if (segments.type === 'iso-base-media') {
109
- return getTracksFromIsoBaseMedia(segments.boxes);
114
+ return (0, exports.getTracksFromIsoBaseMedia)(segments.boxes);
110
115
  }
111
116
  if (segments.type === 'riff') {
112
117
  return (0, get_tracks_from_avi_1.getTracksFromAvi)(segments, state);
@@ -1,13 +1,10 @@
1
1
  import type { Options, ParseMediaFields } from './options';
2
- import type { Structure } from './parse-result';
3
2
  import type { ParserState } from './state/parser-state';
4
- export declare const getAvailableInfo: ({ fieldsToFetch, structure, state, }: {
3
+ export declare const getAvailableInfo: ({ fieldsToFetch, state, }: {
5
4
  fieldsToFetch: Options<ParseMediaFields>;
6
- structure: Structure | null;
7
5
  state: ParserState;
8
6
  }) => Record<keyof Options<ParseMediaFields>, boolean>;
9
- export declare const hasAllInfo: ({ fields, state, structure, }: {
10
- structure: Structure | null;
7
+ export declare const hasAllInfo: ({ fields, state, }: {
11
8
  fields: Options<ParseMediaFields>;
12
9
  state: ParserState;
13
10
  }) => boolean;
@@ -7,10 +7,13 @@ const get_dimensions_1 = require("./get-dimensions");
7
7
  const get_duration_1 = require("./get-duration");
8
8
  const get_fps_1 = require("./get-fps");
9
9
  const get_is_hdr_1 = require("./get-is-hdr");
10
+ const get_keyframes_1 = require("./get-keyframes");
10
11
  const get_tracks_1 = require("./get-tracks");
11
12
  const get_video_codec_1 = require("./get-video-codec");
12
- const getAvailableInfo = ({ fieldsToFetch, structure, state, }) => {
13
+ const may_skip_video_data_1 = require("./may-skip-video-data/may-skip-video-data");
14
+ const getAvailableInfo = ({ fieldsToFetch, state, }) => {
13
15
  const keys = Object.entries(fieldsToFetch).filter(([, value]) => value);
16
+ const structure = state.structure.getStructureOrNull();
14
17
  const infos = keys.map(([_key]) => {
15
18
  const key = _key;
16
19
  if (key === 'structure') {
@@ -19,6 +22,9 @@ const getAvailableInfo = ({ fieldsToFetch, structure, state, }) => {
19
22
  if (key === 'durationInSeconds') {
20
23
  return Boolean(structure && (0, get_duration_1.hasDuration)(structure, state));
21
24
  }
25
+ if (key === 'slowDurationInSeconds') {
26
+ return Boolean(structure && (0, get_duration_1.hasSlowDuration)(structure, state));
27
+ }
22
28
  if (key === 'dimensions' ||
23
29
  key === 'rotation' ||
24
30
  key === 'unrotatedDimensions') {
@@ -27,6 +33,10 @@ const getAvailableInfo = ({ fieldsToFetch, structure, state, }) => {
27
33
  if (key === 'fps') {
28
34
  return Boolean(structure && (0, get_fps_1.hasFps)(structure));
29
35
  }
36
+ if (key === 'slowFps') {
37
+ // In case FPS is available an non-null, it also works for `slowFps`
38
+ return Boolean(structure && (0, get_fps_1.hasFpsSuitedForSlowFps)(structure));
39
+ }
30
40
  if (key === 'isHdr') {
31
41
  return Boolean(structure && (0, get_is_hdr_1.hasHdr)(structure, state));
32
42
  }
@@ -39,6 +49,9 @@ const getAvailableInfo = ({ fieldsToFetch, structure, state, }) => {
39
49
  if (key === 'tracks') {
40
50
  return Boolean(structure && (0, get_tracks_1.hasTracks)(structure, state));
41
51
  }
52
+ if (key === 'keyframes') {
53
+ return Boolean(structure && (0, get_keyframes_1.hasKeyframes)(structure, state));
54
+ }
42
55
  if (key === 'internalStats') {
43
56
  return true;
44
57
  }
@@ -57,6 +70,12 @@ const getAvailableInfo = ({ fieldsToFetch, structure, state, }) => {
57
70
  if (key === 'metadata' || key === 'location') {
58
71
  return false;
59
72
  }
73
+ if (key === 'slowKeyframes') {
74
+ return false;
75
+ }
76
+ if (key === 'slowNumberOfFrames') {
77
+ return false;
78
+ }
60
79
  throw new Error(`Unknown key: ${key}`);
61
80
  });
62
81
  const entries = [];
@@ -67,13 +86,13 @@ const getAvailableInfo = ({ fieldsToFetch, structure, state, }) => {
67
86
  return Object.fromEntries(entries);
68
87
  };
69
88
  exports.getAvailableInfo = getAvailableInfo;
70
- const hasAllInfo = ({ fields, state, structure, }) => {
89
+ const hasAllInfo = ({ fields, state, }) => {
71
90
  const availableInfo = (0, exports.getAvailableInfo)({
72
91
  fieldsToFetch: fields !== null && fields !== void 0 ? fields : {},
73
- structure,
74
92
  state,
75
93
  });
76
94
  return (Object.values(availableInfo).every(Boolean) &&
77
- (state.maySkipVideoData() || state.canSkipTracksState.canSkipTracks()));
95
+ ((0, may_skip_video_data_1.maySkipVideoData)({ state }) ||
96
+ state.callbacks.canSkipTracksState.canSkipTracks()));
78
97
  };
79
98
  exports.hasAllInfo = hasAllInfo;
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { ProgressTracker } from './create/progress-tracker';
3
3
  import type { LogLevel } from './log';
4
4
  export { IsAGifError, IsAnImageError, IsAnUnsupportedAudioTypeError, IsAnUnsupportedFileTypeError, IsAPdfError, } from './errors';
5
5
  export { MetadataEntry } from './metadata/get-metadata';
6
+ export { MediaParserKeyframe } from './options';
6
7
  export { WriterInterface } from './writers/writer';
7
8
  export { AudioTrack, MediaParserAudioCodec, MediaParserVideoCodec, OtherTrack, Track, VideoTrack, VideoTrackColorParams, } from './get-tracks';
8
9
  export type { Options, ParseMediaContainer, ParseMediaDynamicOptions, ParseMediaFields, ParseMediaOnProgress, ParseMediaOptions, ParseMediaProgress, ParseMediaResult, TracksField, } from './options';
@@ -46,7 +47,7 @@ export declare const MediaParserInternals: {
46
47
  audioObjectType: number;
47
48
  sampleRate: number;
48
49
  channelConfiguration: number;
49
- }) => Uint8Array<ArrayBuffer>;
50
+ }) => Uint8Array;
50
51
  };
51
52
  export type { IoEventEmitter, LogLevel, ProgressTracker };
52
53
  export { VERSION } from './version';
@@ -0,0 +1,4 @@
1
+ import type { ParserState } from '../state/parser-state';
2
+ export declare const maySkipVideoData: ({ state }: {
3
+ state: ParserState;
4
+ }) => boolean;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.maySkipVideoData = void 0;
4
+ const need_samples_for_fields_1 = require("./need-samples-for-fields");
5
+ const maySkipVideoData = ({ state }) => {
6
+ return (state.callbacks.tracks.hasAllTracks() &&
7
+ Object.values(state.callbacks.videoSampleCallbacks).length === 0 &&
8
+ Object.values(state.callbacks.audioSampleCallbacks).length === 0 &&
9
+ !(0, need_samples_for_fields_1.needsToIterateOverSamples)({
10
+ emittedFields: state.emittedFields,
11
+ fields: state.fields,
12
+ }));
13
+ };
14
+ exports.maySkipVideoData = maySkipVideoData;
@@ -0,0 +1,5 @@
1
+ import type { AllOptions, Options, ParseMediaFields } from '../options';
2
+ export declare const needsToIterateOverSamples: ({ fields, emittedFields, }: {
3
+ fields: Options<ParseMediaFields>;
4
+ emittedFields: AllOptions<ParseMediaFields>;
5
+ }) => boolean;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.needsToIterateOverSamples = void 0;
4
+ const needsSamples = {
5
+ slowDurationInSeconds: true,
6
+ slowFps: true,
7
+ slowKeyframes: true,
8
+ slowNumberOfFrames: true,
9
+ audioCodec: false,
10
+ container: false,
11
+ dimensions: false,
12
+ durationInSeconds: false,
13
+ fps: false,
14
+ internalStats: false,
15
+ isHdr: false,
16
+ name: false,
17
+ rotation: false,
18
+ size: false,
19
+ structure: false,
20
+ tracks: false,
21
+ unrotatedDimensions: false,
22
+ videoCodec: false,
23
+ metadata: false,
24
+ location: false,
25
+ mimeType: false,
26
+ keyframes: false,
27
+ };
28
+ const needsToIterateOverSamples = ({ fields, emittedFields, }) => {
29
+ const keys = Object.keys(fields !== null && fields !== void 0 ? fields : {});
30
+ const selectedKeys = keys.filter((k) => fields[k]);
31
+ return selectedKeys.some((k) => needsSamples[k] && !emittedFields[k]);
32
+ };
33
+ exports.needsToIterateOverSamples = needsToIterateOverSamples;
package/dist/options.d.ts CHANGED
@@ -11,8 +11,10 @@ export type KnownAudioCodecs = 'aac' | 'mp3' | 'aiff' | 'opus' | 'pcm' | 'vorbis
11
11
  export type ParseMediaFields = {
12
12
  dimensions: boolean;
13
13
  durationInSeconds: boolean;
14
+ slowDurationInSeconds: boolean;
14
15
  structure: boolean;
15
16
  fps: boolean;
17
+ slowFps: boolean;
16
18
  videoCodec: boolean;
17
19
  audioCodec: boolean;
18
20
  tracks: boolean;
@@ -26,10 +28,16 @@ export type ParseMediaFields = {
26
28
  metadata: boolean;
27
29
  location: boolean;
28
30
  mimeType: boolean;
31
+ keyframes: boolean;
32
+ slowKeyframes: boolean;
33
+ slowNumberOfFrames: boolean;
29
34
  };
30
35
  export type AllParseMediaFields = {
31
36
  dimensions: true;
32
37
  durationInSeconds: true;
38
+ slowDurationInSeconds: true;
39
+ slowNumberOfFrames: true;
40
+ slowFps: true;
33
41
  structure: true;
34
42
  fps: true;
35
43
  videoCodec: true;
@@ -45,10 +53,14 @@ export type AllParseMediaFields = {
45
53
  metadata: true;
46
54
  location: true;
47
55
  mimeType: true;
56
+ keyframes: true;
57
+ slowKeyframes: true;
48
58
  };
49
59
  export type AllOptions<Fields extends ParseMediaFields> = {
50
60
  dimensions: Fields['dimensions'];
51
61
  durationInSeconds: Fields['durationInSeconds'];
62
+ slowDurationInSeconds: Fields['slowDurationInSeconds'];
63
+ slowFps: Fields['slowFps'];
52
64
  structure: Fields['structure'];
53
65
  fps: Fields['fps'];
54
66
  videoCodec: Fields['videoCodec'];
@@ -64,6 +76,9 @@ export type AllOptions<Fields extends ParseMediaFields> = {
64
76
  metadata: Fields['metadata'];
65
77
  location: Fields['location'];
66
78
  mimeType: Fields['mimeType'];
79
+ keyframes: Fields['keyframes'];
80
+ slowKeyframes: Fields['slowKeyframes'];
81
+ slowNumberOfFrames: Fields['slowNumberOfFrames'];
67
82
  };
68
83
  export type Options<Fields extends ParseMediaFields> = Partial<AllOptions<Fields>>;
69
84
  export type TracksField = {
@@ -71,9 +86,18 @@ export type TracksField = {
71
86
  audioTracks: AudioTrack[];
72
87
  };
73
88
  export type ParseMediaContainer = 'mp4' | 'webm' | 'avi' | 'transport-stream';
89
+ export type MediaParserKeyframe = {
90
+ positionInBytes: number;
91
+ sizeInBytes: number;
92
+ presentationTimeInSeconds: number;
93
+ decodingTimeInSeconds: number;
94
+ trackId: number;
95
+ };
74
96
  export interface ParseMediaCallbacks {
75
97
  onDimensions?: (dimensions: Dimensions) => void;
76
98
  onDurationInSeconds?: (durationInSeconds: number | null) => void;
99
+ onSlowDurationInSeconds?: (durationInSeconds: number) => void;
100
+ onSlowFps?: (fps: number) => void;
77
101
  onStructure?: (structure: Structure) => void;
78
102
  onFps?: (fps: number | null) => void;
79
103
  onVideoCodec?: (codec: MediaParserVideoCodec | null) => void;
@@ -89,10 +113,15 @@ export interface ParseMediaCallbacks {
89
113
  onMetadata?: (metadata: MetadataEntry[]) => void;
90
114
  onLocation?: (location: MediaParserLocation | null) => void;
91
115
  onMimeType?: (mimeType: string | null) => void;
116
+ onKeyframes?: (keyframes: MediaParserKeyframe[] | null) => void;
117
+ onSlowKeyframes?: (keyframes: MediaParserKeyframe[]) => void;
118
+ onSlowNumberOfFrames?: (samples: number) => void;
92
119
  }
93
120
  export interface ParseMediaData {
94
121
  dimensions: Dimensions;
95
122
  durationInSeconds: number | null;
123
+ slowDurationInSeconds: number;
124
+ slowFps: number;
96
125
  structure: Structure;
97
126
  fps: number | null;
98
127
  videoCodec: MediaParserVideoCodec | null;
@@ -108,6 +137,9 @@ export interface ParseMediaData {
108
137
  location: MediaParserLocation | null;
109
138
  container: ParseMediaContainer;
110
139
  mimeType: string | null;
140
+ keyframes: MediaParserKeyframe[] | null;
141
+ slowKeyframes: MediaParserKeyframe[];
142
+ slowNumberOfFrames: number;
111
143
  }
112
144
  export type ParseMediaResult<T extends Partial<ParseMediaFields>> = {
113
145
  [K in keyof T]: T[K] extends true ? K extends keyof ParseMediaData ? ParseMediaData[K] : never : never;
@@ -17,55 +17,30 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
17
17
  fields: fieldsInReturnValue,
18
18
  callbacks: more,
19
19
  });
20
+ const { reader, contentLength, name, contentType, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
21
+ const supportsContentRange = readerSupportsContentRange &&
22
+ !(typeof process !== 'undefined' &&
23
+ typeof process.env !== 'undefined' &&
24
+ process.env.DISABLE_CONTENT_RANGE === 'true');
20
25
  const state = (0, parser_state_1.makeParserState)({
21
26
  hasAudioTrackHandlers: Boolean(onAudioTrack),
22
27
  hasVideoTrackHandlers: Boolean(onVideoTrack),
23
28
  signal,
24
29
  getIterator: () => iterator,
25
30
  fields,
26
- });
27
- const { reader, contentLength, name, contentType, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
28
- let currentReader = reader;
29
- const emittedFields = {
30
- audioCodec: false,
31
- container: false,
32
- dimensions: false,
33
- durationInSeconds: false,
34
- fps: false,
35
- internalStats: false,
36
- isHdr: false,
37
- location: false,
38
- metadata: false,
39
- mimeType: false,
40
- name: false,
41
- rotation: false,
42
- size: false,
43
- structure: false,
44
- tracks: false,
45
- videoCodec: false,
46
- unrotatedDimensions: false,
47
- };
48
- const supportsContentRange = readerSupportsContentRange &&
49
- !(typeof process !== 'undefined' &&
50
- typeof process.env !== 'undefined' &&
51
- process.env.DISABLE_CONTENT_RANGE === 'true');
52
- const returnValue = {};
53
- const moreFields = more;
54
- const options = {
55
31
  onAudioTrack: onAudioTrack !== null && onAudioTrack !== void 0 ? onAudioTrack : null,
56
32
  onVideoTrack: onVideoTrack !== null && onVideoTrack !== void 0 ? onVideoTrack : null,
57
- parserState: state,
58
33
  nullifySamples: !(typeof process !== 'undefined' &&
59
34
  typeof process.env !== 'undefined' &&
60
35
  process.env.KEEP_SAMPLES === 'true'),
61
36
  supportsContentRange,
62
- nextTrackIndex: 0,
63
- };
37
+ });
38
+ let currentReader = reader;
39
+ const returnValue = {};
40
+ const moreFields = more;
64
41
  const triggerInfoEmit = () => {
65
- var _a;
66
42
  const availableInfo = (0, has_all_info_1.getAvailableInfo)({
67
43
  fieldsToFetch: fields,
68
- structure: (_a = parseResult === null || parseResult === void 0 ? void 0 : parseResult.segments) !== null && _a !== void 0 ? _a : null,
69
44
  state,
70
45
  });
71
46
  (0, emit_available_info_1.emitAvailableInfo)({
@@ -78,7 +53,6 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
78
53
  contentLength,
79
54
  name,
80
55
  mimeType: contentType,
81
- emittedFields,
82
56
  });
83
57
  };
84
58
  triggerInfoEmit();
@@ -118,13 +92,13 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
118
92
  }));
119
93
  triggerInfoEmit();
120
94
  if (parseResult && parseResult.status === 'incomplete') {
121
- log_1.Log.verbose(logLevel, 'Continuing parsing of file, currently at position', iterator.counter.getOffset());
95
+ log_1.Log.trace(logLevel, 'Continuing parsing of file, currently at position', iterator.counter.getOffset());
122
96
  parseResult = await parseResult.continueParsing();
123
97
  }
124
98
  else {
125
99
  parseResult = await (0, parse_video_1.parseVideo)({
126
100
  iterator,
127
- options,
101
+ state,
128
102
  signal: signal !== null && signal !== void 0 ? signal : null,
129
103
  logLevel,
130
104
  fields,
@@ -138,7 +112,6 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
138
112
  }
139
113
  if ((0, has_all_info_1.hasAllInfo)({
140
114
  fields,
141
- structure: parseResult.segments,
142
115
  state,
143
116
  })) {
144
117
  log_1.Log.verbose(logLevel, 'Got all info, skipping to the end.');
@@ -180,11 +153,10 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
180
153
  contentLength,
181
154
  mimeType: contentType,
182
155
  name,
183
- emittedFields,
184
156
  });
185
157
  currentReader.abort();
186
158
  iterator === null || iterator === void 0 ? void 0 : iterator.destroy();
187
- state.tracks.ensureHasTracksAtEnd();
159
+ state.callbacks.tracks.ensureHasTracksAtEnd();
188
160
  return returnValue;
189
161
  };
190
162
  exports.parseMedia = parseMedia;
@@ -56,14 +56,12 @@ export type TransportStreamStructure = {
56
56
  boxes: TransportStreamBox[];
57
57
  };
58
58
  export type Structure = IsoBaseMediaStructure | RiffStructure | MatroskaStructure | TransportStreamStructure;
59
- export type ParseResult<TStructure extends Structure> = {
59
+ export type ParseResult = {
60
60
  status: 'done';
61
- segments: TStructure;
62
61
  } | {
63
62
  status: 'incomplete';
64
- segments: TStructure;
65
63
  skipTo: number | null;
66
- continueParsing: () => Promise<ParseResult<TStructure>>;
64
+ continueParsing: () => Promise<ParseResult>;
67
65
  };
68
66
  export type MatroskaParseResult = {
69
67
  status: 'done';
@@ -1,8 +1,8 @@
1
1
  import type { BufferIterator } from './buffer-iterator';
2
2
  import { type LogLevel } from './log';
3
3
  import type { Options, ParseMediaFields } from './options';
4
- import type { IsoBaseMediaBox, ParseResult, Structure } from './parse-result';
5
- import type { ParserContext } from './parser-context';
4
+ import type { IsoBaseMediaBox, ParseResult } from './parse-result';
5
+ import type { ParserState } from './state/parser-state';
6
6
  export type PartialMdatBox = {
7
7
  type: 'partial-mdat-box';
8
8
  boxSize: number;
@@ -16,13 +16,13 @@ export type BoxAndNext = {
16
16
  } | {
17
17
  type: 'incomplete';
18
18
  } | PartialMdatBox;
19
- export declare const parseVideo: ({ iterator, options, signal, logLevel, fields, mimeType, contentLength, name, }: {
19
+ export declare const parseVideo: ({ iterator, state, signal, logLevel, fields, mimeType, contentLength, name, }: {
20
20
  iterator: BufferIterator;
21
- options: ParserContext;
21
+ state: ParserState;
22
22
  signal: AbortSignal | null;
23
23
  logLevel: LogLevel;
24
24
  fields: Options<ParseMediaFields>;
25
25
  mimeType: string | null;
26
26
  contentLength: number | null;
27
27
  name: string | null;
28
- }) => Promise<ParseResult<Structure>>;
28
+ }) => Promise<ParseResult>;