@remotion/media-parser 4.0.237 → 4.0.240

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 (111) hide show
  1. package/dist/aac-codecprivate.d.ts +2 -9
  2. package/dist/aac-codecprivate.js +69 -34
  3. package/dist/add-avc-profile-to-track.js +4 -23
  4. package/dist/boxes/avc/codec-private.d.ts +2 -0
  5. package/dist/boxes/avc/codec-private.js +28 -0
  6. package/dist/boxes/avc/codec-string.d.ts +2 -0
  7. package/dist/boxes/avc/codec-string.js +7 -0
  8. package/dist/boxes/avc/color.d.ts +6 -0
  9. package/dist/boxes/avc/color.js +39 -0
  10. package/dist/boxes/avc/interpret-sps.d.ts +11 -0
  11. package/dist/boxes/avc/interpret-sps.js +44 -0
  12. package/dist/boxes/avc/key.d.ts +2 -0
  13. package/dist/boxes/avc/key.js +11 -0
  14. package/dist/boxes/avc/parse-avc.d.ts +36 -3
  15. package/dist/boxes/avc/parse-avc.js +161 -4
  16. package/dist/boxes/avc/sps-and-pps.d.ts +3 -0
  17. package/dist/boxes/avc/sps-and-pps.js +12 -0
  18. package/dist/boxes/iso-base-media/get-video-codec-from-iso-track.d.ts +2 -0
  19. package/dist/boxes/iso-base-media/get-video-codec-from-iso-track.js +55 -0
  20. package/dist/boxes/iso-base-media/make-track.js +2 -1
  21. package/dist/boxes/iso-base-media/mdat/mdat.js +8 -14
  22. package/dist/boxes/iso-base-media/process-box.js +1 -1
  23. package/dist/boxes/riff/parse-box.js +2 -2
  24. package/dist/boxes/riff/parse-movi.js +12 -14
  25. package/dist/boxes/transport-stream/adts-header.d.ts +7 -0
  26. package/dist/boxes/transport-stream/adts-header.js +56 -0
  27. package/dist/boxes/transport-stream/boxes.d.ts +41 -0
  28. package/dist/boxes/transport-stream/boxes.js +2 -0
  29. package/dist/boxes/transport-stream/discard-rest-of-packet.d.ts +3 -0
  30. package/dist/boxes/transport-stream/discard-rest-of-packet.js +13 -0
  31. package/dist/boxes/transport-stream/find-separator.d.ts +2 -0
  32. package/dist/boxes/transport-stream/find-separator.js +30 -0
  33. package/dist/boxes/transport-stream/get-tracks.d.ts +5 -0
  34. package/dist/boxes/transport-stream/get-tracks.js +33 -0
  35. package/dist/boxes/transport-stream/handle-aac-packet.d.ts +7 -0
  36. package/dist/boxes/transport-stream/handle-aac-packet.js +50 -0
  37. package/dist/boxes/transport-stream/handle-avc-packet.d.ts +8 -0
  38. package/dist/boxes/transport-stream/handle-avc-packet.js +60 -0
  39. package/dist/boxes/transport-stream/next-pes-header-store.d.ts +6 -0
  40. package/dist/boxes/transport-stream/next-pes-header-store.js +18 -0
  41. package/dist/boxes/transport-stream/parse-packet.d.ts +13 -0
  42. package/dist/boxes/transport-stream/parse-packet.js +80 -0
  43. package/dist/boxes/transport-stream/parse-pat.d.ts +8 -0
  44. package/dist/boxes/transport-stream/parse-pat.js +49 -0
  45. package/dist/boxes/transport-stream/parse-pes.d.ts +8 -0
  46. package/dist/boxes/transport-stream/parse-pes.js +76 -0
  47. package/dist/boxes/transport-stream/parse-pmt.d.ts +11 -0
  48. package/dist/boxes/transport-stream/parse-pmt.js +64 -0
  49. package/dist/boxes/transport-stream/parse-stream-packet.d.ts +15 -0
  50. package/dist/boxes/transport-stream/parse-stream-packet.js +107 -0
  51. package/dist/boxes/transport-stream/parse-transport-stream.d.ts +14 -0
  52. package/dist/boxes/transport-stream/parse-transport-stream.js +72 -0
  53. package/dist/boxes/transport-stream/process-stream-buffers.d.ts +19 -0
  54. package/dist/boxes/transport-stream/process-stream-buffers.js +42 -0
  55. package/dist/boxes/transport-stream/traversal.d.ts +6 -0
  56. package/dist/boxes/transport-stream/traversal.js +30 -0
  57. package/dist/boxes/webm/ebml.d.ts +1 -1
  58. package/dist/boxes/webm/parse-ebml.js +1 -1
  59. package/dist/buffer-iterator.d.ts +2 -0
  60. package/dist/buffer-iterator.js +25 -0
  61. package/dist/convert-audio-or-video-sample.d.ts +2 -0
  62. package/dist/convert-audio-or-video-sample.js +17 -0
  63. package/dist/create/iso-base-media/create-iso-base-media.js +38 -19
  64. package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.js +7 -1
  65. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.js +3 -0
  66. package/dist/create/media-fn.d.ts +0 -1
  67. package/dist/create/progress-tracker.d.ts +2 -0
  68. package/dist/create/progress-tracker.js +32 -8
  69. package/dist/emit-available-info.js +13 -2
  70. package/dist/esm/index.mjs +1325 -247
  71. package/dist/get-container.d.ts +1 -1
  72. package/dist/get-container.js +3 -0
  73. package/dist/get-duration.js +4 -1
  74. package/dist/get-fps.js +8 -2
  75. package/dist/get-location.d.ts +13 -0
  76. package/dist/get-location.js +40 -0
  77. package/dist/get-tracks.d.ts +4 -3
  78. package/dist/get-tracks.js +9 -2
  79. package/dist/get-video-codec.d.ts +1 -2
  80. package/dist/get-video-codec.js +9 -148
  81. package/dist/has-all-info.js +1 -1
  82. package/dist/index.d.ts +3 -0
  83. package/dist/metadata/get-metadata.js +3 -0
  84. package/dist/options.d.ts +11 -3
  85. package/dist/parse-media.js +3 -3
  86. package/dist/parse-result.d.ts +7 -2
  87. package/dist/parse-video.js +15 -0
  88. package/dist/register-track.d.ts +5 -5
  89. package/dist/register-track.js +16 -10
  90. package/dist/state/can-skip-tracks.js +1 -0
  91. package/dist/state/has-tracks-section.d.ts +3 -0
  92. package/dist/state/has-tracks-section.js +5 -0
  93. package/dist/state/parser-state.d.ts +2 -0
  94. package/dist/version.d.ts +1 -1
  95. package/dist/version.js +1 -1
  96. package/dist/webcodec-sample-types.d.ts +9 -2
  97. package/package.json +3 -3
  98. package/dist/add-new-matroska-tracks.d.ts +0 -13
  99. package/dist/add-new-matroska-tracks.js +0 -29
  100. package/dist/boxes/iso-base-media/meta/keys.d.ts +0 -10
  101. package/dist/boxes/iso-base-media/meta/keys.js +0 -17
  102. package/dist/boxes/iso-base-media/meta/list.d.ts +0 -12
  103. package/dist/boxes/iso-base-media/meta/list.js +0 -33
  104. package/dist/boxes/riff/strf.d.ts +0 -7
  105. package/dist/boxes/riff/strf.js +0 -67
  106. package/dist/create/mp3/create-mp3.d.ts +0 -2
  107. package/dist/create/mp3/create-mp3.js +0 -49
  108. package/dist/get-metadata.d.ts +0 -7
  109. package/dist/get-metadata.js +0 -63
  110. package/dist/parser-state.d.ts +0 -33
  111. package/dist/parser-state.js +0 -162
