@remotion/media-parser 4.0.240 → 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 (186) hide show
  1. package/dist/add-avc-profile-to-track.js +2 -2
  2. package/dist/boxes/avc/codec-private.d.ts +1 -1
  3. package/dist/boxes/avc/codec-private.js +2 -2
  4. package/dist/boxes/avc/create-sps-pps-data.d.ts +2 -0
  5. package/dist/boxes/avc/create-sps-pps-data.js +28 -0
  6. package/dist/boxes/iso-base-media/get-keyframes.d.ts +3 -0
  7. package/dist/boxes/iso-base-media/get-keyframes.js +30 -0
  8. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +3 -3
  9. package/dist/boxes/iso-base-media/mdat/mdat.js +9 -5
  10. package/dist/boxes/iso-base-media/moov/moov.d.ts +3 -3
  11. package/dist/boxes/iso-base-media/moov/moov.js +5 -4
  12. package/dist/boxes/iso-base-media/process-box.d.ts +9 -9
  13. package/dist/boxes/iso-base-media/process-box.js +48 -56
  14. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +3 -3
  15. package/dist/boxes/iso-base-media/stsd/mebx.js +5 -4
  16. package/dist/boxes/iso-base-media/stsd/samples.d.ts +5 -5
  17. package/dist/boxes/iso-base-media/stsd/samples.js +19 -16
  18. package/dist/boxes/iso-base-media/stsd/stsd.d.ts +3 -3
  19. package/dist/boxes/iso-base-media/stsd/stsd.js +2 -2
  20. package/dist/boxes/iso-base-media/trak/trak.d.ts +3 -3
  21. package/dist/boxes/iso-base-media/trak/trak.js +7 -6
  22. package/dist/boxes/riff/expect-riff-box.d.ts +3 -3
  23. package/dist/boxes/riff/expect-riff-box.js +5 -5
  24. package/dist/boxes/riff/get-tracks-from-avi.js +1 -1
  25. package/dist/boxes/riff/parse-box.d.ts +7 -7
  26. package/dist/boxes/riff/parse-box.js +29 -24
  27. package/dist/boxes/riff/parse-list-box.d.ts +3 -3
  28. package/dist/boxes/riff/parse-list-box.js +2 -2
  29. package/dist/boxes/riff/parse-movi.d.ts +5 -5
  30. package/dist/boxes/riff/parse-movi.js +35 -20
  31. package/dist/boxes/riff/parse-riff-box.d.ts +3 -3
  32. package/dist/boxes/riff/parse-riff-box.js +2 -2
  33. package/dist/boxes/transport-stream/adts-header.d.ts +1 -1
  34. package/dist/boxes/transport-stream/discard-rest-of-packet.d.ts +1 -1
  35. package/dist/boxes/transport-stream/get-tracks.js +1 -1
  36. package/dist/boxes/transport-stream/handle-aac-packet.d.ts +4 -3
  37. package/dist/boxes/transport-stream/handle-aac-packet.js +6 -4
  38. package/dist/boxes/transport-stream/handle-avc-packet.d.ts +4 -3
  39. package/dist/boxes/transport-stream/handle-avc-packet.js +8 -6
  40. package/dist/boxes/transport-stream/parse-packet.d.ts +3 -3
  41. package/dist/boxes/transport-stream/parse-packet.js +2 -2
  42. package/dist/boxes/transport-stream/parse-stream-packet.d.ts +3 -3
  43. package/dist/boxes/transport-stream/parse-stream-packet.js +14 -7
  44. package/dist/boxes/transport-stream/parse-transport-stream.d.ts +5 -6
  45. package/dist/boxes/transport-stream/parse-transport-stream.js +10 -9
  46. package/dist/boxes/transport-stream/process-stream-buffers.d.ts +6 -5
  47. package/dist/boxes/transport-stream/process-stream-buffers.js +18 -8
  48. package/dist/boxes/webm/ebml.d.ts +1 -1
  49. package/dist/boxes/webm/get-sample-from-block.d.ts +2 -2
  50. package/dist/boxes/webm/get-sample-from-block.js +8 -4
  51. package/dist/boxes/webm/make-header.d.ts +3 -3
  52. package/dist/boxes/webm/parse-ebml.d.ts +4 -4
  53. package/dist/boxes/webm/parse-ebml.js +18 -18
  54. package/dist/boxes/webm/parse-webm-header.d.ts +5 -5
  55. package/dist/boxes/webm/parse-webm-header.js +6 -5
  56. package/dist/boxes/webm/segments/parse-children.d.ts +5 -5
  57. package/dist/boxes/webm/segments/parse-children.js +12 -13
  58. package/dist/boxes/webm/segments.d.ts +3 -3
  59. package/dist/boxes/webm/segments.js +13 -13
  60. package/dist/buffer-iterator.d.ts +2 -6
  61. package/dist/buffer-iterator.js +4 -29
  62. package/dist/convert-audio-or-video-sample.js +2 -0
  63. package/dist/create/iso-base-media/codec-specific/avc1.d.ts +1 -1
  64. package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.d.ts +1 -1
  65. package/dist/create/iso-base-media/codec-specific/mp4a.d.ts +1 -1
  66. package/dist/create/iso-base-media/create-colr.d.ts +1 -1
  67. package/dist/create/iso-base-media/create-ftyp.d.ts +2 -2
  68. package/dist/create/iso-base-media/create-ilst.d.ts +1 -1
  69. package/dist/create/iso-base-media/create-mdia.d.ts +1 -1
  70. package/dist/create/iso-base-media/create-moov.d.ts +1 -1
  71. package/dist/create/iso-base-media/create-mvhd.d.ts +1 -1
  72. package/dist/create/iso-base-media/create-trak.d.ts +1 -1
  73. package/dist/create/iso-base-media/create-udta.d.ts +1 -1
  74. package/dist/create/iso-base-media/create-url.d.ts +1 -1
  75. package/dist/create/iso-base-media/ilst/create-cmt.d.ts +1 -1
  76. package/dist/create/iso-base-media/ilst/create-too.d.ts +1 -1
  77. package/dist/create/iso-base-media/mdia/create-mdhd.d.ts +1 -1
  78. package/dist/create/iso-base-media/mp4-header.d.ts +1 -1
  79. package/dist/create/iso-base-media/primitives.d.ts +13 -13
  80. package/dist/create/iso-base-media/serialize-track.d.ts +1 -1
  81. package/dist/create/iso-base-media/trak/create-tkhd.d.ts +2 -2
  82. package/dist/create/iso-base-media/trak/mdia/create-minf.d.ts +1 -1
  83. package/dist/create/iso-base-media/trak/mdia/minf/create-dinf.d.ts +1 -1
  84. package/dist/create/iso-base-media/trak/mdia/minf/create-smhd.d.ts +1 -1
  85. package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.d.ts +1 -1
  86. package/dist/create/iso-base-media/trak/mdia/minf/create-vmhd.d.ts +1 -1
  87. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.d.ts +1 -1
  88. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stco.d.ts +1 -1
  89. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.d.ts +1 -1
  90. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stss.d.ts +1 -1
  91. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.d.ts +1 -1
  92. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.d.ts +1 -1
  93. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.d.ts +1 -1
  94. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.d.ts +1 -1
  95. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.d.ts +1 -1
  96. package/dist/create/iso-base-media/udta/create-meta.d.ts +1 -1
  97. package/dist/create/iso-base-media/udta/meta/create-hdlr.d.ts +1 -1
  98. package/dist/create/matroska/cluster-segment.d.ts +1 -1
  99. package/dist/emit-available-info.d.ts +6 -4
  100. package/dist/emit-available-info.js +231 -79
  101. package/dist/errors/detect-file-type.d.ts +1 -0
  102. package/dist/errors/detect-file-type.js +88 -0
  103. package/dist/errors/file-types.d.ts +1 -0
  104. package/dist/errors/file-types.js +88 -0
  105. package/dist/errors.d.ts +68 -0
  106. package/dist/errors.js +71 -0
  107. package/dist/esm/from-fetch.mjs +1 -0
  108. package/dist/esm/from-node.mjs +1 -0
  109. package/dist/esm/from-web-file.mjs +2 -1
  110. package/dist/esm/index.mjs +1457 -542
  111. package/dist/file-types/bmp.d.ts +6 -0
  112. package/dist/file-types/bmp.js +23 -0
  113. package/dist/file-types/detect-file-type.d.ts +42 -0
  114. package/dist/file-types/detect-file-type.js +59 -0
  115. package/dist/file-types/get-jpeg-dimensions.d.ts +4 -0
  116. package/dist/file-types/get-jpeg-dimensions.js +32 -0
  117. package/dist/file-types/index.d.ts +2 -0
  118. package/dist/file-types/index.js +57 -0
  119. package/dist/file-types/jpeg.d.ts +12 -0
  120. package/dist/file-types/jpeg.js +44 -0
  121. package/dist/file-types/pdf.d.ts +4 -0
  122. package/dist/file-types/pdf.js +12 -0
  123. package/dist/file-types/png.d.ts +10 -0
  124. package/dist/file-types/png.js +32 -0
  125. package/dist/file-types/webp.d.ts +6 -0
  126. package/dist/file-types/webp.js +69 -0
  127. package/dist/file-types.d.ts +1 -0
  128. package/dist/file-types.js +88 -0
  129. package/dist/get-audio-codec.d.ts +1 -1
  130. package/dist/get-duration.d.ts +1 -0
  131. package/dist/get-duration.js +14 -1
  132. package/dist/get-fields-from-callbacks.d.ts +5 -0
  133. package/dist/get-fields-from-callbacks.js +32 -0
  134. package/dist/get-fps.d.ts +1 -0
  135. package/dist/get-fps.js +17 -12
  136. package/dist/get-keyframes.d.ts +5 -0
  137. package/dist/get-keyframes.js +20 -0
  138. package/dist/get-tracks.d.ts +7 -1
  139. package/dist/get-tracks.js +15 -10
  140. package/dist/has-all-info.d.ts +5 -4
  141. package/dist/has-all-info.js +31 -5
  142. package/dist/index.d.ts +2 -0
  143. package/dist/index.js +7 -1
  144. package/dist/may-skip-video-data/may-skip-video-data.d.ts +4 -0
  145. package/dist/may-skip-video-data/may-skip-video-data.js +14 -0
  146. package/dist/may-skip-video-data/need-samples-for-fields.d.ts +5 -0
  147. package/dist/may-skip-video-data/need-samples-for-fields.js +33 -0
  148. package/dist/options.d.ts +68 -53
  149. package/dist/parse-media.js +42 -31
  150. package/dist/parse-result.d.ts +2 -4
  151. package/dist/parse-video.d.ts +8 -5
  152. package/dist/parse-video.js +94 -17
  153. package/dist/probing/detect-file-type.d.ts +1 -0
  154. package/dist/probing/detect-file-type.js +88 -0
  155. package/dist/probing/get-jpeg-dimensions.d.ts +4 -0
  156. package/dist/probing/get-jpeg-dimensions.js +32 -0
  157. package/dist/readers/from-fetch.js +1 -0
  158. package/dist/readers/from-node.js +1 -0
  159. package/dist/readers/from-web-file.js +1 -0
  160. package/dist/readers/reader.d.ts +1 -0
  161. package/dist/register-track.d.ts +5 -5
  162. package/dist/register-track.js +12 -12
  163. package/dist/state/can-skip-tracks.js +6 -0
  164. package/dist/state/emitted-fields.d.ts +2 -0
  165. package/dist/state/emitted-fields.js +31 -0
  166. package/dist/state/has-tracks-section.d.ts +1 -0
  167. package/dist/state/keyframes.d.ts +6 -0
  168. package/dist/state/keyframes.js +15 -0
  169. package/dist/state/parser-state.d.ts +60 -29
  170. package/dist/state/parser-state.js +32 -150
  171. package/dist/state/riff.d.ts +10 -0
  172. package/dist/state/riff.js +32 -0
  173. package/dist/state/sample-callbacks.d.ts +31 -0
  174. package/dist/state/sample-callbacks.js +96 -0
  175. package/dist/state/slow-duration-fps.d.ts +8 -0
  176. package/dist/state/slow-duration-fps.js +36 -0
  177. package/dist/state/structure.d.ts +7 -0
  178. package/dist/state/structure.js +21 -0
  179. package/dist/state/tracks-and-samples.d.ts +0 -0
  180. package/dist/state/tracks-and-samples.js +1 -0
  181. package/dist/state/webm.d.ts +11 -0
  182. package/dist/state/webm.js +67 -0
  183. package/dist/version.d.ts +1 -1
  184. package/dist/version.js +1 -1
  185. package/dist/webcodec-sample-types.d.ts +2 -0
  186. package/package.json +3 -3
