mediabunny 1.17.0 → 1.17.2
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/bundles/mediabunny.cjs +229 -86
- package/dist/bundles/mediabunny.min.cjs +4 -4
- package/dist/bundles/mediabunny.min.mjs +4 -4
- package/dist/bundles/mediabunny.mjs +229 -86
- package/dist/modules/shared/mp3-misc.d.ts +3 -4
- package/dist/modules/shared/mp3-misc.d.ts.map +1 -1
- package/dist/modules/shared/mp3-misc.js +38 -41
- package/dist/modules/src/mp3/mp3-demuxer.d.ts.map +1 -1
- package/dist/modules/src/mp3/mp3-demuxer.js +6 -2
- package/dist/modules/src/mp3/mp3-muxer.d.ts.map +1 -1
- package/dist/modules/src/mp3/mp3-muxer.js +1 -0
- package/dist/modules/src/mp3/mp3-writer.d.ts +2 -1
- package/dist/modules/src/mp3/mp3-writer.d.ts.map +1 -1
- package/dist/modules/src/mp3/mp3-writer.js +60 -54
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/mp3/mp3-demuxer.ts +9 -2
- package/src/mp3/mp3-muxer.ts +1 -0
- package/src/mp3/mp3-writer.ts +79 -71
|
@@ -7906,37 +7906,158 @@ ${cue.notes ?? ""}`;
|
|
|
7906
7906
|
|
|
7907
7907
|
// shared/mp3-misc.ts
|
|
7908
7908
|
var FRAME_HEADER_SIZE = 4;
|
|
7909
|
-
var
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
//
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7909
|
+
var SAMPLING_RATES = [44100, 48e3, 32e3];
|
|
7910
|
+
var KILOBIT_RATES = [
|
|
7911
|
+
// lowSamplingFrequency === 0
|
|
7912
|
+
-1,
|
|
7913
|
+
-1,
|
|
7914
|
+
-1,
|
|
7915
|
+
-1,
|
|
7916
|
+
-1,
|
|
7917
|
+
-1,
|
|
7918
|
+
-1,
|
|
7919
|
+
-1,
|
|
7920
|
+
-1,
|
|
7921
|
+
-1,
|
|
7922
|
+
-1,
|
|
7923
|
+
-1,
|
|
7924
|
+
-1,
|
|
7925
|
+
-1,
|
|
7926
|
+
-1,
|
|
7927
|
+
-1,
|
|
7928
|
+
// layer = 0
|
|
7929
|
+
-1,
|
|
7930
|
+
32,
|
|
7931
|
+
40,
|
|
7932
|
+
48,
|
|
7933
|
+
56,
|
|
7934
|
+
64,
|
|
7935
|
+
80,
|
|
7936
|
+
96,
|
|
7937
|
+
112,
|
|
7938
|
+
128,
|
|
7939
|
+
160,
|
|
7940
|
+
192,
|
|
7941
|
+
224,
|
|
7942
|
+
256,
|
|
7943
|
+
320,
|
|
7944
|
+
-1,
|
|
7945
|
+
// layer 1
|
|
7946
|
+
-1,
|
|
7947
|
+
32,
|
|
7948
|
+
48,
|
|
7949
|
+
56,
|
|
7950
|
+
64,
|
|
7951
|
+
80,
|
|
7952
|
+
96,
|
|
7953
|
+
112,
|
|
7954
|
+
128,
|
|
7955
|
+
160,
|
|
7956
|
+
192,
|
|
7957
|
+
224,
|
|
7958
|
+
256,
|
|
7959
|
+
320,
|
|
7960
|
+
384,
|
|
7961
|
+
-1,
|
|
7962
|
+
// layer = 2
|
|
7963
|
+
-1,
|
|
7964
|
+
32,
|
|
7965
|
+
64,
|
|
7966
|
+
96,
|
|
7967
|
+
128,
|
|
7968
|
+
160,
|
|
7969
|
+
192,
|
|
7970
|
+
224,
|
|
7971
|
+
256,
|
|
7972
|
+
288,
|
|
7973
|
+
320,
|
|
7974
|
+
352,
|
|
7975
|
+
384,
|
|
7976
|
+
416,
|
|
7977
|
+
448,
|
|
7978
|
+
-1,
|
|
7979
|
+
// layer = 3
|
|
7980
|
+
// lowSamplingFrequency === 1
|
|
7981
|
+
-1,
|
|
7982
|
+
-1,
|
|
7983
|
+
-1,
|
|
7984
|
+
-1,
|
|
7985
|
+
-1,
|
|
7986
|
+
-1,
|
|
7987
|
+
-1,
|
|
7988
|
+
-1,
|
|
7989
|
+
-1,
|
|
7990
|
+
-1,
|
|
7991
|
+
-1,
|
|
7992
|
+
-1,
|
|
7993
|
+
-1,
|
|
7994
|
+
-1,
|
|
7995
|
+
-1,
|
|
7996
|
+
-1,
|
|
7997
|
+
// layer = 0
|
|
7998
|
+
-1,
|
|
7999
|
+
8,
|
|
8000
|
+
16,
|
|
8001
|
+
24,
|
|
8002
|
+
32,
|
|
8003
|
+
40,
|
|
8004
|
+
48,
|
|
8005
|
+
56,
|
|
8006
|
+
64,
|
|
8007
|
+
80,
|
|
8008
|
+
96,
|
|
8009
|
+
112,
|
|
8010
|
+
128,
|
|
8011
|
+
144,
|
|
8012
|
+
160,
|
|
8013
|
+
-1,
|
|
8014
|
+
// layer = 1
|
|
8015
|
+
-1,
|
|
8016
|
+
8,
|
|
8017
|
+
16,
|
|
8018
|
+
24,
|
|
8019
|
+
32,
|
|
8020
|
+
40,
|
|
8021
|
+
48,
|
|
8022
|
+
56,
|
|
8023
|
+
64,
|
|
8024
|
+
80,
|
|
8025
|
+
96,
|
|
8026
|
+
112,
|
|
8027
|
+
128,
|
|
8028
|
+
144,
|
|
8029
|
+
160,
|
|
8030
|
+
-1,
|
|
8031
|
+
// layer = 2
|
|
8032
|
+
-1,
|
|
8033
|
+
32,
|
|
8034
|
+
48,
|
|
8035
|
+
56,
|
|
8036
|
+
64,
|
|
8037
|
+
80,
|
|
8038
|
+
96,
|
|
8039
|
+
112,
|
|
8040
|
+
128,
|
|
8041
|
+
144,
|
|
8042
|
+
160,
|
|
8043
|
+
176,
|
|
8044
|
+
192,
|
|
8045
|
+
224,
|
|
8046
|
+
256,
|
|
8047
|
+
-1
|
|
8048
|
+
// layer = 3
|
|
8049
|
+
];
|
|
7933
8050
|
var XING = 1483304551;
|
|
7934
8051
|
var INFO = 1231971951;
|
|
7935
|
-
var computeMp3FrameSize = (layer, bitrate, sampleRate, padding) => {
|
|
7936
|
-
if (layer ===
|
|
7937
|
-
return
|
|
8052
|
+
var computeMp3FrameSize = (lowSamplingFrequency, layer, bitrate, sampleRate, padding) => {
|
|
8053
|
+
if (layer === 0) {
|
|
8054
|
+
return 0;
|
|
8055
|
+
} else if (layer === 1) {
|
|
8056
|
+
return Math.round(144 * bitrate / (sampleRate << lowSamplingFrequency)) + padding;
|
|
8057
|
+
} else if (layer === 2) {
|
|
8058
|
+
return Math.round(144 * bitrate / sampleRate) + padding;
|
|
7938
8059
|
} else {
|
|
7939
|
-
return Math.
|
|
8060
|
+
return (Math.round(12 * bitrate / sampleRate) + padding) * 4;
|
|
7940
8061
|
}
|
|
7941
8062
|
};
|
|
7942
8063
|
var getXingOffset = (mpegVersionId, channel) => {
|
|
@@ -7959,26 +8080,31 @@ ${cue.notes ?? ""}`;
|
|
|
7959
8080
|
if ((secondByte & 224) !== 224) {
|
|
7960
8081
|
return { header: null, bytesAdvanced: 1 };
|
|
7961
8082
|
}
|
|
8083
|
+
let lowSamplingFrequency = 0;
|
|
8084
|
+
let mpeg25 = 0;
|
|
8085
|
+
if (secondByte & 1 << 4) {
|
|
8086
|
+
lowSamplingFrequency = secondByte & 1 << 3 ? 0 : 1;
|
|
8087
|
+
} else {
|
|
8088
|
+
lowSamplingFrequency = 1;
|
|
8089
|
+
mpeg25 = 1;
|
|
8090
|
+
}
|
|
7962
8091
|
const mpegVersionId = secondByte >> 3 & 3;
|
|
7963
8092
|
const layer = secondByte >> 1 & 3;
|
|
7964
8093
|
const bitrateIndex = thirdByte >> 4 & 15;
|
|
7965
|
-
const frequencyIndex = thirdByte >> 2 & 3;
|
|
8094
|
+
const frequencyIndex = (thirdByte >> 2 & 3) % 3;
|
|
7966
8095
|
const padding = thirdByte >> 1 & 1;
|
|
7967
8096
|
const channel = fourthByte >> 6 & 3;
|
|
7968
8097
|
const modeExtension = fourthByte >> 4 & 3;
|
|
7969
8098
|
const copyright = fourthByte >> 3 & 1;
|
|
7970
8099
|
const original = fourthByte >> 2 & 1;
|
|
7971
8100
|
const emphasis = fourthByte & 3;
|
|
7972
|
-
const kilobitRate =
|
|
7973
|
-
if (
|
|
8101
|
+
const kilobitRate = KILOBIT_RATES[lowSamplingFrequency * 16 * 4 + layer * 16 + bitrateIndex];
|
|
8102
|
+
if (kilobitRate === -1) {
|
|
7974
8103
|
return { header: null, bytesAdvanced: 1 };
|
|
7975
8104
|
}
|
|
7976
8105
|
const bitrate = kilobitRate * 1e3;
|
|
7977
|
-
const sampleRate = SAMPLING_RATES[
|
|
7978
|
-
|
|
7979
|
-
return { header: null, bytesAdvanced: 1 };
|
|
7980
|
-
}
|
|
7981
|
-
const frameLength = computeMp3FrameSize(layer, bitrate, sampleRate, padding);
|
|
8106
|
+
const sampleRate = SAMPLING_RATES[frequencyIndex] >> lowSamplingFrequency + mpeg25;
|
|
8107
|
+
const frameLength = computeMp3FrameSize(lowSamplingFrequency, layer, bitrate, sampleRate, padding);
|
|
7982
8108
|
if (remainingBytes !== null && remainingBytes < frameLength) {
|
|
7983
8109
|
return { header: null, bytesAdvanced: 1 };
|
|
7984
8110
|
}
|
|
@@ -8758,6 +8884,65 @@ ${cue.notes ?? ""}`;
|
|
|
8758
8884
|
}
|
|
8759
8885
|
this.writer.write(this.helper.subarray(0, text.length));
|
|
8760
8886
|
}
|
|
8887
|
+
writeXingFrame(data) {
|
|
8888
|
+
const startPos = this.writer.getPos();
|
|
8889
|
+
const firstByte = 255;
|
|
8890
|
+
const secondByte = 224 | data.mpegVersionId << 3 | data.layer << 1;
|
|
8891
|
+
let lowSamplingFrequency;
|
|
8892
|
+
if (data.mpegVersionId & 2) {
|
|
8893
|
+
lowSamplingFrequency = data.mpegVersionId & 1 ? 0 : 1;
|
|
8894
|
+
} else {
|
|
8895
|
+
lowSamplingFrequency = 1;
|
|
8896
|
+
}
|
|
8897
|
+
const padding = 0;
|
|
8898
|
+
const neededBytes = 155;
|
|
8899
|
+
let bitrateIndex = -1;
|
|
8900
|
+
const bitrateOffset = lowSamplingFrequency * 16 * 4 + data.layer * 16;
|
|
8901
|
+
for (let i = 0; i < 16; i++) {
|
|
8902
|
+
const kbr = KILOBIT_RATES[bitrateOffset + i];
|
|
8903
|
+
const size = computeMp3FrameSize(lowSamplingFrequency, data.layer, 1e3 * kbr, data.sampleRate, padding);
|
|
8904
|
+
if (size >= neededBytes) {
|
|
8905
|
+
bitrateIndex = i;
|
|
8906
|
+
break;
|
|
8907
|
+
}
|
|
8908
|
+
}
|
|
8909
|
+
if (bitrateIndex === -1) {
|
|
8910
|
+
throw new Error("No suitable bitrate found.");
|
|
8911
|
+
}
|
|
8912
|
+
const thirdByte = bitrateIndex << 4 | data.frequencyIndex << 2 | padding << 1;
|
|
8913
|
+
const fourthByte = data.channel << 6 | data.modeExtension << 4 | data.copyright << 3 | data.original << 2 | data.emphasis;
|
|
8914
|
+
this.helper[0] = firstByte;
|
|
8915
|
+
this.helper[1] = secondByte;
|
|
8916
|
+
this.helper[2] = thirdByte;
|
|
8917
|
+
this.helper[3] = fourthByte;
|
|
8918
|
+
this.writer.write(this.helper.subarray(0, 4));
|
|
8919
|
+
const xingOffset = getXingOffset(data.mpegVersionId, data.channel);
|
|
8920
|
+
this.writer.seek(startPos + xingOffset);
|
|
8921
|
+
this.writeU32(XING);
|
|
8922
|
+
let flags = 0;
|
|
8923
|
+
if (data.frameCount !== null) {
|
|
8924
|
+
flags |= 1;
|
|
8925
|
+
}
|
|
8926
|
+
if (data.fileSize !== null) {
|
|
8927
|
+
flags |= 2;
|
|
8928
|
+
}
|
|
8929
|
+
if (data.toc !== null) {
|
|
8930
|
+
flags |= 4;
|
|
8931
|
+
}
|
|
8932
|
+
this.writeU32(flags);
|
|
8933
|
+
this.writeU32(data.frameCount ?? 0);
|
|
8934
|
+
this.writeU32(data.fileSize ?? 0);
|
|
8935
|
+
this.writer.write(data.toc ?? new Uint8Array(100));
|
|
8936
|
+
const kilobitRate = KILOBIT_RATES[bitrateOffset + bitrateIndex];
|
|
8937
|
+
const frameSize = computeMp3FrameSize(
|
|
8938
|
+
lowSamplingFrequency,
|
|
8939
|
+
data.layer,
|
|
8940
|
+
1e3 * kilobitRate,
|
|
8941
|
+
data.sampleRate,
|
|
8942
|
+
padding
|
|
8943
|
+
);
|
|
8944
|
+
this.writer.seek(startPos + frameSize);
|
|
8945
|
+
}
|
|
8761
8946
|
writeSynchsafeU32(value) {
|
|
8762
8947
|
this.writeU32(encodeSynchsafe(value));
|
|
8763
8948
|
}
|
|
@@ -8846,54 +9031,6 @@ ${cue.notes ?? ""}`;
|
|
|
8846
9031
|
}
|
|
8847
9032
|
this.writer.write(imageData);
|
|
8848
9033
|
}
|
|
8849
|
-
writeXingFrame(data) {
|
|
8850
|
-
const startPos = this.writer.getPos();
|
|
8851
|
-
const firstByte = 255;
|
|
8852
|
-
const secondByte = 224 | data.mpegVersionId << 3 | data.layer << 1;
|
|
8853
|
-
const bitrateGroup = data.mpegVersionId === 3 ? MPEG_V1_BITRATES : MPEG_V2_BITRATES;
|
|
8854
|
-
const bitrates = bitrateGroup?.[data.layer];
|
|
8855
|
-
if (!bitrates) {
|
|
8856
|
-
throw new Error("Invalid MPEG version and layer combination.");
|
|
8857
|
-
}
|
|
8858
|
-
const sampleRate = SAMPLING_RATES[data.mpegVersionId]?.[data.frequencyIndex];
|
|
8859
|
-
if (!sampleRate || sampleRate === -1) {
|
|
8860
|
-
throw new Error("Invalid MPEG version and frequency index combination.");
|
|
8861
|
-
}
|
|
8862
|
-
const padding = 0;
|
|
8863
|
-
const neededBytes = 155;
|
|
8864
|
-
const bitrateIndex = bitrates.findIndex((kbr) => {
|
|
8865
|
-
return computeMp3FrameSize(data.layer, 1e3 * kbr, sampleRate, padding) >= neededBytes;
|
|
8866
|
-
});
|
|
8867
|
-
if (bitrateIndex === -1) {
|
|
8868
|
-
throw new Error("No suitable bitrate found.");
|
|
8869
|
-
}
|
|
8870
|
-
const thirdByte = bitrateIndex << 4 | data.frequencyIndex << 2 | padding << 1;
|
|
8871
|
-
const fourthByte = data.channel << 6 | data.modeExtension << 4 | data.copyright << 3 | data.original << 2 | data.emphasis;
|
|
8872
|
-
this.helper[0] = firstByte;
|
|
8873
|
-
this.helper[1] = secondByte;
|
|
8874
|
-
this.helper[2] = thirdByte;
|
|
8875
|
-
this.helper[3] = fourthByte;
|
|
8876
|
-
this.writer.write(this.helper.subarray(0, 4));
|
|
8877
|
-
const xingOffset = getXingOffset(data.mpegVersionId, data.channel);
|
|
8878
|
-
this.writer.seek(startPos + xingOffset);
|
|
8879
|
-
this.writeU32(XING);
|
|
8880
|
-
let flags = 0;
|
|
8881
|
-
if (data.frameCount !== null) {
|
|
8882
|
-
flags |= 1;
|
|
8883
|
-
}
|
|
8884
|
-
if (data.fileSize !== null) {
|
|
8885
|
-
flags |= 2;
|
|
8886
|
-
}
|
|
8887
|
-
if (data.toc !== null) {
|
|
8888
|
-
flags |= 4;
|
|
8889
|
-
}
|
|
8890
|
-
this.writeU32(flags);
|
|
8891
|
-
this.writeU32(data.frameCount ?? 0);
|
|
8892
|
-
this.writeU32(data.fileSize ?? 0);
|
|
8893
|
-
this.writer.write(data.toc ?? new Uint8Array(100));
|
|
8894
|
-
const frameSize = computeMp3FrameSize(data.layer, 1e3 * bitrates[bitrateIndex], sampleRate, padding);
|
|
8895
|
-
this.writer.seek(startPos + frameSize);
|
|
8896
|
-
}
|
|
8897
9034
|
};
|
|
8898
9035
|
|
|
8899
9036
|
// src/mp3/mp3-muxer.ts
|
|
@@ -8945,6 +9082,7 @@ ${cue.notes ?? ""}`;
|
|
|
8945
9082
|
mpegVersionId: header.mpegVersionId,
|
|
8946
9083
|
layer: header.layer,
|
|
8947
9084
|
frequencyIndex: header.frequencyIndex,
|
|
9085
|
+
sampleRate: header.sampleRate,
|
|
8948
9086
|
channel: header.channel,
|
|
8949
9087
|
modeExtension: header.modeExtension,
|
|
8950
9088
|
copyright: header.copyright,
|
|
@@ -20790,9 +20928,14 @@ ${cue.notes ?? ""}`;
|
|
|
20790
20928
|
if (!this.firstFrameHeader) {
|
|
20791
20929
|
this.firstFrameHeader = header;
|
|
20792
20930
|
}
|
|
20793
|
-
|
|
20931
|
+
if (header.sampleRate !== this.firstFrameHeader.sampleRate) {
|
|
20932
|
+
console.warn(
|
|
20933
|
+
`MP3 changed sample rate mid-file: ${this.firstFrameHeader.sampleRate} Hz to ${header.sampleRate} Hz. Might be a bug, so please report this file.`
|
|
20934
|
+
);
|
|
20935
|
+
}
|
|
20936
|
+
const sampleDuration = header.audioSamplesInFrame / this.firstFrameHeader.sampleRate;
|
|
20794
20937
|
const sample = {
|
|
20795
|
-
timestamp: this.nextTimestampInSamples /
|
|
20938
|
+
timestamp: this.nextTimestampInSamples / this.firstFrameHeader.sampleRate,
|
|
20796
20939
|
duration: sampleDuration,
|
|
20797
20940
|
dataStart: result.startPos,
|
|
20798
20941
|
dataSize: header.totalSize
|