@remotion/media-parser 4.0.340 → 4.0.341

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.
@@ -3,9 +3,4 @@ export type JumpMark = {
3
3
  afterSampleWithOffset: number;
4
4
  jumpToOffset: number;
5
5
  };
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[];
6
+ export declare const calculateJumpMarks: (samplePositionTracks: MinimalFlatSampleForTesting[][], endOfMdat: number) => JumpMark[];
@@ -13,38 +13,33 @@ exports.calculateJumpMarks = void 0;
13
13
  // Therefore, we need to emit them to be less than 10 seconds apart
14
14
  const MAX_SPREAD_IN_SECONDS = 8;
15
15
  const getKey = (samplePositionTrack) => {
16
- return `${samplePositionTrack.track.trackId}-${samplePositionTrack.samplePosition.decodingTimestamp}.${samplePositionTrack.samplePosition.offset}`;
16
+ return `${samplePositionTrack.track.trackId}-${samplePositionTrack.samplePosition.decodingTimestamp}`;
17
17
  };
18
- const findBestJump = ({ sampleMap, offsetsSorted, visited, progresses, }) => {
18
+ const findBestJump = ({ allSamplesSortedByOffset, 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 = offsetsSorted.findIndex((offset) => sampleMap.get(offset).track.trackId ===
23
- Number(trackNumberWithLowestProgress) &&
24
- !visited.has(getKey(sampleMap.get(offset))));
25
- if (firstSampleAboveMinProgress === -1) {
26
- // Track might be done, so we don't care about minimum progress
27
- // then
28
- const backup = offsetsSorted.findIndex((offset) => !visited.has(getKey(sampleMap.get(offset))));
29
- if (backup === -1) {
30
- throw new Error('this should not happen');
31
- }
32
- return backup;
33
- }
22
+ const firstSampleAboveMinProgress = allSamplesSortedByOffset.findIndex((sample) => sample.track.trackId === Number(trackNumberWithLowestProgress) &&
23
+ !visited.has(getKey(sample)));
34
24
  return firstSampleAboveMinProgress;
35
25
  };
36
- const calculateJumpMarks = ({ sampleMap, offsetsSorted, trackIds, endOfMdat, }) => {
26
+ const calculateJumpMarks = (samplePositionTracks, endOfMdat) => {
37
27
  const progresses = {};
38
- for (const trackId of trackIds) {
39
- progresses[trackId] = 0;
28
+ for (const track of samplePositionTracks) {
29
+ progresses[track[0].track.trackId] = 0;
40
30
  }
41
31
  const jumpMarks = [];
32
+ const allSamplesSortedByOffset = samplePositionTracks
33
+ .flat(1)
34
+ .sort((a, b) => a.samplePosition.offset - b.samplePosition.offset);
42
35
  let indexToVisit = 0;
43
36
  const visited = new Set();
37
+ let rollOverToProcess = false;
44
38
  const increaseIndex = () => {
45
39
  indexToVisit++;
46
- if (indexToVisit >= offsetsSorted.length) {
47
- throw new Error('should not roll over, should jump');
40
+ if (indexToVisit >= allSamplesSortedByOffset.length) {
41
+ rollOverToProcess = true;
42
+ indexToVisit = 0;
48
43
  }
49
44
  };
50
45
  let lastVisitedSample = null;
@@ -54,44 +49,61 @@ const calculateJumpMarks = ({ sampleMap, offsetsSorted, trackIds, endOfMdat, })
54
49
  }
55
50
  const jumpMark = {
56
51
  afterSampleWithOffset: lastVisitedSample.samplePosition.offset,
57
- jumpToOffset: offsetsSorted[firstSampleAboveMinProgress],
52
+ jumpToOffset: allSamplesSortedByOffset[firstSampleAboveMinProgress].samplePosition
53
+ .offset,
58
54
  };
59
- if (firstSampleAboveMinProgress ===
60
- offsetsSorted.indexOf(lastVisitedSample.samplePosition.offset) + 1) {
61
- indexToVisit = firstSampleAboveMinProgress;
62
- return;
63
- }
64
55
  indexToVisit = firstSampleAboveMinProgress;
65
56
  jumpMarks.push(jumpMark);
66
57
  };
67
58
  const addFinalJumpIfNecessary = () => {
68
- if (indexToVisit === offsetsSorted.length - 1) {
59
+ if (indexToVisit === allSamplesSortedByOffset.length - 1) {
69
60
  return;
70
61
  }
71
62
  jumpMarks.push({
72
- afterSampleWithOffset: offsetsSorted[indexToVisit],
63
+ afterSampleWithOffset: allSamplesSortedByOffset[indexToVisit].samplePosition.offset,
73
64
  jumpToOffset: endOfMdat,
74
65
  });
75
66
  };
76
67
  const considerJump = () => {
77
68
  const firstSampleAboveMinProgress = findBestJump({
78
- sampleMap,
79
- offsetsSorted,
69
+ allSamplesSortedByOffset,
80
70
  visited,
81
71
  progresses,
82
72
  });
83
- addJumpMark({ firstSampleAboveMinProgress });
73
+ if (firstSampleAboveMinProgress > -1 &&
74
+ firstSampleAboveMinProgress !== indexToVisit + 1) {
75
+ addJumpMark({ firstSampleAboveMinProgress });
76
+ indexToVisit = firstSampleAboveMinProgress;
77
+ }
78
+ else {
79
+ while (true) {
80
+ increaseIndex();
81
+ if (!visited.has(getKey(allSamplesSortedByOffset[indexToVisit]))) {
82
+ break;
83
+ }
84
+ }
85
+ }
84
86
  };
85
87
  while (true) {
86
- const currentSamplePosition = sampleMap.get(offsetsSorted[indexToVisit]);
88
+ const currentSamplePosition = allSamplesSortedByOffset[indexToVisit];
87
89
  const sampleKey = getKey(currentSamplePosition);
88
90
  if (visited.has(sampleKey)) {
89
91
  considerJump();
90
92
  continue;
91
93
  }
92
94
  visited.add(sampleKey);
95
+ if (rollOverToProcess) {
96
+ if (!lastVisitedSample) {
97
+ throw new Error('no last visited sample');
98
+ }
99
+ jumpMarks.push({
100
+ afterSampleWithOffset: lastVisitedSample.samplePosition.offset,
101
+ jumpToOffset: currentSamplePosition.samplePosition.offset,
102
+ });
103
+ rollOverToProcess = false;
104
+ }
93
105
  lastVisitedSample = currentSamplePosition;
94
- if (visited.size === offsetsSorted.length) {
106
+ if (visited.size === allSamplesSortedByOffset.length) {
95
107
  addFinalJumpIfNecessary();
96
108
  break;
97
109
  }
@@ -102,7 +114,7 @@ const calculateJumpMarks = ({ sampleMap, offsetsSorted, trackIds, endOfMdat, })
102
114
  const maxProgress = Math.max(...progressValues);
103
115
  const minProgress = Math.min(...progressValues);
104
116
  const spread = maxProgress - minProgress;
105
- if (visited.size === offsetsSorted.length) {
117
+ if (visited.size === allSamplesSortedByOffset.length) {
106
118
  addFinalJumpIfNecessary();
107
119
  break;
108
120
  }
@@ -110,9 +122,6 @@ const calculateJumpMarks = ({ sampleMap, offsetsSorted, trackIds, endOfMdat, })
110
122
  if (spread > MAX_SPREAD_IN_SECONDS) {
111
123
  considerJump();
112
124
  }
113
- else if (indexToVisit === offsetsSorted.length - 1) {
114
- considerJump();
115
- }
116
125
  else {
117
126
  increaseIndex();
118
127
  }
@@ -0,0 +1,30 @@
1
+ import type { BufferIterator } from '../../iterator/buffer-iterator';
2
+ import type { BaseBox } from './base-type';
3
+ export type ThreeDMatrix = [
4
+ number,
5
+ number,
6
+ number,
7
+ number,
8
+ number,
9
+ number,
10
+ number,
11
+ number,
12
+ number
13
+ ];
14
+ export interface MvhdBox extends BaseBox {
15
+ durationInUnits: number;
16
+ durationInSeconds: number;
17
+ creationTime: number | null;
18
+ modificationTime: number | null;
19
+ timeScale: number;
20
+ rate: number;
21
+ volume: number;
22
+ matrix: ThreeDMatrix;
23
+ nextTrackId: number;
24
+ type: 'mvhd-box';
25
+ }
26
+ export declare const parseMvhd: ({ iterator, offset, size, }: {
27
+ iterator: BufferIterator;
28
+ offset: number;
29
+ size: number;
30
+ }) => MvhdBox;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseMvhd = void 0;
4
+ const buffer_iterator_1 = require("../../iterator/buffer-iterator");
5
+ const to_date_1 = require("./to-date");
6
+ const parseMvhd = ({ iterator, offset, size, }) => {
7
+ const version = iterator.getUint8();
8
+ // Flags, we discard them
9
+ iterator.discard(3);
10
+ const creationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
11
+ const modificationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
12
+ const timeScale = iterator.getUint32();
13
+ const durationInUnits = version === 1 ? iterator.getUint64() : iterator.getUint32();
14
+ const durationInSeconds = Number(durationInUnits) / timeScale;
15
+ const rateArray = iterator.getSlice(4);
16
+ const rateView = (0, buffer_iterator_1.getArrayBufferIterator)(rateArray, rateArray.length);
17
+ const rate = rateView.getInt8() * 10 +
18
+ rateView.getInt8() +
19
+ rateView.getInt8() * 0.1 +
20
+ rateView.getInt8() * 0.01;
21
+ const volumeArray = iterator.getSlice(2);
22
+ const volumeView = (0, buffer_iterator_1.getArrayBufferIterator)(volumeArray, volumeArray.length);
23
+ const volume = volumeView.getInt8() + volumeView.getInt8() * 0.1;
24
+ // reserved 16bit
25
+ iterator.discard(2);
26
+ // reserved 32bit x2
27
+ iterator.discard(4);
28
+ iterator.discard(4);
29
+ // matrix
30
+ const matrix = [
31
+ iterator.getFixedPointSigned1616Number(),
32
+ iterator.getFixedPointSigned1616Number(),
33
+ iterator.getFixedPointSigned230Number(),
34
+ iterator.getFixedPointSigned1616Number(),
35
+ iterator.getFixedPointSigned1616Number(),
36
+ iterator.getFixedPointSigned230Number(),
37
+ iterator.getFixedPointSigned1616Number(),
38
+ iterator.getFixedPointSigned1616Number(),
39
+ iterator.getFixedPointSigned230Number(),
40
+ ];
41
+ // pre-defined
42
+ iterator.discard(4 * 6);
43
+ // next track id
44
+ const nextTrackId = iterator.getUint32();
45
+ volumeView.destroy();
46
+ const bytesRemaining = size - (iterator.counter.getOffset() - offset);
47
+ if (bytesRemaining !== 0) {
48
+ throw new Error('expected 0 bytes ' + bytesRemaining);
49
+ }
50
+ return {
51
+ creationTime: (0, to_date_1.toUnixTimestamp)(Number(creationTime)),
52
+ modificationTime: (0, to_date_1.toUnixTimestamp)(Number(modificationTime)),
53
+ timeScale,
54
+ durationInUnits: Number(durationInUnits),
55
+ durationInSeconds,
56
+ rate,
57
+ volume,
58
+ matrix: matrix,
59
+ nextTrackId,
60
+ type: 'mvhd-box',
61
+ boxSize: size,
62
+ offset,
63
+ };
64
+ };
65
+ exports.parseMvhd = parseMvhd;
@@ -177,7 +177,7 @@ const innerParseMp3PacketHeader = (iterator) => {
177
177
  const bitrateInKbit = getBitrateKB({
178
178
  bits: bitrateIndex,
179
179
  mpegVersion,
180
- level: audioVersionId,
180
+ level: layer,
181
181
  });
182
182
  if (bitrateInKbit === 'bad') {
183
183
  throw new Error('Invalid bitrate');
@@ -186,10 +186,11 @@ const innerParseMp3PacketHeader = (iterator) => {
186
186
  throw new Error('Free bitrate not supported');
187
187
  }
188
188
  const samplingFrequencyIndex = iterator.getBits(2);
189
- const sampleRate = getSamplingFrequency({
189
+ const baseSampleRate = getSamplingFrequency({
190
190
  bits: samplingFrequencyIndex,
191
191
  mpegVersion,
192
192
  });
193
+ const sampleRate = audioVersionId === 0b00 ? baseSampleRate / 2 : baseSampleRate;
193
194
  const padding = Boolean(iterator.getBits(1));
194
195
  iterator.getBits(1); // private bit
195
196
  const channelMode = iterator.getBits(2); // channel mode
@@ -8,6 +8,9 @@ const discardUntilSyncword = ({ iterator, }) => {
8
8
  if (next2Bytes !== 0xff) {
9
9
  continue;
10
10
  }
11
+ if (iterator.bytesRemaining() === 0) {
12
+ break;
13
+ }
11
14
  const nextByte = iterator.getUint8();
12
15
  const mask = 0xe0; // 1110 0000
13
16
  if ((nextByte & mask) !== mask) {
@@ -8247,10 +8247,7 @@ var getMetadata = (state) => {
8247
8247
  }
8248
8248
  if (structure.type === "mp3") {
8249
8249
  const tags2 = getMetadataFromMp3(structure);
8250
- if (tags2 === null) {
8251
- throw new Error("Failed to get metadata from mp3");
8252
- }
8253
- return tags2;
8250
+ return tags2 ?? [];
8254
8251
  }
8255
8252
  if (structure.type === "wav") {
8256
8253
  return getMetadataFromWav(structure) ?? [];
@@ -13432,7 +13429,7 @@ var innerParseMp3PacketHeader = (iterator) => {
13432
13429
  const bitrateInKbit = getBitrateKB({
13433
13430
  bits: bitrateIndex,
13434
13431
  mpegVersion,
13435
- level: audioVersionId
13432
+ level: layer
13436
13433
  });
13437
13434
  if (bitrateInKbit === "bad") {
13438
13435
  throw new Error("Invalid bitrate");
@@ -13441,10 +13438,11 @@ var innerParseMp3PacketHeader = (iterator) => {
13441
13438
  throw new Error("Free bitrate not supported");
13442
13439
  }
13443
13440
  const samplingFrequencyIndex = iterator.getBits(2);
13444
- const sampleRate = getSamplingFrequency({
13441
+ const baseSampleRate = getSamplingFrequency({
13445
13442
  bits: samplingFrequencyIndex,
13446
13443
  mpegVersion
13447
13444
  });
13445
+ const sampleRate = audioVersionId === 0 ? baseSampleRate / 2 : baseSampleRate;
13448
13446
  const padding = Boolean(iterator.getBits(1));
13449
13447
  iterator.getBits(1);
13450
13448
  const channelMode = iterator.getBits(2);
@@ -13709,6 +13707,9 @@ var discardUntilSyncword = ({
13709
13707
  if (next2Bytes !== 255) {
13710
13708
  continue;
13711
13709
  }
13710
+ if (iterator.bytesRemaining() === 0) {
13711
+ break;
13712
+ }
13712
13713
  const nextByte = iterator.getUint8();
13713
13714
  const mask = 224;
13714
13715
  if ((nextByte & mask) !== mask) {
@@ -18185,7 +18186,7 @@ var downloadAndParseMedia = async (options) => {
18185
18186
  return returnValue;
18186
18187
  };
18187
18188
  // src/version.ts
18188
- var VERSION = "4.0.340";
18189
+ var VERSION = "4.0.341";
18189
18190
 
18190
18191
  // src/index.ts
18191
18192
  var MediaParserInternals = {
@@ -5871,10 +5871,7 @@ var getMetadata = (state) => {
5871
5871
  }
5872
5872
  if (structure.type === "mp3") {
5873
5873
  const tags2 = getMetadataFromMp3(structure);
5874
- if (tags2 === null) {
5875
- throw new Error("Failed to get metadata from mp3");
5876
- }
5877
- return tags2;
5874
+ return tags2 ?? [];
5878
5875
  }
5879
5876
  if (structure.type === "wav") {
5880
5877
  return getMetadataFromWav(structure) ?? [];
@@ -13163,7 +13160,7 @@ var innerParseMp3PacketHeader = (iterator) => {
13163
13160
  const bitrateInKbit = getBitrateKB({
13164
13161
  bits: bitrateIndex,
13165
13162
  mpegVersion,
13166
- level: audioVersionId
13163
+ level: layer
13167
13164
  });
13168
13165
  if (bitrateInKbit === "bad") {
13169
13166
  throw new Error("Invalid bitrate");
@@ -13172,10 +13169,11 @@ var innerParseMp3PacketHeader = (iterator) => {
13172
13169
  throw new Error("Free bitrate not supported");
13173
13170
  }
13174
13171
  const samplingFrequencyIndex = iterator.getBits(2);
13175
- const sampleRate = getSamplingFrequency({
13172
+ const baseSampleRate = getSamplingFrequency({
13176
13173
  bits: samplingFrequencyIndex,
13177
13174
  mpegVersion
13178
13175
  });
13176
+ const sampleRate = audioVersionId === 0 ? baseSampleRate / 2 : baseSampleRate;
13179
13177
  const padding = Boolean(iterator.getBits(1));
13180
13178
  iterator.getBits(1);
13181
13179
  const channelMode = iterator.getBits(2);
@@ -13440,6 +13438,9 @@ var discardUntilSyncword = ({
13440
13438
  if (next2Bytes !== 255) {
13441
13439
  continue;
13442
13440
  }
13441
+ if (iterator.bytesRemaining() === 0) {
13442
+ break;
13443
+ }
13443
13444
  const nextByte = iterator.getUint8();
13444
13445
  const mask = 224;
13445
13446
  if ((nextByte & mask) !== mask) {
@@ -5768,10 +5768,7 @@ var getMetadata = (state) => {
5768
5768
  }
5769
5769
  if (structure.type === "mp3") {
5770
5770
  const tags2 = getMetadataFromMp3(structure);
5771
- if (tags2 === null) {
5772
- throw new Error("Failed to get metadata from mp3");
5773
- }
5774
- return tags2;
5771
+ return tags2 ?? [];
5775
5772
  }
5776
5773
  if (structure.type === "wav") {
5777
5774
  return getMetadataFromWav(structure) ?? [];
@@ -13032,7 +13029,7 @@ var innerParseMp3PacketHeader = (iterator) => {
13032
13029
  const bitrateInKbit = getBitrateKB({
13033
13030
  bits: bitrateIndex,
13034
13031
  mpegVersion,
13035
- level: audioVersionId
13032
+ level: layer
13036
13033
  });
13037
13034
  if (bitrateInKbit === "bad") {
13038
13035
  throw new Error("Invalid bitrate");
@@ -13041,10 +13038,11 @@ var innerParseMp3PacketHeader = (iterator) => {
13041
13038
  throw new Error("Free bitrate not supported");
13042
13039
  }
13043
13040
  const samplingFrequencyIndex = iterator.getBits(2);
13044
- const sampleRate = getSamplingFrequency({
13041
+ const baseSampleRate = getSamplingFrequency({
13045
13042
  bits: samplingFrequencyIndex,
13046
13043
  mpegVersion
13047
13044
  });
13045
+ const sampleRate = audioVersionId === 0 ? baseSampleRate / 2 : baseSampleRate;
13048
13046
  const padding = Boolean(iterator.getBits(1));
13049
13047
  iterator.getBits(1);
13050
13048
  const channelMode = iterator.getBits(2);
@@ -13309,6 +13307,9 @@ var discardUntilSyncword = ({
13309
13307
  if (next2Bytes !== 255) {
13310
13308
  continue;
13311
13309
  }
13310
+ if (iterator.bytesRemaining() === 0) {
13311
+ break;
13312
+ }
13312
13313
  const nextByte = iterator.getUint8();
13313
13314
  const mask = 224;
13314
13315
  if ((nextByte & mask) !== mask) {
@@ -21,10 +21,9 @@ const getMetadata = (state) => {
21
21
  }
22
22
  if (structure.type === 'mp3') {
23
23
  const tags = (0, get_metadata_from_mp3_1.getMetadataFromMp3)(structure);
24
- if (tags === null) {
25
- throw new Error('Failed to get metadata from mp3');
26
- }
27
- return tags;
24
+ // Not all MP3s file have this header.
25
+ // Internal link: https://discord.com/channels/809501355504959528/1001500302375125055/1408880907602890752
26
+ return tags !== null && tags !== void 0 ? tags : [];
28
27
  }
29
28
  if (structure.type === 'wav') {
30
29
  return (_a = (0, get_metadata_from_wav_1.getMetadataFromWav)(structure)) !== null && _a !== void 0 ? _a : [];
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "4.0.340";
1
+ export declare const VERSION = "4.0.341";
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.340';
5
+ exports.VERSION = '4.0.341';
package/package.json CHANGED
@@ -3,7 +3,7 @@
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.340",
6
+ "version": "4.0.341",
7
7
  "main": "dist/index.js",
8
8
  "sideEffects": false,
9
9
  "devDependencies": {
@@ -11,8 +11,8 @@
11
11
  "eslint": "9.19.0",
12
12
  "mediabunny": "1.3.0",
13
13
  "@types/bun": "1.2.8",
14
- "@remotion/example-videos": "4.0.340",
15
- "@remotion/eslint-config-internal": "4.0.340"
14
+ "@remotion/eslint-config-internal": "4.0.341",
15
+ "@remotion/example-videos": "4.0.341"
16
16
  },
17
17
  "publishConfig": {
18
18
  "access": "public"