@@ -3,50 +3,56 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseMedia = void 0;
4
4
  const buffer_iterator_1 = require("./buffer-iterator");
5
5
  const emit_available_info_1 = require("./emit-available-info");
6
+ const get_fields_from_callbacks_1 = require("./get-fields-from-callbacks");
6
7
  const has_all_info_1 = require("./has-all-info");
7
8
  const log_1 = require("./log");
8
9
  const parse_video_1 = require("./parse-video");
9
10
  const from_fetch_1 = require("./readers/from-fetch");
10
11
  const parser_state_1 = require("./state/parser-state");
11
- const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.fetchReader, onAudioTrack, onVideoTrack, signal, logLevel = 'info', onParseProgress, ...more }) => {
12
+ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader: readerInterface = from_fetch_1.fetchReader, onAudioTrack, onVideoTrack, signal, logLevel = 'info', onParseProgress, ...more }) {
12
13
  let iterator = null;
13
14
  let parseResult = null;
14
- const state = (0, parser_state_1.makeParserState)({
15
- hasAudioTrackHandlers: Boolean(onAudioTrack),
16
- hasVideoTrackHandlers: Boolean(onVideoTrack),
17
- signal,
18
- getIterator: () => iterator,
19
- fields: fields !== null && fields !== void 0 ? fields : {},
15
+ const fieldsInReturnValue = _fieldsInReturnValue !== null && _fieldsInReturnValue !== void 0 ? _fieldsInReturnValue : {};
16
+ const fields = (0, get_fields_from_callbacks_1.getFieldsFromCallback)({
17
+ fields: fieldsInReturnValue,
18
+ callbacks: more,
20
19
  });
21
- const { reader, contentLength, name, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
22
- let currentReader = reader;
20
+ const { reader, contentLength, name, contentType, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
23
21
  const supportsContentRange = readerSupportsContentRange &&
24
22
  !(typeof process !== 'undefined' &&
25
23
  typeof process.env !== 'undefined' &&
26
24
  process.env.DISABLE_CONTENT_RANGE === 'true');
27
- const returnValue = {};
28
- const moreFields = more;
29
- const options = {
25
+ const state = (0, parser_state_1.makeParserState)({
26
+ hasAudioTrackHandlers: Boolean(onAudioTrack),
27
+ hasVideoTrackHandlers: Boolean(onVideoTrack),
28
+ signal,
29
+ getIterator: () => iterator,
30
+ fields,
30
31
  onAudioTrack: onAudioTrack !== null && onAudioTrack !== void 0 ? onAudioTrack : null,
31
32
  onVideoTrack: onVideoTrack !== null && onVideoTrack !== void 0 ? onVideoTrack : null,
32
- parserState: state,
33
33
  nullifySamples: !(typeof process !== 'undefined' &&
34
34
  typeof process.env !== 'undefined' &&
35
35
  process.env.KEEP_SAMPLES === 'true'),
36
36
  supportsContentRange,
37
- nextTrackIndex: 0,
38
- };
37
+ });
38
+ let currentReader = reader;
39
+ const returnValue = {};
40
+ const moreFields = more;
39
41
  const triggerInfoEmit = () => {
40
- var _a;
41
- const availableInfo = (0, has_all_info_1.getAvailableInfo)(fields !== null && fields !== void 0 ? fields : {}, (_a = parseResult === null || parseResult === void 0 ? void 0 : parseResult.segments) !== null && _a !== void 0 ? _a : null, state);
42
+ const availableInfo = (0, has_all_info_1.getAvailableInfo)({
43
+ fieldsToFetch: fields,
44
+ state,
45
+ });
42
46
  (0, emit_available_info_1.emitAvailableInfo)({
43
47
  hasInfo: availableInfo,
44
- moreFields,
48
+ callbacks: moreFields,
49
+ fieldsInReturnValue,
45
50
  parseResult,
46
51
  state,
47
52
  returnValue,
48
53
  contentLength,
49
54
  name,
55
+ mimeType: contentType,
50
56
  });
51
57
  };
52
58
  triggerInfoEmit();
@@ -86,24 +92,26 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
86
92
  }));
87
93
  triggerInfoEmit();
88
94
  if (parseResult && parseResult.status === 'incomplete') {
89
- 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());
90
96
  parseResult = await parseResult.continueParsing();
91
97
  }
92
98
  else {
93
99
  parseResult = await (0, parse_video_1.parseVideo)({
94
100
  iterator,
95
- options,
101
+ state,
96
102
  signal: signal !== null && signal !== void 0 ? signal : null,
97
103
  logLevel,
98
- fields: fields !== null && fields !== void 0 ? fields : {},
104
+ fields,
105
+ mimeType: contentType,
106
+ contentLength,
107
+ name,
99
108
  });
100
109
  }
101
110
  if (parseResult.status === 'incomplete' && parseResult.skipTo !== null) {
102
111
  state.increaseSkippedBytes(parseResult.skipTo - iterator.counter.getOffset());
103
112
  }
104
113
  if ((0, has_all_info_1.hasAllInfo)({
105
- fields: fields !== null && fields !== void 0 ? fields : {},
106
- structure: parseResult.segments,
114
+ fields,
107
115
  state,
108
116
  })) {
109
117
  log_1.Log.verbose(logLevel, 'Got all info, skipping to the end.');
@@ -128,24 +136,27 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
128
136
  }
129
137
  }
