@remotion/media-parser 4.0.240 → 4.0.241

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 (96) hide show
  1. package/dist/boxes/avc/codec-private.d.ts +1 -1
  2. package/dist/boxes/transport-stream/adts-header.d.ts +1 -1
  3. package/dist/boxes/transport-stream/discard-rest-of-packet.d.ts +1 -1
  4. package/dist/boxes/webm/ebml.d.ts +1 -1
  5. package/dist/boxes/webm/make-header.d.ts +3 -3
  6. package/dist/buffer-iterator.d.ts +2 -6
  7. package/dist/buffer-iterator.js +4 -29
  8. package/dist/create/iso-base-media/codec-specific/avc1.d.ts +1 -1
  9. package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.d.ts +1 -1
  10. package/dist/create/iso-base-media/codec-specific/mp4a.d.ts +1 -1
  11. package/dist/create/iso-base-media/create-colr.d.ts +1 -1
  12. package/dist/create/iso-base-media/create-ftyp.d.ts +2 -2
  13. package/dist/create/iso-base-media/create-ilst.d.ts +1 -1
  14. package/dist/create/iso-base-media/create-mdia.d.ts +1 -1
  15. package/dist/create/iso-base-media/create-moov.d.ts +1 -1
  16. package/dist/create/iso-base-media/create-mvhd.d.ts +1 -1
  17. package/dist/create/iso-base-media/create-trak.d.ts +1 -1
  18. package/dist/create/iso-base-media/create-udta.d.ts +1 -1
  19. package/dist/create/iso-base-media/create-url.d.ts +1 -1
  20. package/dist/create/iso-base-media/ilst/create-cmt.d.ts +1 -1
  21. package/dist/create/iso-base-media/ilst/create-too.d.ts +1 -1
  22. package/dist/create/iso-base-media/mdia/create-mdhd.d.ts +1 -1
  23. package/dist/create/iso-base-media/mp4-header.d.ts +1 -1
  24. package/dist/create/iso-base-media/primitives.d.ts +13 -13
  25. package/dist/create/iso-base-media/serialize-track.d.ts +1 -1
  26. package/dist/create/iso-base-media/trak/create-tkhd.d.ts +2 -2
  27. package/dist/create/iso-base-media/trak/mdia/create-minf.d.ts +1 -1
  28. package/dist/create/iso-base-media/trak/mdia/minf/create-dinf.d.ts +1 -1
  29. package/dist/create/iso-base-media/trak/mdia/minf/create-smhd.d.ts +1 -1
  30. package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.d.ts +1 -1
  31. package/dist/create/iso-base-media/trak/mdia/minf/create-vmhd.d.ts +1 -1
  32. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.d.ts +1 -1
  33. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stco.d.ts +1 -1
  34. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.d.ts +1 -1
  35. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stss.d.ts +1 -1
  36. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.d.ts +1 -1
  37. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.d.ts +1 -1
  38. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.d.ts +1 -1
  39. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.d.ts +1 -1
  40. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.d.ts +1 -1
  41. package/dist/create/iso-base-media/udta/create-meta.d.ts +1 -1
  42. package/dist/create/iso-base-media/udta/meta/create-hdlr.d.ts +1 -1
  43. package/dist/create/matroska/cluster-segment.d.ts +1 -1
  44. package/dist/emit-available-info.d.ts +6 -3
  45. package/dist/emit-available-info.js +107 -69
  46. package/dist/errors/detect-file-type.d.ts +1 -0
  47. package/dist/errors/detect-file-type.js +88 -0
  48. package/dist/errors/file-types.d.ts +1 -0
  49. package/dist/errors/file-types.js +88 -0
  50. package/dist/errors.d.ts +68 -0
  51. package/dist/errors.js +71 -0
  52. package/dist/esm/from-fetch.mjs +1 -0
  53. package/dist/esm/from-node.mjs +1 -0
  54. package/dist/esm/from-web-file.mjs +2 -1
  55. package/dist/esm/index.mjs +633 -109
  56. package/dist/file-types/bmp.d.ts +6 -0
  57. package/dist/file-types/bmp.js +23 -0
  58. package/dist/file-types/detect-file-type.d.ts +42 -0
  59. package/dist/file-types/detect-file-type.js +59 -0
  60. package/dist/file-types/get-jpeg-dimensions.d.ts +4 -0
  61. package/dist/file-types/get-jpeg-dimensions.js +32 -0
  62. package/dist/file-types/index.d.ts +2 -0
  63. package/dist/file-types/index.js +57 -0
  64. package/dist/file-types/jpeg.d.ts +12 -0
  65. package/dist/file-types/jpeg.js +44 -0
  66. package/dist/file-types/pdf.d.ts +4 -0
  67. package/dist/file-types/pdf.js +12 -0
  68. package/dist/file-types/png.d.ts +10 -0
  69. package/dist/file-types/png.js +32 -0
  70. package/dist/file-types/webp.d.ts +6 -0
  71. package/dist/file-types/webp.js +69 -0
  72. package/dist/file-types.d.ts +1 -0
  73. package/dist/file-types.js +88 -0
  74. package/dist/get-audio-codec.d.ts +1 -1
  75. package/dist/get-fields-from-callbacks.d.ts +5 -0
  76. package/dist/get-fields-from-callbacks.js +27 -0
  77. package/dist/has-all-info.d.ts +5 -1
  78. package/dist/has-all-info.js +10 -3
  79. package/dist/index.d.ts +2 -1
  80. package/dist/index.js +7 -1
  81. package/dist/options.d.ts +36 -53
  82. package/dist/parse-media.js +53 -14
  83. package/dist/parse-video.d.ts +4 -1
  84. package/dist/parse-video.js +71 -8
  85. package/dist/probing/detect-file-type.d.ts +1 -0
  86. package/dist/probing/detect-file-type.js +88 -0
  87. package/dist/probing/get-jpeg-dimensions.d.ts +4 -0
  88. package/dist/probing/get-jpeg-dimensions.js +32 -0
  89. package/dist/readers/from-fetch.js +1 -0
  90. package/dist/readers/from-node.js +1 -0
  91. package/dist/readers/from-web-file.js +1 -0
  92. package/dist/readers/reader.d.ts +1 -0
  93. package/dist/state/can-skip-tracks.js +1 -0
  94. package/dist/version.d.ts +1 -1
  95. package/dist/version.js +1 -1
  96. package/package.json +3 -3
