@remotion/media-parser 4.0.326 → 4.0.329

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 (32) hide show
  1. package/dist/containers/aac/parse-aac.js +1 -0
  2. package/dist/containers/flac/parse-streaminfo.js +1 -0
  3. package/dist/containers/iso-base-media/make-track.js +12 -1
  4. package/dist/containers/iso-base-media/mdat/calculate-jump-marks.d.ts +6 -1
  5. package/dist/containers/iso-base-media/mdat/calculate-jump-marks.js +17 -20
  6. package/dist/containers/iso-base-media/mdat/get-editlist.d.ts +3 -0
  7. package/dist/containers/iso-base-media/mdat/get-editlist.js +18 -1
  8. package/dist/containers/iso-base-media/mdat/mdat.js +24 -13
  9. package/dist/containers/mp3/parse-mpeg-header.js +1 -0
  10. package/dist/containers/riff/get-tracks-from-avi.js +2 -0
  11. package/dist/containers/transport-stream/handle-aac-packet.js +1 -0
  12. package/dist/containers/transport-stream/handle-avc-packet.js +1 -0
  13. package/dist/containers/wav/parse-fmt.js +1 -0
  14. package/dist/containers/webm/make-track.js +2 -0
  15. package/dist/esm/index.mjs +120 -49
  16. package/dist/esm/worker-server-entry.mjs +140 -69
  17. package/dist/esm/worker-web-entry.mjs +140 -69
  18. package/dist/get-tracks.d.ts +3 -0
  19. package/dist/index.d.ts +3 -2
  20. package/dist/normalize-video-rotation.d.ts +1 -0
  21. package/dist/normalize-video-rotation.js +7 -0
  22. package/dist/parse-loop.js +2 -0
  23. package/dist/print-timings.js +1 -0
  24. package/dist/state/iso-base-media/cached-sample-positions.d.ts +6 -5
  25. package/dist/state/iso-base-media/cached-sample-positions.js +14 -7
  26. package/dist/state/iso-base-media/iso-state.d.ts +2 -2
  27. package/dist/state/parser-state.d.ts +3 -2
  28. package/dist/state/timings.d.ts +1 -0
  29. package/dist/state/timings.js +1 -0
  30. package/dist/version.d.ts +1 -1
  31. package/dist/version.js +1 -1
  32. package/package.json +4 -3
@@ -65,6 +65,7 @@ const parseAac = async (state) => {
65
65
  type: 'audio',
66
66
  startInSeconds: 0,
67
67
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
68
+ trackMediaTimeOffsetInTrackTimescale: 0,
68
69
  },
69
70
  registerAudioSampleCallback: state.callbacks.registerAudioSampleCallback,
70
71
  tracks: state.callbacks.tracks,
@@ -46,6 +46,7 @@ const parseStreamInfo = async ({ iterator, state, }) => {
46
46
  trackId: 0,
47
47
  startInSeconds: 0,
48
48
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
49
+ trackMediaTimeOffsetInTrackTimescale: 0,
49
50
  },
50
51
  registerAudioSampleCallback: state.callbacks.registerAudioSampleCallback,
51
52
  tracks: state.callbacks.tracks,
@@ -5,10 +5,12 @@ const get_audio_codec_1 = require("../../get-audio-codec");
5
5
  const get_fps_1 = require("../../get-fps");
6
6
  const get_sample_aspect_ratio_1 = require("../../get-sample-aspect-ratio");
7
7
  const get_video_codec_1 = require("../../get-video-codec");
8
+ const normalize_video_rotation_1 = require("../../normalize-video-rotation");
8
9
  const webcodecs_timescale_1 = require("../../webcodecs-timescale");
9
10
  const color_to_webcodecs_colors_1 = require("./color-to-webcodecs-colors");
10
11
  const get_actual_number_of_channels_1 = require("./get-actual-number-of-channels");
11
12
  const get_video_codec_from_iso_track_1 = require("./get-video-codec-from-iso-track");
13
+ const get_editlist_1 = require("./mdat/get-editlist");
12
14
  const traversal_1 = require("./traversal");
13
15
  const makeBaseMediaTrack = (trakBox, startTimeInSeconds) => {
14
16
  var _a, _b, _c, _d, _e;
@@ -51,6 +53,9 @@ const makeBaseMediaTrack = (trakBox, startTimeInSeconds) => {
51
53
  codecEnum,
52
54
  startInSeconds: startTimeInSeconds,
53
55
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
56
+ trackMediaTimeOffsetInTrackTimescale: (0, get_editlist_1.findTrackMediaTimeOffsetInTrackTimescale)({
57
+ trakBox,
58
+ }),
54
59
  };
55
60
  }