130
138
  log_1.Log.verbose(logLevel, 'Finished parsing file');
139
+ const hasInfo = Object.keys(fields).reduce((acc, key) => {
140
+ if (fields === null || fields === void 0 ? void 0 : fields[key]) {
141
+ acc[key] = true;
142
+ }
143
+ return acc;
144
+ }, {});
131
145
  // Force assign
132
146
  (0, emit_available_info_1.emitAvailableInfo)({
133
- hasInfo: Object.keys(fields !== null && fields !== void 0 ? fields : {}).reduce((acc, key) => {
134
- if (fields === null || fields === void 0 ? void 0 : fields[key]) {
135
- acc[key] = true;
136
- }
137
- return acc;
138
- }, {}),
139
- moreFields,
147
+ hasInfo,
148
+ callbacks: moreFields,
149
+ fieldsInReturnValue,
140
150
  parseResult,
141
151
  state,
142
152
  returnValue,
143
153
  contentLength,
154
+ mimeType: contentType,
144
155
  name,
145
156
  });
146
157
  currentReader.abort();
147
158
  iterator === null || iterator === void 0 ? void 0 : iterator.destroy();
148
- state.tracks.ensureHasTracksAtEnd();
159
+ state.callbacks.tracks.ensureHasTracksAtEnd();
149
160
  return returnValue;