package/dist/options.d.ts CHANGED
@@ -25,6 +25,7 @@ export type ParseMediaFields = {
25
25
  isHdr: boolean;
26
26
  metadata: boolean;
27
27
  location: boolean;
28
+ mimeType: boolean;
28
29
  };
29
30
  export type AllParseMediaFields = {
30
31
  dimensions: true;
@@ -43,95 +44,77 @@ export type AllParseMediaFields = {
43
44
  isHdr: true;
44
45
  metadata: true;
45
46
  location: true;
47
+ mimeType: true;
46
48
  };
47
- export type Options<Fields extends ParseMediaFields> = {
48
- dimensions?: Fields['dimensions'];
49
- durationInSeconds?: Fields['durationInSeconds'];
50
- structure?: Fields['structure'];
51
- fps?: Fields['fps'];
52
- videoCodec?: Fields['videoCodec'];
53
- audioCodec?: Fields['audioCodec'];
54
- tracks?: Fields['tracks'];
55
- rotation?: Fields['rotation'];
56
- unrotatedDimensions?: Fields['unrotatedDimensions'];
57
- internalStats?: Fields['internalStats'];
58
- size?: Fields['size'];
59
- name?: Fields['name'];
60
- container?: Fields['container'];
61
- isHdr?: Fields['isHdr'];
62
- metadata?: Fields['metadata'];
63
- location?: Fields['location'];
49
+ export type AllOptions<Fields extends ParseMediaFields> = {
50
+ dimensions: Fields['dimensions'];
51
+ durationInSeconds: Fields['durationInSeconds'];
52
+ structure: Fields['structure'];
53
+ fps: Fields['fps'];
54
+ videoCodec: Fields['videoCodec'];
55
+ audioCodec: Fields['audioCodec'];
56
+ tracks: Fields['tracks'];
57
+ rotation: Fields['rotation'];
58
+ unrotatedDimensions: Fields['unrotatedDimensions'];
59
+ internalStats: Fields['internalStats'];
60
+ size: Fields['size'];
61
+ name: Fields['name'];
62
+ container: Fields['container'];
63
+ isHdr: Fields['isHdr'];
64
+ metadata: Fields['metadata'];
65
+ location: Fields['location'];
66
+ mimeType: Fields['mimeType'];
64
67
  };
68
+ export type Options<Fields extends ParseMediaFields> = Partial<AllOptions<Fields>>;
65
69
  export type TracksField = {
66
70
  videoTracks: VideoTrack[];
67
71
  audioTracks: AudioTrack[];
68
72
  };
69
73
  export type ParseMediaContainer = 'mp4' | 'webm' | 'avi' | 'transport-stream';
70
- export type ParseMediaCallbacks<Fields extends Options<ParseMediaFields>> = (Fields['dimensions'] extends true ? {
74
+ export interface ParseMediaCallbacks {
71
75
  onDimensions?: (dimensions: Dimensions) => void;
72
- } : {}) & (Fields['durationInSeconds'] extends true ? {
73
76
  onDurationInSeconds?: (durationInSeconds: number | null) => void;
74
- } : {}) & (Fields['structure'] extends true ? {
75
77
  onStructure?: (structure: Structure) => void;
76
- } : {}) & (Fields['fps'] extends true ? {
77
78
  onFps?: (fps: number | null) => void;
78
- } : {}) & (Fields['videoCodec'] extends true ? {
79
79
  onVideoCodec?: (codec: MediaParserVideoCodec | null) => void;
80
- } : {}) & (Fields['audioCodec'] extends true ? {
81
80
  onAudioCodec?: (codec: MediaParserAudioCodec | null) => void;
82
- } : {}) & (Fields['tracks'] extends true ? {
83
81
  onTracks?: (tracks: TracksField) => void;
84
- } : {}) & (Fields['rotation'] extends true ? {
85
82
  onRotation?: (rotation: number | null) => void;
86
- } : {}) & (Fields['metadata'] extends true ? {
87
- onMetadata?: (metadata: MetadataEntry[]) => void;
88
- } : {}) & (Fields['location'] extends true ? {
89
- onLocation?: (location: MediaParserLocation | null) => void;
90
- } : {}) & (Fields['unrotatedDimensions'] extends true ? {
91
83
  onUnrotatedDimensions?: (dimensions: Dimensions) => void;
92
- } : {}) & (Fields['isHdr'] extends true ? {
93
- onIsHdr?: (isHdr: boolean) => void;
94
- } : {}) & (Fields['size'] extends true ? {
84
+ onInternalStats?: (internalStats: InternalStats) => void;
95
85
  onSize?: (size: number | null) => void;
96
- } : {}) & (Fields['name'] extends true ? {
97
86
  onName?: (name: string) => void;
98
- } : {}) & (Fields['container'] extends true ? {
99
87
  onContainer?: (container: ParseMediaContainer) => void;
100
- } : {});
101
- export type ParseMediaResult<Fields extends Options<ParseMediaFields>> = (Fields['dimensions'] extends true ? {
88
+ onIsHdr?: (isHdr: boolean) => void;
89
+ onMetadata?: (metadata: MetadataEntry[]) => void;
90
+ onLocation?: (location: MediaParserLocation | null) => void;
91
+ onMimeType?: (mimeType: string | null) => void;
92
+ }
93
+ export interface ParseMediaData {
102
94
  dimensions: Dimensions;
103
- } : {}) & (Fields['durationInSeconds'] extends true ? {
104
95
  durationInSeconds: number | null;
105
- } : {}) & (Fields['structure'] extends true ? {
106
96
  structure: Structure;
107
- } : {}) & (Fields['fps'] extends true ? {
108
97
  fps: number | null;
109
- } : {}) & (Fields['videoCodec'] extends true ? {
110
98
  videoCodec: MediaParserVideoCodec | null;
111
- } : {}) & (Fields['audioCodec'] extends true ? {
112
99
  audioCodec: MediaParserAudioCodec | null;
113
- } : {}) & (Fields['tracks'] extends true ? TracksField : {}) & (Fields['rotation'] extends true ? {
100
+ tracks: TracksField;
114
101
  rotation: number | null;
115
- } : {}) & (Fields['unrotatedDimensions'] extends true ? {
116
102
  unrotatedDimensions: Dimensions;
117
- } : {}) & (Fields['isHdr'] extends true ? {
118
103
  isHdr: boolean;
119
- } : {}) & (Fields['internalStats'] extends true ? {
120
104
  internalStats: InternalStats;
121
- } : {}) & (Fields['size'] extends true ? {
122
105
  size: number | null;
123
- } : {}) & (Fields['name'] extends true ? {
124
106
  name: string;
125
- } : {}) & (Fields['metadata'] extends true ? {
126
107
  metadata: MetadataEntry[];
127
- } : {}) & (Fields['location'] extends true ? {
128
108
  location: MediaParserLocation | null;
129
- } : {}) & (Fields['container'] extends true ? {
130
109
  container: ParseMediaContainer;
131
- } : {});
110
+ mimeType: string | null;
111
+ }
112
+ export type ParseMediaResult<T extends Partial<ParseMediaFields>> = {
113
+ [K in keyof T]: T[K] extends true ? K extends keyof ParseMediaData ? ParseMediaData[K] : never : never;
114
+ };
132
115
  export type ParseMediaDynamicOptions<F extends Options<ParseMediaFields>> = {
133
116
  fields?: F;
134
- } & ParseMediaCallbacks<F>;
117
+ } & ParseMediaCallbacks;
135
118
  export type ParseMediaProgress = {
136
119
  bytes: number;
137
120
  percentage: number | null;
@@ -3,23 +3,48 @@ 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;
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,
19
+ });
14
20
  const state = (0, parser_state_1.makeParserState)({
15
21
  hasAudioTrackHandlers: Boolean(onAudioTrack),
16
22
  hasVideoTrackHandlers: Boolean(onVideoTrack),
17
23
  signal,
18
24
  getIterator: () => iterator,
19
- fields: fields !== null && fields !== void 0 ? fields : {},
25
+ fields,
20
26
  });