56
61
  if (!(0, get_fps_1.trakBoxContainsVideo)(trakBox)) {
@@ -61,6 +66,9 @@ const makeBaseMediaTrack = (trakBox, startTimeInSeconds) => {
61
66
  trakBox,
62
67
  startInSeconds: startTimeInSeconds,
63
68
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
69
+ trackMediaTimeOffsetInTrackTimescale: (0, get_editlist_1.findTrackMediaTimeOffsetInTrackTimescale)({
70
+ trakBox,
71
+ }),
64
72
  };
65
73
  }
66
74
  const videoSample = (0, get_sample_aspect_ratio_1.getStsdVideoConfig)(trakBox);
@@ -103,7 +111,7 @@ const makeBaseMediaTrack = (trakBox, startTimeInSeconds) => {
103
111
  // Repeating those keys because they get picked up by VideoDecoder
104
112
  displayAspectWidth,
105
113
  displayAspectHeight,
106
- rotation,
114
+ rotation: (0, normalize_video_rotation_1.normalizeVideoRotation)(0 - rotation),
107
115
  codecData: privateData,
108
116
  colorSpace: (0, color_to_webcodecs_colors_1.mediaParserAdvancedColorToWebCodecsColor)(advancedColor),
109
117
  advancedColor,
@@ -111,6 +119,9 @@ const makeBaseMediaTrack = (trakBox, startTimeInSeconds) => {
111
119
  fps: (0, get_fps_1.getFpsFromMp4TrakBox)(trakBox),
112
120
  startInSeconds: startTimeInSeconds,
113
121
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
122
+ trackMediaTimeOffsetInTrackTimescale: (0, get_editlist_1.findTrackMediaTimeOffsetInTrackTimescale)({
123
+ trakBox,
124
+ }),
114
125
  };
115
126
  return track;
116
127
  };
@@ -3,4 +3,9 @@ export type JumpMark = {
3
3
  afterSampleWithOffset: number;
4
4
  jumpToOffset: number;
5
5
  };
6
- export declare const calculateJumpMarks: (samplePositionTracks: MinimalFlatSampleForTesting[][], endOfMdat: number) => JumpMark[];
6
+ export declare const calculateJumpMarks: ({ sampleMap, offsetsSorted, trackIds, endOfMdat, }: {
7
+ sampleMap: Map<number, MinimalFlatSampleForTesting>;
8
+ offsetsSorted: number[];
9
+ trackIds: number[];
10
+ endOfMdat: number;
11
+ }) => JumpMark[];
@@ -15,30 +15,27 @@ const MAX_SPREAD_IN_SECONDS = 8;
15
15
  const getKey = (samplePositionTrack) => {
16
16
  return `${samplePositionTrack.track.trackId}-${samplePositionTrack.samplePosition.decodingTimestamp}`;
17
17
  };