150
161
  };
151
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,10 +16,13 @@ export type BoxAndNext = {
16
16
  } | {
17
17
  type: 'incomplete';
18
18
  } | PartialMdatBox;
19
- export declare const parseVideo: ({ iterator, options, signal, logLevel, fields, }: {
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
- }) => Promise<ParseResult<Structure>>;
25
+ mimeType: string | null;
26
+ contentLength: number | null;
27
+ name: string | null;
28
+ }) => Promise<ParseResult>;
@@ -6,49 +6,126 @@ const parse_box_1 = require("./boxes/riff/parse-box");
6
6
  const next_pes_header_store_1 = require("./boxes/transport-stream/next-pes-header-store");
7
7
  const parse_transport_stream_1 = require("./boxes/transport-stream/parse-transport-stream");
8
8
  const parse_webm_header_1 = require("./boxes/webm/parse-webm-header");
9
+ const errors_1 = require("./errors");
9
10
  const log_1 = require("./log");
10
- const parseVideo = ({ iterator, options, signal, logLevel, fields, }) => {
11
+ const parseVideo = ({ iterator, state, signal, logLevel, fields, mimeType, contentLength, name, }) => {
11
12
  if (iterator.bytesRemaining() === 0) {
12
13
  return Promise.reject(new Error('no bytes'));
13
14
  }
14
- if (iterator.isRiff()) {
15
+ const fileType = iterator.detectFileType();
16
+ if (fileType.type === 'riff') {
15
17
  log_1.Log.verbose(logLevel, 'Detected RIFF container');
16
- return Promise.resolve((0, parse_box_1.parseRiff)({ iterator, options, fields }));
18
+ state.structure.setStructure({
19
+ type: 'riff',
20
+ boxes: [],
21
+ });
22
+ return Promise.resolve((0, parse_box_1.parseRiff)({ iterator, state, fields }));
17
23
  }
18
- if (iterator.isIsoBaseMedia()) {
24
+ if (fileType.type === 'iso-base-media') {
19
25
  log_1.Log.verbose(logLevel, 'Detected ISO Base Media container');
26
+ const initialBoxes = [];
27
+ state.structure.setStructure({
28
+ type: 'iso-base-media',
29
+ boxes: initialBoxes,
30
+ });
20
31
  return (0, process_box_1.parseIsoBaseMediaBoxes)({
21
32
  iterator,
22
33
  maxBytes: Infinity,
23
34
  allowIncompleteBoxes: true,
24
- initialBoxes: [],
25
- options,
35
+ initialBoxes,
36
+ state,
26
37
  continueMdat: false,
27
38
  signal,
28
39
  logLevel,
29
40
  fields,
30
41
  });
31
42
  }
32
- if (iterator.isWebm()) {
43
+ if (fileType.type === 'webm') {
33
44
  log_1.Log.verbose(logLevel, 'Detected Matroska container');
34
- return (0, parse_webm_header_1.parseWebm)({ counter: iterator, parserContext: options, fields });
45
+ state.structure.setStructure({
46
+ boxes: [],
47
+ type: 'matroska',
48
+ });
49
+ return (0, parse_webm_header_1.parseWebm)({ counter: iterator, state, fields });
35
50
  }
36
- if (iterator.isTransportStream()) {
51
+ if (fileType.type === 'transport-stream') {
52
+ log_1.Log.verbose(logLevel, 'Detected MPEG-2 Transport Stream');
53
+ state.structure.setStructure({
54
+ boxes: [],
55
+ type: 'transport-stream',
56
+ });
37
57
  return (0, parse_transport_stream_1.parseTransportStream)({
38
58
  iterator,
39
- parserContext: options,
40
- structure: {
41
- type: 'transport-stream',
42
- boxes: [],
43
- },
59
+ state,
44
60
  streamBuffers: new Map(),
45
61
  fields,
46
62
  nextPesHeaderStore: (0, next_pes_header_store_1.makeNextPesHeaderStore)(),
47
63
  });
48
64
  }
49
- if (iterator.isMp3()) {
50
- return Promise.reject(new Error('MP3 files are not yet supported'));
65
+ if (fileType.type === 'mp3') {
66
+ return Promise.reject(new errors_1.IsAnUnsupportedAudioTypeError({
67
+ message: 'MP3 files are not yet supported',
68
+ mimeType,
69
+ sizeInBytes: contentLength,
70
+ fileName: name,
71
+ audioType: 'mp3',
72
+ }));
73
+ }
74
+ if (fileType.type === 'wav') {
75
+ return Promise.reject(new errors_1.IsAnUnsupportedAudioTypeError({
76
+ message: 'WAV files are not yet supported',
77
+ mimeType,
78
+ sizeInBytes: contentLength,
79
+ fileName: name,
80
+ audioType: 'wav',
81
+ }));
82
+ }
83
+ if (fileType.type === 'aac') {
84
+ return Promise.reject(new errors_1.IsAnUnsupportedAudioTypeError({
85
+ message: 'AAC files are not yet supported',
86
+ mimeType,
87
+ sizeInBytes: contentLength,
88
+ fileName: name,
89
+ audioType: 'aac',
90
+ }));
91
+ }
92
+ if (fileType.type === 'gif') {
93
+ return Promise.reject(new errors_1.IsAGifError({
94
+ message: 'GIF files are not yet supported',
95
+ mimeType,
96
+ sizeInBytes: contentLength,
97
+ fileName: name,
98
+ }));
99
+ }
100
+ if (fileType.type === 'pdf') {
101
+ return Promise.reject(new errors_1.IsAPdfError({
102
+ message: 'GIF files are not supported',
103
+ mimeType,
104
+ sizeInBytes: contentLength,
105
+ fileName: name,
106
+ }));
107
+ }
108
+ if (fileType.type === 'bmp' ||
109
+ fileType.type === 'jpeg' ||
110
+ fileType.type === 'png' ||
111
+ fileType.type === 'webp') {
112
+ return Promise.reject(new errors_1.IsAnImageError({
113
+ message: 'Image files are not supported',
114
+ imageType: fileType.type,
115
+ dimensions: fileType.dimensions,
116
+ mimeType,
117
+ sizeInBytes: contentLength,
118
+ fileName: name,
119
+ }));
120
+ }
121
+ if (fileType.type === 'unknown') {
122
+ return Promise.reject(new errors_1.IsAnUnsupportedFileTypeError({
123
+ message: 'Unknown file format',
124
+ mimeType,
125
+ sizeInBytes: contentLength,
126
+ fileName: name,
127
+ }));
51
128
  }
52
- return Promise.reject(new Error('Unknown video format'));
129
+ return Promise.reject(new Error('Unknown video format ' + fileType));
53
130
  };
54
131
  exports.parseVideo = parseVideo;
@@ -0,0 +1 @@
1
+ export declare const detectFileType: (data: Uint8Array) => "webp" | "riff" | "webm" | "iso-base-media" | "transport-stream" | "mp3" | "gif" | "png" | "bmp" | "jpeg" | "unknown";
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectFileType = void 0;
4
+ const make_header_1 = require("../boxes/webm/make-header");
5
+ const get_jpeg_dimensions_1 = require("./get-jpeg-dimensions");
6
+ const matchesPattern = (pattern) => {
7
+ return (data) => {
8
+ return pattern.every((value, index) => data[index] === value);
9
+ };
10
+ };
11
+ const isRiff = (data) => {
12
+ const riffPattern = new Uint8Array([0x52, 0x49, 0x46, 0x46]);
13
+ return matchesPattern(riffPattern)(data.subarray(0, 4));
14
+ };
15
+ const isWebm = (data) => {
16
+ return matchesPattern(make_header_1.webmPattern)(data.subarray(0, 4));
17
+ };
18
+ const isIsoBaseMedia = (data) => {
19
+ const isoBaseMediaMp4Pattern = new TextEncoder().encode('ftyp');
20
+ return matchesPattern(isoBaseMediaMp4Pattern)(data.subarray(4, 8));
21
+ };
22
+ const isTransportStream = (data) => {
23
+ return data[0] === 0x47 && data[188] === 0x47;
24
+ };
25
+ const isMp3 = (data) => {
26
+ const mpegPattern = new Uint8Array([0xff, 0xf3, 0xe4, 0x64]);
27
+ return matchesPattern(mpegPattern)(data.subarray(0, 4));
28
+ };
29
+ const isGif = (data) => {
30
+ const gifPattern = new Uint8Array([0x47, 0x49, 0x46, 0x38]);
31
+ return matchesPattern(gifPattern)(data.subarray(0, 4));
32
+ };
33
+ const isPng = (data) => {
34
+ const pngPattern = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
35
+ return matchesPattern(pngPattern)(data.subarray(0, 4));
36
+ };
37
+ const isBmp = (data) => {
38
+ const bmpPattern = new Uint8Array([0x42, 0x4d]);
39
+ return matchesPattern(bmpPattern)(data.subarray(0, 2));
40
+ };
41
+ const isJpeg = (data) => {
42
+ const jpegPattern = new Uint8Array([0xff, 0xd8]);
43
+ const jpeg = matchesPattern(jpegPattern)(data.subarray(0, 2));
44
+ if (!jpeg) {
45
+ return false;
46
+ }
47
+ const dim = (0, get_jpeg_dimensions_1.getJpegDimensions)(data);
48
+ console.log(dim);
49
+ return true;
50
+ };
51
+ const isWebp = (data) => {
52
+ const webpPattern = new Uint8Array([0x52, 0x49, 0x46, 0x46]);
53
+ return matchesPattern(webpPattern)(data.subarray(0, 4));
54
+ };
55
+ const detectFileType = (data) => {
56
+ if (isWebp(data)) {
57
+ return 'webp';
58
+ }
59
+ if (isRiff(data)) {
60
+ return 'riff';
61
+ }
62
+ if (isWebm(data)) {
63
+ return 'webm';
64
+ }
65
+ if (isIsoBaseMedia(data)) {
66
+ return 'iso-base-media';
67
+ }
68
+ if (isTransportStream(data)) {
69
+ return 'transport-stream';
70
+ }
71
+ if (isMp3(data)) {
72
+ return 'mp3';
73
+ }
74
+ if (isGif(data)) {
75
+ return 'gif';
76
+ }
77
+ if (isPng(data)) {
78
+ return 'png';
79
+ }
80
+ if (isBmp(data)) {
81
+ return 'bmp';
82
+ }
83
+ if (isJpeg(data)) {
84
+ return 'jpeg';
85
+ }
86
+ return 'unknown';
87
+ };
88
+ exports.detectFileType = detectFileType;
@@ -0,0 +1,4 @@
1
+ export declare function getJpegDimensions(data: Uint8Array): {
2
+ width: number;
3
+ height: number;
4
+ } | null;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getJpegDimensions = getJpegDimensions;
4
+ function getJpegDimensions(data) {
5
+ let offset = 0;
6
+ // Helper function to read a 16-bit big-endian integer
7
+ function readUint16BE(o) {
8
+ return (data[o] << 8) | data[o + 1];
9
+ }
10
+ // Skip the Start of Image (SOI) marker
11
+ if (readUint16BE(offset) !== 0xffd8) {
12
+ return null; // Not a valid JPEG file
13
+ }
14
+ offset += 2;
15
+ while (offset < data.length) {
16
+ if (data[offset] === 0xff) {
17
+ const marker = data[offset + 1];
18
+ if (marker === 0xc0 || marker === 0xc2) {
19
+ // SOF0 or SOF2
20
+ const height = readUint16BE(offset + 5);
21
+ const width = readUint16BE(offset + 7);
22
+ return { width, height };
23
+ }
24
+ const length = readUint16BE(offset + 2);
25
+ offset += length + 2; // Move to the next marker
26
+ }
27
+ else {
28
+ offset++;
29
+ }
30
+ }
31
+ return null; // Return null if dimensions are not found
32
+ }
@@ -110,6 +110,7 @@ exports.fetchReader = {
110
110
  },
111
111
  },
112
112
  contentLength,
113
+ contentType: res.headers.get('content-type'),
113
114
  name: name !== null && name !== void 0 ? name : fallbackName,
114
115
  supportsContentRange,
115
116
  };
@@ -38,6 +38,7 @@ exports.nodeReader = {
38
38
  },
39
39
  },
40
40
  contentLength: stats.size,
41
+ contentType: null,
41
42
  name: src.split(path_1.sep).pop(),
42
43
  supportsContentRange: true,
43
44
  };
@@ -39,6 +39,7 @@ exports.webFileReader = {
39
39
  contentLength: file.size,
40
40
  name: file.name,
41
41
  supportsContentRange: true,
42
+ contentType: file.type,
42
43
  });
43
44
  };