21
- const { reader, contentLength, name, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
27
+ const { reader, contentLength, name, contentType, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
22
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
+ };
23
48
  const supportsContentRange = readerSupportsContentRange &&
24
49
  !(typeof process !== 'undefined' &&
25
50
  typeof process.env !== 'undefined' &&
@@ -38,15 +63,22 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
38
63
  };
39
64
  const triggerInfoEmit = () => {
40
65
  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);
66
+ const availableInfo = (0, has_all_info_1.getAvailableInfo)({
67
+ fieldsToFetch: fields,
68
+ structure: (_a = parseResult === null || parseResult === void 0 ? void 0 : parseResult.segments) !== null && _a !== void 0 ? _a : null,
69
+ state,
70
+ });
42
71
  (0, emit_available_info_1.emitAvailableInfo)({
43
72
  hasInfo: availableInfo,
44
- moreFields,
73
+ callbacks: moreFields,
74
+ fieldsInReturnValue,
45
75
  parseResult,
46
76
  state,
47
77
  returnValue,
48
78
  contentLength,
49
79
  name,
80
+ mimeType: contentType,
81
+ emittedFields,
50
82
  });
51
83
  };
52
84
  triggerInfoEmit();
@@ -95,14 +127,17 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
95
127
  options,
96
128
  signal: signal !== null && signal !== void 0 ? signal : null,