18
- const findBestJump = ({ allSamplesSortedByOffset, visited, progresses, }) => {
18
+ const findBestJump = ({ sampleMap, offsetsSorted, visited, progresses, }) => {
19
19
  var _a;
20
20
  const minProgress = Math.min(...Object.values(progresses));
21
21
  const trackNumberWithLowestProgress = (_a = Object.entries(progresses).find(([, progress]) => progress === minProgress)) === null || _a === void 0 ? void 0 : _a[0];
22
- const firstSampleAboveMinProgress = allSamplesSortedByOffset.findIndex((sample) => sample.track.trackId === Number(trackNumberWithLowestProgress) &&
23
- !visited.has(getKey(sample)));
22
+ const firstSampleAboveMinProgress = offsetsSorted.findIndex((offset) => sampleMap.get(offset).track.trackId ===
23
+ Number(trackNumberWithLowestProgress) &&
24
+ !visited.has(getKey(sampleMap.get(offset))));
24
25
  return firstSampleAboveMinProgress;
25
26
  };
26
- const calculateJumpMarks = (samplePositionTracks, endOfMdat) => {
27
+ const calculateJumpMarks = ({ sampleMap, offsetsSorted, trackIds, endOfMdat, }) => {
27
28
  const progresses = {};
28
- for (const track of samplePositionTracks) {
29
- progresses[track[0].track.trackId] = 0;
29
+ for (const trackId of trackIds) {
30
+ progresses[trackId] = 0;
30
31
  }
31
32
  const jumpMarks = [];
32
- const allSamplesSortedByOffset = samplePositionTracks
33
- .flat(1)
34
- .filter((s) => s.track.type === 'audio' || s.track.type === 'video')
35
- .sort((a, b) => a.samplePosition.offset - b.samplePosition.offset);
36
33
  let indexToVisit = 0;
37
34
  const visited = new Set();
38
35
  let rollOverToProcess = false;
39
36
  const increaseIndex = () => {
40
37
  indexToVisit++;
41
- if (indexToVisit >= allSamplesSortedByOffset.length) {
38
+ if (indexToVisit >= offsetsSorted.length) {
42
39
  rollOverToProcess = true;
43
40
  indexToVisit = 0;
44
41
  }
@@ -50,24 +47,24 @@ const calculateJumpMarks = (samplePositionTracks, endOfMdat) => {
50
47
  }
51
48
  const jumpMark = {
52
49
  afterSampleWithOffset: lastVisitedSample.samplePosition.offset,
53
- jumpToOffset: allSamplesSortedByOffset[firstSampleAboveMinProgress].samplePosition
54
- .offset,
50
+ jumpToOffset: offsetsSorted[firstSampleAboveMinProgress],
55
51
  };
56
52
  indexToVisit = firstSampleAboveMinProgress;
57
53
  jumpMarks.push(jumpMark);
58
54
  };
59
55
  const addFinalJumpIfNecessary = () => {
60
- if (indexToVisit === allSamplesSortedByOffset.length - 1) {
56
+ if (indexToVisit === offsetsSorted.length - 1) {
61
57
  return;
62
58
  }
63
59
  jumpMarks.push({
64
- afterSampleWithOffset: allSamplesSortedByOffset[indexToVisit].samplePosition.offset,
60
+ afterSampleWithOffset: offsetsSorted[indexToVisit],
65
61
  jumpToOffset: endOfMdat,
66
62
  });
67
63
  };
68
64
  const considerJump = () => {
69
65
  const firstSampleAboveMinProgress = findBestJump({
70
- allSamplesSortedByOffset,
66
+ sampleMap,
67
+ offsetsSorted,
71
68
  visited,
72
69
  progresses,
73
70
  });
@@ -79,14 +76,14 @@ const calculateJumpMarks = (samplePositionTracks, endOfMdat) => {
79
76
  else {
80
77
  while (true) {
81
78
  increaseIndex();
82
- if (!visited.has(getKey(allSamplesSortedByOffset[indexToVisit]))) {
79
+ if (!visited.has(getKey(sampleMap.get(offsetsSorted[indexToVisit])))) {
83
80
  break;
84
81
  }
85
82
  }
86
83
  }
87
84
  };
88
85
  while (true) {
89
- const currentSamplePosition = allSamplesSortedByOffset[indexToVisit];
86
+ const currentSamplePosition = sampleMap.get(offsetsSorted[indexToVisit]);
90
87
  const sampleKey = getKey(currentSamplePosition);
91
88
  if (visited.has(sampleKey)) {
92
89
  considerJump();
@@ -104,7 +101,7 @@ const calculateJumpMarks = (samplePositionTracks, endOfMdat) => {
104
101
  rollOverToProcess = false;
105
102
  }
106
103
  lastVisitedSample = currentSamplePosition;
107
- if (visited.size === allSamplesSortedByOffset.length) {
104
+ if (visited.size === offsetsSorted.length) {
108
105
  addFinalJumpIfNecessary();
109
106
  break;
110
107
  }
@@ -115,7 +112,7 @@ const calculateJumpMarks = (samplePositionTracks, endOfMdat) => {
115
112
  const maxProgress = Math.max(...progressValues);
116
113
  const minProgress = Math.min(...progressValues);
117
114
  const spread = maxProgress - minProgress;
118
- if (visited.size === allSamplesSortedByOffset.length) {
115
+ if (visited.size === offsetsSorted.length) {
119
116
  addFinalJumpIfNecessary();
120
117
  break;
121
118
  }
@@ -3,3 +3,6 @@ export declare const findTrackStartTimeInSeconds: ({ movieTimeScale, trakBox, }:
3
3
  movieTimeScale: number;
4
4
  trakBox: TrakBox;
5
5
  }) => number;
6
+ export declare const findTrackMediaTimeOffsetInTrackTimescale: ({ trakBox, }: {
7
+ trakBox: TrakBox;
8
+ }) => number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findTrackStartTimeInSeconds = void 0;
3
+ exports.findTrackMediaTimeOffsetInTrackTimescale = exports.findTrackStartTimeInSeconds = void 0;
4
4
  const traversal_1 = require("../traversal");
5
5
  const findTrackStartTimeInSeconds = ({ movieTimeScale, trakBox, }) => {
6
6
  const elstBox = (0, traversal_1.getElstBox)(trakBox);
@@ -19,3 +19,20 @@ const findTrackStartTimeInSeconds = ({ movieTimeScale, trakBox, }) => {
19
19
  return dwellTime / movieTimeScale;
20
20
  };
21
21
  exports.findTrackStartTimeInSeconds = findTrackStartTimeInSeconds;
22
+ const findTrackMediaTimeOffsetInTrackTimescale = ({ trakBox, }) => {
23
+ const elstBox = (0, traversal_1.getElstBox)(trakBox);
24
+ if (!elstBox) {
25
+ return 0;
26
+ }
27
+ const { entries } = elstBox;
28
+ let dwellTime = 0;
29
+ for (const entry of entries) {
30
+ const { mediaTime } = entry;
31
+ if (mediaTime === -1) {
32
+ continue;
33
+ }
34
+ dwellTime += mediaTime;
35
+ }
36
+ return dwellTime;
37
+ };
38
+ exports.findTrackMediaTimeOffsetInTrackTimescale = findTrackMediaTimeOffsetInTrackTimescale;
@@ -9,6 +9,7 @@ const cached_sample_positions_1 = require("../../../state/iso-base-media/cached-
9
9
  const last_moof_box_1 = require("../../../state/iso-base-media/last-moof-box");
10
10
  const may_skip_video_data_1 = require("../../../state/may-skip-video-data");
11
11
  const video_section_1 = require("../../../state/video-section");
12
+ const webcodecs_timescale_1 = require("../../../webcodecs-timescale");
12
13
  const get_moov_atom_1 = require("../get-moov-atom");
13
14
  const calculate_jump_marks_1 = require("./calculate-jump-marks");
14
15
  const postprocess_bytes_1 = require("./postprocess-bytes");
@@ -65,29 +66,33 @@ const parseMdatSection = async (state) => {
65
66
  return (0, exports.parseMdatSection)(state);
66
67
  }
67
68
  if (!state.iso.flatSamples.getSamples(mediaSection.start)) {
68
- const flattedSamples = (0, cached_sample_positions_1.calculateFlatSamples)({
69
+ const { flatSamples: flatSamplesMap, offsets, trackIds, } = (0, cached_sample_positions_1.calculateFlatSamples)({
69
70
  state,
70
71
  mediaSectionStart: mediaSection.start,
71
72
  });
72
- const calcedJumpMarks = (0, calculate_jump_marks_1.calculateJumpMarks)(flattedSamples, endOfMdat);
73
+ const calcedJumpMarks = (0, calculate_jump_marks_1.calculateJumpMarks)({
74
+ sampleMap: flatSamplesMap,
75
+ offsetsSorted: offsets,
76
+ trackIds,
77
+ endOfMdat,
78
+ });
73
79
  state.iso.flatSamples.setJumpMarks(mediaSection.start, calcedJumpMarks);
74
- state.iso.flatSamples.setSamples(mediaSection.start, flattedSamples.flat(1));
80
+ state.iso.flatSamples.setSamples(mediaSection.start, flatSamplesMap);
75
81
  }
76
82
  const flatSamples = state.iso.flatSamples.getSamples(mediaSection.start);
77
83
  const jumpMarks = state.iso.flatSamples.getJumpMarks(mediaSection.start);
78
84
  const { iterator } = state;
79
- const samplesWithIndex = flatSamples.find((sample) => {
80
- return sample.samplePosition.offset === iterator.counter.getOffset();
81
- });
85
+ const samplesWithIndex = flatSamples.get(iterator.counter.getOffset());
82
86
  if (!samplesWithIndex) {
83
87
  // There are various reasons why in mdat we find weird stuff:
84
88
  // - iphonevideo.hevc has a fake hoov atom which is not mapped
85
89
  // - corrupted.mp4 has a corrupt table
86
- const nextSample_ = flatSamples
87
- .filter((s) => s.samplePosition.offset > iterator.counter.getOffset())
88
- .sort((a, b) => a.samplePosition.offset - b.samplePosition.offset)[0];
90
+ const offsets = Array.from(flatSamples.keys());
91
+ const nextSample_ = offsets
92
+ .filter((s) => s > iterator.counter.getOffset())
93
+ .sort((a, b) => a - b)[0];
89
94
  if (nextSample_) {
90
- iterator.discard(nextSample_.samplePosition.offset - iterator.counter.getOffset());
95
+ iterator.discard(nextSample_ - iterator.counter.getOffset());
91
96
  return null;
92
97
  }
93
98
  // guess we reached the end!
@@ -108,9 +113,15 @@ const parseMdatSection = async (state) => {
108
113
  return (0, skip_1.makeFetchMoreData)(samplesWithIndex.samplePosition.size - iterator.bytesRemaining());
109
114
  }
110
115
  const { timestamp: rawCts, decodingTimestamp: rawDts, duration, isKeyframe, offset, bigEndian, chunkSize, } = samplesWithIndex.samplePosition;
111
- const { originalTimescale, startInSeconds } = samplesWithIndex.track;
112
- const cts = rawCts + startInSeconds * originalTimescale;
113
- const dts = rawDts + startInSeconds * originalTimescale;
116
+ const { originalTimescale, startInSeconds, trackMediaTimeOffsetInTrackTimescale, timescale: trackTimescale, } = samplesWithIndex.track;
117
+ const cts = rawCts +
118
+ startInSeconds * originalTimescale -
119
+ (trackMediaTimeOffsetInTrackTimescale / trackTimescale) *
120
+ webcodecs_timescale_1.WEBCODECS_TIMESCALE;
121
+ const dts = rawDts +
122
+ startInSeconds * originalTimescale -
123
+ (trackMediaTimeOffsetInTrackTimescale / trackTimescale) *
124
+ webcodecs_timescale_1.WEBCODECS_TIMESCALE;
114
125
  const bytes = (0, postprocess_bytes_1.postprocessBytes)({
115
126
  bytes: iterator.getSlice(samplesWithIndex.samplePosition.size),
116
127
  bigEndian,
@@ -70,6 +70,7 @@ const parseMpegHeader = async ({ state, }) => {
70
70
  trackId: 0,
71
71
  startInSeconds: 0,
72
72
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
73
+ trackMediaTimeOffsetInTrackTimescale: 0,
73
74
  },
74
75
  registerAudioSampleCallback: state.callbacks.registerAudioSampleCallback,
75
76
  tracks: state.callbacks.tracks,
@@ -31,6 +31,7 @@ const makeAviAudioTrack = ({ strf, index, }) => {
31
31
  trackId: index,
32
32
  startInSeconds: 0,
33
33
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
34
+ trackMediaTimeOffsetInTrackTimescale: 0,
34
35
  };
35
36
  };
36
37
  exports.makeAviAudioTrack = makeAviAudioTrack;
@@ -73,6 +74,7 @@ const makeAviVideoTrack = ({ strh, strf, index, }) => {
73
74
  fps: strh.rate / strh.scale,
74
75
  startInSeconds: 0,
75
76
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
77
+ trackMediaTimeOffsetInTrackTimescale: 0,
76
78
  };
77
79
  };
78
80
  exports.makeAviVideoTrack = makeAviVideoTrack;
@@ -40,6 +40,7 @@ const handleAacPacket = async ({ streamBuffer, programId, offset, sampleCallback
40
40
  sampleRate,
41
41
  startInSeconds: 0,
42
42
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
43
+ trackMediaTimeOffsetInTrackTimescale: 0,
43
44
  };
44
45
  await (0, register_track_1.registerAudioTrack)({
45
46
  track,
@@ -59,6 +59,7 @@ const handleAvcPacket = async ({ streamBuffer, programId, offset, sampleCallback
59
59
  advancedColor,
60
60
  startInSeconds: 0,
61
61
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
62
+ trackMediaTimeOffsetInTrackTimescale: 0,
62
63
  };
63
64
  await (0, register_track_1.registerVideoTrack)({
64
65
  track,
@@ -110,6 +110,7 @@ const parseFmt = async ({ state, }) => {
110
110
  trackId: 0,
111
111
  startInSeconds: 0,
112
112
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
113
+ trackMediaTimeOffsetInTrackTimescale: 0,
113
114
  },
114
115
  container: 'wav',
115
116
  registerAudioSampleCallback: state.callbacks.registerAudioSampleCallback,
@@ -273,6 +273,7 @@ const getTrack = ({ timescale, track, }) => {
273
273
  fps: null,
274
274
  startInSeconds: 0,
275
275
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
276
+ trackMediaTimeOffsetInTrackTimescale: 0,
276
277
  };
277
278
  }
278
279
  if ((0, track_entry_1.trackTypeToString)(trackType.value.value) === 'audio') {
@@ -301,6 +302,7 @@ const getTrack = ({ timescale, track, }) => {
301
302
  }),
302
303
  startInSeconds: 0,
303
304
  timescale: webcodecs_timescale_1.WEBCODECS_TIMESCALE,
305
+ trackMediaTimeOffsetInTrackTimescale: 0,
304
306
  };
305
307
  }
306
308
  return null;