44
45
  reader.onerror = (error) => {
@@ -5,6 +5,7 @@ type Reader = {
5
5
  type ReadResult = {
6
6
  reader: Reader;
7
7
  contentLength: number | null;
8
+ contentType: string | null;
8
9
  name: string;
9
10
  supportsContentRange: boolean;
10
11
  };
@@ -1,13 +1,13 @@
1
1
  import type { Track, VideoTrack } from './get-tracks';
2
2
  import type { ParseMediaContainer } from './options';
3
- import type { ParserContext } from './parser-context';
4
- export declare const registerTrack: ({ options, track, container, }: {
5
- options: ParserContext;
3
+ import type { ParserState } from './state/parser-state';
4
+ export declare const registerTrack: ({ state, track, container, }: {
5
+ state: ParserState;
6
6
  track: Track;
7
7
  container: ParseMediaContainer;
8
8
  }) => Promise<void>;
9
- export declare const registerVideoTrackWhenProfileIsAvailable: ({ options, track, container, }: {
10
- options: ParserContext;
9
+ export declare const registerVideoTrackWhenProfileIsAvailable: ({ state, track, container, }: {
10
+ state: ParserState;
11
11
  track: VideoTrack;
12
12
  container: ParseMediaContainer;
13
13
  }) => void;
@@ -2,27 +2,27 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerVideoTrackWhenProfileIsAvailable = exports.registerTrack = void 0;
4
4
  const add_avc_profile_to_track_1 = require("./add-avc-profile-to-track");
5
- const registerTrack = async ({ options, track, container, }) => {
5
+ const registerTrack = async ({ state, track, container, }) => {
6
6
  if (track.type === 'video') {
7
- options.parserState.tracks.addTrack(track);
8
- if (options.onVideoTrack) {
9
- const callback = await options.onVideoTrack({ track, container });
10
- await options.parserState.registerVideoSampleCallback(track.trackId, callback !== null && callback !== void 0 ? callback : null);
7
+ state.callbacks.tracks.addTrack(track);
8
+ if (state.onVideoTrack) {
9
+ const callback = await state.onVideoTrack({ track, container });
10
+ await state.callbacks.registerVideoSampleCallback(track.trackId, callback !== null && callback !== void 0 ? callback : null);
11
11
  }
12
12
  }
13
13
  if (track.type === 'audio') {
14
- options.parserState.tracks.addTrack(track);
15
- if (options.onAudioTrack) {
16
- const callback = await options.onAudioTrack({ track, container });
17
- await options.parserState.registerAudioSampleCallback(track.trackId, callback !== null && callback !== void 0 ? callback : null);
14
+ state.callbacks.tracks.addTrack(track);
15
+ if (state.onAudioTrack) {
16
+ const callback = await state.onAudioTrack({ track, container });
17
+ await state.callbacks.registerAudioSampleCallback(track.trackId, callback !== null && callback !== void 0 ? callback : null);
18
18
  }
19
19
  }
20
20
  };
21
21
  exports.registerTrack = registerTrack;
22
- const registerVideoTrackWhenProfileIsAvailable = ({ options, track, container, }) => {
23
- options.parserState.registerOnAvcProfileCallback(async (profile) => {
22
+ const registerVideoTrackWhenProfileIsAvailable = ({ state, track, container, }) => {
23
+ state.riff.registerOnAvcProfileCallback(async (profile) => {
24
24
  await (0, exports.registerTrack)({
25
- options,
25
+ state,
26
26
  track: (0, add_avc_profile_to_track_1.addAvcProfileToTrack)(track, profile),
27
27
  container,
28
28
  });
@@ -6,6 +6,8 @@ const needsTracksField = {
6
6
  container: false,
7
7
  dimensions: true,
8
8
  durationInSeconds: true,
9
+ slowDurationInSeconds: true,
10
+ slowFps: true,
9
11
  fps: true,
10
12
  internalStats: false,
11
13
  isHdr: true,
@@ -18,6 +20,10 @@ const needsTracksField = {
18
20
  videoCodec: true,
19
21
  metadata: true,
20
22
  location: true,
23
+ mimeType: false,
24
+ slowKeyframes: true,
25
+ slowNumberOfFrames: true,
26
+ keyframes: true,
21
27
  };
22
28
  const makeCanSkipTracksState = ({ hasAudioTrackHandlers, fields, hasVideoTrackHandlers, }) => {
23
29
  return {
@@ -0,0 +1,2 @@
1
+ import type { AllOptions, ParseMediaFields } from '../options';
2
+ export declare const emittedState: () => AllOptions<ParseMediaFields>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emittedState = void 0;
4
+ const emittedState = () => {
5
+ const emittedFields = {
6
+ audioCodec: false,
7
+ container: false,
8
+ dimensions: false,
9
+ durationInSeconds: false,
10
+ fps: false,
11
+ internalStats: false,
12
+ isHdr: false,
13
+ location: false,
14
+ metadata: false,
15
+ mimeType: false,
16
+ name: false,
17
+ rotation: false,
18
+ size: false,
19
+ structure: false,
20
+ tracks: false,
21
+ videoCodec: false,
22
+ unrotatedDimensions: false,
23
+ slowDurationInSeconds: false,
24
+ slowFps: false,
25
+ slowKeyframes: false,
26
+ slowNumberOfFrames: false,
27
+ keyframes: false,
28
+ };
29
+ return emittedFields;
30
+ };
31
+ exports.emittedState = emittedState;
@@ -7,3 +7,4 @@ export declare const makeTracksSectionState: (canSkipTracksState: CanSkipTracksS
7
7
  getTracks: () => Track[];
8
8
  ensureHasTracksAtEnd: () => void;
9
9
  };
10
+ export type TracksState = ReturnType<typeof makeTracksSectionState>;
@@ -0,0 +1,6 @@
1
+ import type { MediaParserKeyframe } from '../options';
2
+ export declare const keyframesState: () => {
3
+ addKeyframe: (keyframe: MediaParserKeyframe) => void;
4
+ getKeyframes: () => MediaParserKeyframe[];
5
+ };
6
+ export type KeyframesState = ReturnType<typeof keyframesState>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.keyframesState = void 0;
4
+ const keyframesState = () => {
5
+ const keyframes = [];
6
+ return {
7
+ addKeyframe: (keyframe) => {
8
+ keyframes.push(keyframe);
9
+ },
10
+ getKeyframes: () => {
11
+ return keyframes;
12
+ },
13
+ };
14
+ };
15
+ exports.keyframesState = keyframesState;