97
129
  logLevel,
98
- fields: fields !== null && fields !== void 0 ? fields : {},
130
+ fields,
131
+ mimeType: contentType,
132
+ contentLength,
133
+ name,
99
134
  });
100
135
  }
101
136
  if (parseResult.status === 'incomplete' && parseResult.skipTo !== null) {
102
137
  state.increaseSkippedBytes(parseResult.skipTo - iterator.counter.getOffset());
103
138
  }
104
139
  if ((0, has_all_info_1.hasAllInfo)({
105
- fields: fields !== null && fields !== void 0 ? fields : {},
140
+ fields,
106
141
  structure: parseResult.segments,
107
142
  state,
108
143
  })) {
@@ -128,20 +163,24 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
128
163
  }
129
164
  }
130
165
  log_1.Log.verbose(logLevel, 'Finished parsing file');
166
+ const hasInfo = Object.keys(fields).reduce((acc, key) => {
167
+ if (fields === null || fields === void 0 ? void 0 : fields[key]) {
168
+ acc[key] = true;
169
+ }
170
+ return acc;
171
+ }, {});
131
172
  // Force assign
132
173
  (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,
174
+ hasInfo,
175
+ callbacks: moreFields,
176
+ fieldsInReturnValue,
140
177
  parseResult,
141
178
  state,
142
179
  returnValue,
143
180
  contentLength,
181
+ mimeType: contentType,
144
182
  name,
183
+ emittedFields,
145
184
  });