@@ -6,6 +6,7 @@ const log_1 = require("../../log");
6
6
  const create_ftyp_1 = require("./create-ftyp");
7
7
  const mp4_header_1 = require("./mp4-header");
8
8
  const primitives_1 = require("./primitives");
9
+ const CONTAINER_TIMESCALE = 1000;
9
10
  const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, }) => {
10
11
  const header = (0, create_ftyp_1.createIsoBaseMediaFtyp)({
11
12
  compatibleBrands: ['isom', 'iso2', 'avc1', 'mp42'],
@@ -14,24 +15,26 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
14
15
  });
15
16
  const w = await writer.createContent({ filename, mimeType: 'video/mp4' });
16
17
  await w.write(header);
17
- let durationInUnits = 0;
18
+ let globalDurationInUnits = 0;
19
+ const lowestTrackTimestamps = {};
20
+ const trackDurations = {};
18
21
  const currentTracks = [];
19
22
  const samplePositions = [];
20
23
  const sampleChunkIndices = [];
21
24
  const moovOffset = w.getWrittenByteCount();
22
25
  const getPaddedMoovAtom = () => {
23
26
  return (0, mp4_header_1.createPaddedMoovAtom)({
24
- durationInUnits,
27
+ durationInUnits: globalDurationInUnits,
25
28
  trackInfo: currentTracks.map((track) => {
26
- var _a;
29
+ var _a, _b;
27
30
  return {
28
31
  track,
29
- durationInUnits,
30
- samplePositions: (_a = samplePositions[track.trackNumber]) !== null && _a !== void 0 ? _a : [],
32
+ durationInUnits: (_a = trackDurations[track.trackNumber]) !== null && _a !== void 0 ? _a : 0,
33
+ samplePositions: (_b = samplePositions[track.trackNumber]) !== null && _b !== void 0 ? _b : [],
31
34
  timescale: track.timescale,
32
35
  };
33
36
  }),
34
- timescale: 1000,
37
+ timescale: CONTAINER_TIMESCALE,
35
38
  });
36
39
  };
37
40
  await w.write(getPaddedMoovAtom());
@@ -52,10 +55,6 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
52
55
  await w.updateDataAt(moovOffset, getPaddedMoovAtom());
53
56
  onBytesProgress(w.getWrittenByteCount());
54
57
  };
