@remotion/media-parser 4.0.340 → 4.0.344
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.
- package/dist/containers/mp3/parse-packet-header.js +3 -2
- package/dist/containers/mp3/seek/wait-until-syncword.js +3 -0
- package/dist/esm/index.mjs +8 -7
- package/dist/esm/worker-server-entry.mjs +7 -6
- package/dist/esm/worker-web-entry.mjs +7 -6
- package/dist/metadata/get-metadata.js +3 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/dist/containers/iso-base-media/mdat/calculate-jump-marks.d.ts +0 -11
- package/dist/containers/iso-base-media/mdat/calculate-jump-marks.js +0 -122
|
@@ -177,7 +177,7 @@ const innerParseMp3PacketHeader = (iterator) => {
|
|
|
177
177
|
const bitrateInKbit = getBitrateKB({
|
|
178
178
|
bits: bitrateIndex,
|
|
179
179
|
mpegVersion,
|
|
180
|
-
level:
|
|
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
|
|
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) {
|
package/dist/esm/index.mjs
CHANGED
|
@@ -8247,10 +8247,7 @@ var getMetadata = (state) => {
|
|
|
8247
8247
|
}
|
|
8248
8248
|
if (structure.type === "mp3") {
|
|
8249
8249
|
const tags2 = getMetadataFromMp3(structure);
|
|
8250
|
-
|
|
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:
|
|
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
|
|
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.
|
|
18189
|
+
var VERSION = "4.0.344";
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
25
|
-
|
|
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.
|
|
1
|
+
export declare const VERSION = "4.0.344";
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
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.
|
|
6
|
+
"version": "4.0.344",
|
|
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.19.0",
|
|
12
|
-
"mediabunny": "1.
|
|
12
|
+
"mediabunny": "1.13.0",
|
|
13
13
|
"@types/bun": "1.2.8",
|
|
14
|
-
"@remotion/example-videos": "4.0.
|
|
15
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
14
|
+
"@remotion/example-videos": "4.0.344",
|
|
15
|
+
"@remotion/eslint-config-internal": "4.0.344"
|
|
16
16
|
},
|
|
17
17
|
"publishConfig": {
|
|
18
18
|
"access": "public"
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { MinimalFlatSampleForTesting } from '../../../state/iso-base-media/cached-sample-positions';
|
|
2
|
-
export type JumpMark = {
|
|
3
|
-
afterSampleWithOffset: number;
|
|
4
|
-
jumpToOffset: number;
|
|
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[];
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
https://discord.com/channels/809501355504959528/1001500302375125055/1364798934832119870
|
|
4
|
-
Android 13 produces MP4 videos where first, all video samples are at the beginning,
|
|
5
|
-
then all audio samples are at the end.
|
|
6
|
-
|
|
7
|
-
This causes issues with our video decoder: "Waited too long for VideoDecoder" because
|
|
8
|
-
the overall progress is stuck.
|
|
9
|
-
*/
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.calculateJumpMarks = void 0;
|
|
12
|
-
// In WebCodecs, we require the tracks to deviate by at most 10 seconds
|
|
13
|
-
// Therefore, we need to emit them to be less than 10 seconds apart
|
|
14
|
-
const MAX_SPREAD_IN_SECONDS = 8;
|
|
15
|
-
const getKey = (samplePositionTrack) => {
|
|
16
|
-
return `${samplePositionTrack.track.trackId}-${samplePositionTrack.samplePosition.decodingTimestamp}.${samplePositionTrack.samplePosition.offset}`;
|
|
17
|
-
};
|
|
18
|
-
const findBestJump = ({ sampleMap, offsetsSorted, visited, progresses, }) => {
|
|
19
|
-
var _a;
|
|
20
|
-
const minProgress = Math.min(...Object.values(progresses));
|
|
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
|
-
}
|
|
34
|
-
return firstSampleAboveMinProgress;
|
|
35
|
-
};
|
|
36
|
-
const calculateJumpMarks = ({ sampleMap, offsetsSorted, trackIds, endOfMdat, }) => {
|
|
37
|
-
const progresses = {};
|
|
38
|
-
for (const trackId of trackIds) {
|
|
39
|
-
progresses[trackId] = 0;
|
|
40
|
-
}
|
|
41
|
-
const jumpMarks = [];
|
|
42
|
-
let indexToVisit = 0;
|
|
43
|
-
const visited = new Set();
|
|
44
|
-
const increaseIndex = () => {
|
|
45
|
-
indexToVisit++;
|
|
46
|
-
if (indexToVisit >= offsetsSorted.length) {
|
|
47
|
-
throw new Error('should not roll over, should jump');
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
let lastVisitedSample = null;
|
|
51
|
-
const addJumpMark = ({ firstSampleAboveMinProgress, }) => {
|
|
52
|
-
if (!lastVisitedSample) {
|
|
53
|
-
throw new Error('no last visited sample');
|
|
54
|
-
}
|
|
55
|
-
const jumpMark = {
|
|
56
|
-
afterSampleWithOffset: lastVisitedSample.samplePosition.offset,
|
|
57
|
-
jumpToOffset: offsetsSorted[firstSampleAboveMinProgress],
|
|
58
|
-
};
|
|
59
|
-
if (firstSampleAboveMinProgress ===
|
|
60
|
-
offsetsSorted.indexOf(lastVisitedSample.samplePosition.offset) + 1) {
|
|
61
|
-
indexToVisit = firstSampleAboveMinProgress;
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
indexToVisit = firstSampleAboveMinProgress;
|
|
65
|
-
jumpMarks.push(jumpMark);
|
|
66
|
-
};
|
|
67
|
-
const addFinalJumpIfNecessary = () => {
|
|
68
|
-
if (indexToVisit === offsetsSorted.length - 1) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
jumpMarks.push({
|
|
72
|
-
afterSampleWithOffset: offsetsSorted[indexToVisit],
|
|
73
|
-
jumpToOffset: endOfMdat,
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
const considerJump = () => {
|
|
77
|
-
const firstSampleAboveMinProgress = findBestJump({
|
|
78
|
-
sampleMap,
|
|
79
|
-
offsetsSorted,
|
|
80
|
-
visited,
|
|
81
|
-
progresses,
|
|
82
|
-
});
|
|
83
|
-
addJumpMark({ firstSampleAboveMinProgress });
|
|
84
|
-
};
|
|
85
|
-
while (true) {
|
|
86
|
-
const currentSamplePosition = sampleMap.get(offsetsSorted[indexToVisit]);
|
|
87
|
-
const sampleKey = getKey(currentSamplePosition);
|
|
88
|
-
if (visited.has(sampleKey)) {
|
|
89
|
-
considerJump();
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
visited.add(sampleKey);
|
|
93
|
-
lastVisitedSample = currentSamplePosition;
|
|
94
|
-
if (visited.size === offsetsSorted.length) {
|
|
95
|
-
addFinalJumpIfNecessary();
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
const timestamp = currentSamplePosition.samplePosition.decodingTimestamp /
|
|
99
|
-
currentSamplePosition.track.originalTimescale;
|
|
100
|
-
progresses[currentSamplePosition.track.trackId] = timestamp;
|
|
101
|
-
const progressValues = Object.values(progresses);
|
|
102
|
-
const maxProgress = Math.max(...progressValues);
|
|
103
|
-
const minProgress = Math.min(...progressValues);
|
|
104
|
-
const spread = maxProgress - minProgress;
|
|
105
|
-
if (visited.size === offsetsSorted.length) {
|
|
106
|
-
addFinalJumpIfNecessary();
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
// Also don't allow audio progress to go more
|
|
110
|
-
if (spread > MAX_SPREAD_IN_SECONDS) {
|
|
111
|
-
considerJump();
|
|
112
|
-
}
|
|
113
|
-
else if (indexToVisit === offsetsSorted.length - 1) {
|
|
114
|
-
considerJump();
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
increaseIndex();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return jumpMarks;
|
|
121
|
-
};
|
|
122
|
-
exports.calculateJumpMarks = calculateJumpMarks;
|