146
185
  currentReader.abort();
147
186
  iterator === null || iterator === void 0 ? void 0 : iterator.destroy();
@@ -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, options, signal, logLevel, fields, mimeType, contentLength, name, }: {
20
20
  iterator: BufferIterator;
21
21
  options: ParserContext;
22
22
  signal: AbortSignal | null;
23
23
  logLevel: LogLevel;
24
24
  fields: Options<ParseMediaFields>;
25
+ mimeType: string | null;
26
+ contentLength: number | null;
27
+ name: string | null;
25
28
  }) => Promise<ParseResult<Structure>>;
@@ -6,16 +6,18 @@ 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, options, 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
18
  return Promise.resolve((0, parse_box_1.parseRiff)({ iterator, options, fields }));
17
19
  }
18
- if (iterator.isIsoBaseMedia()) {
20
+ if (fileType.type === 'iso-base-media') {
19
21
  log_1.Log.verbose(logLevel, 'Detected ISO Base Media container');
20
22
  return (0, process_box_1.parseIsoBaseMediaBoxes)({
21
23
  iterator,
@@ -29,11 +31,11 @@ const parseVideo = ({ iterator, options, signal, logLevel, fields, }) => {
29
31
  fields,
30
32
  });
31
33
  }
32
- if (iterator.isWebm()) {
34
+ if (fileType.type === 'webm') {
33
35
  log_1.Log.verbose(logLevel, 'Detected Matroska container');
34
36
  return (0, parse_webm_header_1.parseWebm)({ counter: iterator, parserContext: options, fields });
35
37
  }
36
- if (iterator.isTransportStream()) {
38
+ if (fileType.type === 'transport-stream') {
37
39
  return (0, parse_transport_stream_1.parseTransportStream)({
38
40
  iterator,
39
41
  parserContext: options,
@@ -46,9 +48,70 @@ const parseVideo = ({ iterator, options, signal, logLevel, fields, }) => {
46
48
  nextPesHeaderStore: (0, next_pes_header_store_1.makeNextPesHeaderStore)(),
47
49
  });
48
50
  }
49
- if (iterator.isMp3()) {
50
- return Promise.reject(new Error('MP3 files are not yet supported'));
51
+ if (fileType.type === 'mp3') {
52
+ return Promise.reject(new errors_1.IsAnUnsupportedAudioTypeError({
53
+ message: 'MP3 files are not yet supported',
54
+ mimeType,
55
+ sizeInBytes: contentLength,
56
+ fileName: name,
57
+ audioType: 'mp3',
58
+ }));
51
59
  }
52
- return Promise.reject(new Error('Unknown video format'));
60
+ if (fileType.type === 'wav') {
61
+ return Promise.reject(new errors_1.IsAnUnsupportedAudioTypeError({
62
+ message: 'WAV files are not yet supported',
63
+ mimeType,
64
+ sizeInBytes: contentLength,
65
+ fileName: name,
66
+ audioType: 'wav',
67
+ }));
68
+ }
69
+ if (fileType.type === 'aac') {
70
+ return Promise.reject(new errors_1.IsAnUnsupportedAudioTypeError({
71
+ message: 'AAC files are not yet supported',
72
+ mimeType,
73
+ sizeInBytes: contentLength,
74
+ fileName: name,
75
+ audioType: 'aac',
76
+ }));
77
+ }
78
+ if (fileType.type === 'gif') {
79
+ return Promise.reject(new errors_1.IsAGifError({
80
+ message: 'GIF files are not yet supported',
81
+ mimeType,
82
+ sizeInBytes: contentLength,
83
+ fileName: name,
84
+ }));
85
+ }
86
+ if (fileType.type === 'pdf') {
87
+ return Promise.reject(new errors_1.IsAPdfError({
88
+ message: 'GIF files are not supported',
89
+ mimeType,
90
+ sizeInBytes: contentLength,
91
+ fileName: name,
92
+ }));
93
+ }
94
+ if (fileType.type === 'bmp' ||
95
+ fileType.type === 'jpeg' ||
96
+ fileType.type === 'png' ||
97
+ fileType.type === 'webp') {
98
+ return Promise.reject(new errors_1.IsAnImageError({
99
+ message: 'Image files are not supported',
100
+ imageType: fileType.type,
101
+ dimensions: fileType.dimensions,
102
+ mimeType,
103
+ sizeInBytes: contentLength,
104
+ fileName: name,
105
+ }));
106
+ }
107
+ if (fileType.type === 'unknown') {
108
+ return Promise.reject(new errors_1.IsAnUnsupportedFileTypeError({
109
+ message: 'Unknown file format',
110
+ mimeType,
111
+ sizeInBytes: contentLength,
112
+ fileName: name,
113
+ }));
114
+ }
115
+ return Promise.reject(new Error('Unknown video format ' + fileType));
53
116
  };
54
117
  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
  };
@@ -18,6 +18,7 @@ const needsTracksField = {
18
18
  videoCodec: true,
19
19
  metadata: true,
20
20
  location: true,
21
+ mimeType: false,
21
22
  };
22
23
  const makeCanSkipTracksState = ({ hasAudioTrackHandlers, fields, hasVideoTrackHandlers, }) => {
23
24
  return {
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "4.0.240";
1
+ export declare const VERSION = "4.0.241";
package/dist/version.js CHANGED
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Automatically generated on publish
5
- exports.VERSION = '4.0.240';
5
+ exports.VERSION = '4.0.241';
package/package.json CHANGED
@@ -3,14 +3,14 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-parser"
4
4
  },
5
5
  "name": "@remotion/media-parser",
6
- "version": "4.0.240",
6
+ "version": "4.0.241",
7
7
  "main": "dist/index.js",
8
8
  "sideEffects": false,
9
9
  "devDependencies": {
10
10
  "@types/wicg-file-system-access": "2023.10.5",
11
11
  "eslint": "9.14.0",
12
- "@remotion/example-videos": "4.0.240",
13
- "@remotion/eslint-config-internal": "4.0.240"
12
+ "@remotion/example-videos": "4.0.241",
13
+ "@remotion/eslint-config-internal": "4.0.241"
14
14
  },
15
15
  "publishConfig": {
16
16
  "access": "public"