55
- const updateDuration = (newDuration) => {
56
- durationInUnits = newDuration;
57
- onMillisecondsProgress(newDuration);
58
- };
59
58
  const addCodecPrivateToTrack = ({ trackNumber, codecPrivate, }) => {
60
59
  currentTracks.forEach((track) => {
61
60
  if (track.trackNumber === trackNumber) {
@@ -64,18 +63,39 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
64
63
  });
65
64
  };
66
65
  let lastChunkWasVideo = false;
67
- const addSample = async ({ chunk, trackNumber, isVideo, timescale, codecPrivate, }) => {
68
- var _a, _b;
66
+ const addSample = async ({ chunk, trackNumber, isVideo, codecPrivate, }) => {
67
+ var _a, _b, _c, _d;
69
68
  const position = w.getWrittenByteCount();
70
69
  await w.write(chunk.data);
71
70
  mdatSize += chunk.data.length;
72
71
  onBytesProgress(w.getWrittenByteCount());
72
+ progressTracker.setPossibleLowestTimestamp(Math.min(chunk.timestamp, (_a = chunk.cts) !== null && _a !== void 0 ? _a : Infinity, (_b = chunk.dts) !== null && _b !== void 0 ? _b : Infinity));
73
73
  progressTracker.updateTrackProgress(trackNumber, chunk.timestamp);
74
74
  if (codecPrivate) {
75
75
  addCodecPrivateToTrack({ trackNumber, codecPrivate });
76
76
  }
77
- const newDuration = Math.round((chunk.timestamp + ((_a = chunk.duration) !== null && _a !== void 0 ? _a : 0)) / 1000);
78
- updateDuration(newDuration);
77
+ const currentTrack = currentTracks.find((t) => t.trackNumber === trackNumber);
78
+ if (!currentTrack) {
79
+ throw new Error(`Tried to add sample to track ${trackNumber}, but it doesn't exist`);
80
+ }
81
+ if (!lowestTrackTimestamps[trackNumber] ||
82
+ chunk.timestamp < lowestTrackTimestamps[trackNumber]) {
83
+ lowestTrackTimestamps[trackNumber] = chunk.timestamp;
84
+ }
85
+ if (typeof lowestTrackTimestamps[trackNumber] !== 'number') {
86
+ throw new Error(`Tried to add sample to track ${trackNumber}, but it has no timestamp`);
87
+ }
88
+ const newDurationInMicroSeconds = chunk.timestamp +
89
+ ((_c = chunk.duration) !== null && _c !== void 0 ? _c : 0) -
90
+ lowestTrackTimestamps[trackNumber];
91
+ const newDurationInTrackTimeUnits = Math.round(newDurationInMicroSeconds / (1000000 / currentTrack.timescale));
92
+ trackDurations[trackNumber] = newDurationInTrackTimeUnits;
93
+ // webcodecs returns frame duration in microseconds
94
+ const newDurationInMilliseconds = Math.round((newDurationInMicroSeconds / 1000000) * CONTAINER_TIMESCALE);
95
+ if (newDurationInMilliseconds > globalDurationInUnits) {
96
+ globalDurationInUnits = newDurationInMilliseconds;
97
+ onMillisecondsProgress(newDurationInMilliseconds);
98
+ }
79
99
  if (!samplePositions[trackNumber]) {
80
100
  samplePositions[trackNumber] = [];
81
101
  }
@@ -99,9 +119,9 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
99
119
  isKeyframe: chunk.type === 'key',
100
120
  offset: position,
101
121
  chunk: sampleChunkIndices[trackNumber],
102
- cts: Math.round(chunk.cts / (1000000 / timescale)),
103
- dts: Math.round(chunk.dts / (1000000 / timescale)),
104
- duration: Math.round(((_b = chunk.duration) !== null && _b !== void 0 ? _b : 0) / (1000000 / timescale)),
122
+ cts: Math.round((chunk.cts / 1000000) * currentTrack.timescale),
123
+ dts: Math.round((chunk.dts / 1000000) * currentTrack.timescale),
124
+ duration: Math.round((((_d = chunk.duration) !== null && _d !== void 0 ? _d : 0) / 1000000) * currentTrack.timescale),
105
125
  size: chunk.data.length,
106
126
  };
107
127
  lastChunkWasVideo = isVideo;
@@ -121,13 +141,12 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
121
141
  remove: async () => {
122
142
  await w.remove();
123
143
  },
124
- addSample: ({ chunk, trackNumber, isVideo, timescale, codecPrivate }) => {
144
+ addSample: ({ chunk, trackNumber, isVideo, codecPrivate }) => {
125
145
  operationProm.current = operationProm.current.then(() => {
126
146
  return addSample({
127
147
  chunk,
128
148
  trackNumber,
129
149
  isVideo,
130
- timescale,
131
150
  codecPrivate,
132
151
  });
133
152
  });
@@ -12,10 +12,16 @@ const create_stsz_1 = require("./stbl/create-stsz");
12
12
  const create_stts_1 = require("./stbl/create-stts");
13
13
  const create_avc1_1 = require("./stbl/stsd/create-avc1");
14
14
  const createStbl = ({ samplePositions, codecSpecificData, isVideo, }) => {
15
+ // For stts:
16
+ // https://developer.apple.com/documentation/quicktime-file-format/time-to-sample_atom
17
+ // The sample entries are ordered by time stamps; therefore, the deltas are all nonnegative.
18
+ // For the other tables, there doesn't seem to be a requirement for them to be sorted
19
+ // -> ordering the sample positions by dts
20
+ const sorted = samplePositions.slice().sort((a, b) => a.dts - b.dts);
15
21
  return (0, primitives_1.addSize)((0, make_header_1.combineUint8Arrays)([
16
22
  (0, primitives_1.stringsToUint8Array)('stbl'),
17
23
  (0, create_avc1_1.createStsdData)(codecSpecificData),
18
- (0, create_stts_1.createSttsAtom)(samplePositions),
24
+ (0, create_stts_1.createSttsAtom)(sorted),
19
25
  isVideo ? (0, create_stss_1.createStss)(samplePositions) : null,
20
26
  (0, create_ctts_1.createCttsBox)(samplePositions),
21
27
  (0, create_stsc_1.createStsc)(samplePositions),
@@ -4,6 +4,9 @@ exports.createSttsAtom = void 0;
4
4
  const make_header_1 = require("../../../../../../boxes/webm/make-header");
5
5
  const primitives_1 = require("../../../../primitives");
6
6
  const makeEntry = (entry) => {
7
+ if (entry.sampleOffset < 0) {
8
+ throw new Error('negative sample offset in stts ' + entry.sampleOffset);
9
+ }
7
10
  return (0, make_header_1.combineUint8Arrays)([
8
11
  (0, primitives_1.numberTo32BitUIntOrInt)(entry.sampleCount),
9
12
  (0, primitives_1.numberTo32BitUIntOrInt)(entry.sampleOffset),
@@ -10,7 +10,6 @@ export type MediaFn = {
10
10
  chunk: AudioOrVideoSample;
11
11
  trackNumber: number;
12
12
  isVideo: boolean;
13
- timescale: number;
14
13
  codecPrivate: Uint8Array | null;
15
14
  }) => Promise<void>;
16
15
  addTrack: (track: Omit<MakeTrackAudio, 'trackNumber'> | Omit<MakeTrackVideo, 'trackNumber'>) => Promise<{
@@ -3,5 +3,7 @@ export declare const makeProgressTracker: () => {
3
3
  getSmallestProgress: () => number;
4
4
  updateTrackProgress: (trackNumber: number, progress: number) => void;
5
5
  waitForProgress: () => Promise<void>;
6
+ getStartingTimestamp: () => number;
7
+ setPossibleLowestTimestamp: (timestamp: number) => void;
6
8
  };
7
9
  export type ProgressTracker = ReturnType<typeof makeProgressTracker>;
@@ -3,23 +3,45 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.makeProgressTracker = void 0;
4
4
  const event_emitter_1 = require("./event-emitter");
5
5
  const with_resolvers_1 = require("./with-resolvers");
6
+ // Make sure to distinguish null and undefined here
6
7
  const makeProgressTracker = () => {
7
8
  const trackNumberProgresses = {};
8
9
  const eventEmitter = new event_emitter_1.IoEventEmitter();
9
- const calculateSmallestProgress = () => {
10
- const progressValues = Object.values(trackNumberProgresses);
11
- if (progressValues.length === 0) {
12
- return 0;
10
+ let startingTimestamp = null;
11
+ const setPossibleLowestTimestamp = (timestamp) => {
12
+ if (startingTimestamp === null) {
13
+ startingTimestamp = timestamp;
14
+ }
15
+ else {
16
+ startingTimestamp = Math.min(startingTimestamp, timestamp);
13
17
  }
18
+ };
19
+ const getStartingTimestamp = () => {
20
+ if (startingTimestamp === null) {
21
+ throw new Error('No starting timestamp');
22
+ }
23
+ return startingTimestamp;
24
+ };
25
+ const calculateSmallestProgress = () => {
26
+ const progressValues = Object.values(trackNumberProgresses).map((p) => {
27
+ if (p !== null) {
28
+ return p;
29
+ }
30
+ // The starting timestamp might not be 0, it might be very huge
31
+ // If no sample has arrived yet, we should assume the smallest value
32
+ // we know as the progress
33
+ if (startingTimestamp === null) {
34
+ throw new Error('No progress values to calculate smallest progress from');
35
+ }
36
+ return startingTimestamp;
37
+ });
14
38
  return Math.min(...progressValues);
15
39
  };
16
40
  return {
17
41
  registerTrack: (trackNumber) => {
18
- trackNumberProgresses[trackNumber] = 0;
19
- },
20
- getSmallestProgress: () => {
21
- return calculateSmallestProgress();
42
+ trackNumberProgresses[trackNumber] = null;
22
43
  },
44
+ getSmallestProgress: calculateSmallestProgress,
23
45
  updateTrackProgress: (trackNumber, progress) => {
24
46
  if (trackNumberProgresses[trackNumber] === undefined) {
25
47
  throw new Error(`Tried to update progress for a track that was not registered: ${trackNumber}`);
@@ -38,6 +60,8 @@ const makeProgressTracker = () => {
38
60
  eventEmitter.addEventListener('processed', on);
39
61
  return promise;
40
62
  },
63
+ getStartingTimestamp,
64
+ setPossibleLowestTimestamp,
41
65
  };
42
66
  };
43
67
  exports.makeProgressTracker = makeProgressTracker;
@@ -7,11 +7,12 @@ 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_location_1 = require("./get-location");
10
11
  const get_tracks_1 = require("./get-tracks");
11
12
  const get_video_codec_1 = require("./get-video-codec");
12
13
  const get_metadata_1 = require("./metadata/get-metadata");
13
14
  const emitAvailableInfo = ({ hasInfo, parseResult, moreFields, state, returnValue, contentLength, name, }) => {
14
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
15
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
15
16
  const keys = Object.keys(hasInfo);
16
17
  for (const key of keys) {
17
18
  if (key === 'structure') {
@@ -84,7 +85,7 @@ const emitAvailableInfo = ({ hasInfo, parseResult, moreFields, state, returnValu
84
85
  if (returnValue.videoCodec === undefined &&
85
86
  hasInfo.videoCodec &&
86
87
  parseResult) {
87
- const videoCodec = (0, get_video_codec_1.getVideoCodec)(parseResult.segments);
88
+ const videoCodec = (0, get_video_codec_1.getVideoCodec)(parseResult.segments, state);
88
89
  (_g = moreFields.onVideoCodec) === null || _g === void 0 ? void 0 : _g.call(moreFields, videoCodec);
89
90
  returnValue.videoCodec = videoCodec;
90
91
  }
@@ -162,6 +163,16 @@ const emitAvailableInfo = ({ hasInfo, parseResult, moreFields, state, returnValu
162
163
  }
163
164
  continue;
164
165
  }
166
+ if (key === 'location') {
167
+ if (returnValue.location === undefined &&
168
+ hasInfo.location &&
169
+ parseResult) {
170
+ const location = (0, get_location_1.getLocation)(parseResult.segments);
171
+ (_q = moreFields.onLocation) === null || _q === void 0 ? void 0 : _q.call(moreFields, location);
172
+ returnValue.location = location;
173
+ }
174
+ continue;
175
+ }
165
176
  throw new Error(`Unhandled key: ${key}`);
166
177
  }
167
178
  };