mediabunny 1.1.0 → 1.2.0
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 +85 -17
- package/dist/bundles/mediabunny.min.cjs +3 -3
- package/dist/bundles/mediabunny.min.mjs +3 -3
- package/dist/bundles/mediabunny.mjs +85 -17
- package/dist/mediabunny.d.ts +5 -0
- package/dist/modules/input-format.js +1 -1
- package/dist/modules/matroska/matroska-demuxer.js +3 -3
- package/dist/modules/output-format.d.ts +5 -0
- package/dist/modules/output-format.d.ts.map +1 -1
- package/dist/modules/output-format.js +3 -0
- package/dist/modules/wave/riff-reader.d.ts +1 -0
- package/dist/modules/wave/riff-reader.d.ts.map +1 -1
- package/dist/modules/wave/riff-reader.js +13 -0
- package/dist/modules/wave/riff-writer.d.ts +2 -1
- package/dist/modules/wave/riff-writer.d.ts.map +1 -1
- package/dist/modules/wave/riff-writer.js +8 -3
- package/dist/modules/wave/wave-demuxer.d.ts.map +1 -1
- package/dist/modules/wave/wave-demuxer.js +18 -3
- package/dist/modules/wave/wave-muxer.d.ts +3 -0
- package/dist/modules/wave/wave-muxer.d.ts.map +1 -1
- package/dist/modules/wave/wave-muxer.js +50 -9
- package/package.json +1 -1
- package/src/input-format.ts +1 -1
- package/src/matroska/matroska-demuxer.ts +3 -3
- package/src/output-format.ts +9 -0
- package/src/wave/riff-reader.ts +15 -0
- package/src/wave/riff-writer.ts +9 -3
- package/src/wave/wave-demuxer.ts +24 -3
- package/src/wave/wave-muxer.ts +57 -9
|
@@ -9411,6 +9411,18 @@ ${cue.notes ?? ""}`;
|
|
|
9411
9411
|
this.pos += 4;
|
|
9412
9412
|
return view2.getUint32(offset, this.littleEndian);
|
|
9413
9413
|
}
|
|
9414
|
+
readU64() {
|
|
9415
|
+
let low;
|
|
9416
|
+
let high;
|
|
9417
|
+
if (this.littleEndian) {
|
|
9418
|
+
low = this.readU32();
|
|
9419
|
+
high = this.readU32();
|
|
9420
|
+
} else {
|
|
9421
|
+
high = this.readU32();
|
|
9422
|
+
low = this.readU32();
|
|
9423
|
+
}
|
|
9424
|
+
return high * 4294967296 + low;
|
|
9425
|
+
}
|
|
9414
9426
|
readAscii(length) {
|
|
9415
9427
|
const { view: view2, offset } = this.reader.getViewAndOffset(this.pos, this.pos + length);
|
|
9416
9428
|
this.pos += length;
|
|
@@ -9438,25 +9450,38 @@ ${cue.notes ?? ""}`;
|
|
|
9438
9450
|
return this.metadataPromise ??= (async () => {
|
|
9439
9451
|
const actualFileSize = await this.metadataReader.reader.source.getSize();
|
|
9440
9452
|
const riffType = this.metadataReader.readAscii(4);
|
|
9441
|
-
this.metadataReader.littleEndian = riffType
|
|
9442
|
-
const
|
|
9453
|
+
this.metadataReader.littleEndian = riffType !== "RIFX";
|
|
9454
|
+
const isRf64 = riffType === "RF64";
|
|
9455
|
+
const outerChunkSize = this.metadataReader.readU32();
|
|
9456
|
+
let totalFileSize = isRf64 ? actualFileSize : Math.min(outerChunkSize + 8, actualFileSize);
|
|
9443
9457
|
const format = this.metadataReader.readAscii(4);
|
|
9444
9458
|
if (format !== "WAVE") {
|
|
9445
9459
|
throw new Error("Invalid WAVE file - wrong format");
|
|
9446
9460
|
}
|
|
9447
9461
|
this.metadataReader.pos = 12;
|
|
9462
|
+
let chunksRead = 0;
|
|
9463
|
+
let dataChunkSize = null;
|
|
9448
9464
|
while (this.metadataReader.pos < totalFileSize) {
|
|
9449
9465
|
await this.metadataReader.reader.loadRange(this.metadataReader.pos, this.metadataReader.pos + 8);
|
|
9450
9466
|
const chunkId = this.metadataReader.readAscii(4);
|
|
9451
9467
|
const chunkSize = this.metadataReader.readU32();
|
|
9452
9468
|
const startPos = this.metadataReader.pos;
|
|
9469
|
+
if (isRf64 && chunksRead === 0 && chunkId !== "ds64") {
|
|
9470
|
+
throw new Error('Invalid RF64 file: First chunk must be "ds64".');
|
|
9471
|
+
}
|
|
9453
9472
|
if (chunkId === "fmt ") {
|
|
9454
9473
|
await this.parseFmtChunk(chunkSize);
|
|
9455
9474
|
} else if (chunkId === "data") {
|
|
9475
|
+
dataChunkSize ??= chunkSize;
|
|
9456
9476
|
this.dataStart = this.metadataReader.pos;
|
|
9457
|
-
this.dataSize = Math.min(
|
|
9477
|
+
this.dataSize = Math.min(dataChunkSize, totalFileSize - this.dataStart);
|
|
9478
|
+
} else if (chunkId === "ds64") {
|
|
9479
|
+
const riffChunkSize = this.metadataReader.readU64();
|
|
9480
|
+
dataChunkSize = this.metadataReader.readU64();
|
|
9481
|
+
totalFileSize = Math.min(riffChunkSize + 8, actualFileSize);
|
|
9458
9482
|
}
|
|
9459
9483
|
this.metadataReader.pos = startPos + chunkSize + (chunkSize & 1);
|
|
9484
|
+
chunksRead++;
|
|
9460
9485
|
}
|
|
9461
9486
|
if (!this.audioInfo) {
|
|
9462
9487
|
throw new Error('Invalid WAVE file - missing "fmt " chunk');
|
|
@@ -9651,13 +9676,18 @@ ${cue.notes ?? ""}`;
|
|
|
9651
9676
|
this.helper = new Uint8Array(8);
|
|
9652
9677
|
this.helperView = new DataView(this.helper.buffer);
|
|
9653
9678
|
}
|
|
9679
|
+
writeU16(value) {
|
|
9680
|
+
this.helperView.setUint16(0, value, true);
|
|
9681
|
+
this.writer.write(this.helper.subarray(0, 2));
|
|
9682
|
+
}
|
|
9654
9683
|
writeU32(value) {
|
|
9655
9684
|
this.helperView.setUint32(0, value, true);
|
|
9656
9685
|
this.writer.write(this.helper.subarray(0, 4));
|
|
9657
9686
|
}
|
|
9658
|
-
|
|
9659
|
-
this.helperView.
|
|
9660
|
-
this.
|
|
9687
|
+
writeU64(value) {
|
|
9688
|
+
this.helperView.setUint32(0, value, true);
|
|
9689
|
+
this.helperView.setUint32(4, Math.floor(value / 2 ** 32), true);
|
|
9690
|
+
this.writer.write(this.helper);
|
|
9661
9691
|
}
|
|
9662
9692
|
writeAscii(text) {
|
|
9663
9693
|
this.writer.write(new TextEncoder().encode(text));
|
|
@@ -9670,9 +9700,12 @@ ${cue.notes ?? ""}`;
|
|
|
9670
9700
|
super(output);
|
|
9671
9701
|
this.headerWritten = false;
|
|
9672
9702
|
this.dataSize = 0;
|
|
9703
|
+
this.sampleRate = null;
|
|
9704
|
+
this.sampleCount = 0;
|
|
9673
9705
|
this.format = format;
|
|
9674
9706
|
this.writer = output._writer;
|
|
9675
9707
|
this.riffWriter = new RiffWriter(output._writer);
|
|
9708
|
+
this.isRf64 = !!format._options.large;
|
|
9676
9709
|
}
|
|
9677
9710
|
async start() {
|
|
9678
9711
|
}
|
|
@@ -9690,11 +9723,18 @@ ${cue.notes ?? ""}`;
|
|
|
9690
9723
|
assert(meta);
|
|
9691
9724
|
assert(meta.decoderConfig);
|
|
9692
9725
|
this.writeHeader(track, meta.decoderConfig);
|
|
9726
|
+
this.sampleRate = meta.decoderConfig.sampleRate;
|
|
9693
9727
|
this.headerWritten = true;
|
|
9694
9728
|
}
|
|
9695
9729
|
this.validateAndNormalizeTimestamp(track, packet.timestamp, packet.type === "key");
|
|
9730
|
+
if (!this.isRf64 && this.writer.getPos() + packet.data.byteLength >= 2 ** 32) {
|
|
9731
|
+
throw new Error(
|
|
9732
|
+
"Adding more audio data would exceed the maximum RIFF size of 4 GiB. To write larger files, use RF64 by setting `large: true` in the WavOutputFormatOptions."
|
|
9733
|
+
);
|
|
9734
|
+
}
|
|
9696
9735
|
this.writer.write(packet.data);
|
|
9697
9736
|
this.dataSize += packet.data.byteLength;
|
|
9737
|
+
this.sampleCount += Math.round(packet.duration * this.sampleRate);
|
|
9698
9738
|
await this.writer.flush();
|
|
9699
9739
|
} finally {
|
|
9700
9740
|
release();
|
|
@@ -9722,9 +9762,21 @@ ${cue.notes ?? ""}`;
|
|
|
9722
9762
|
const channels = config.numberOfChannels;
|
|
9723
9763
|
const sampleRate = config.sampleRate;
|
|
9724
9764
|
const blockSize = pcmInfo.sampleSize * channels;
|
|
9725
|
-
this.riffWriter.writeAscii("RIFF");
|
|
9726
|
-
this.
|
|
9765
|
+
this.riffWriter.writeAscii(this.isRf64 ? "RF64" : "RIFF");
|
|
9766
|
+
if (this.isRf64) {
|
|
9767
|
+
this.riffWriter.writeU32(4294967295);
|
|
9768
|
+
} else {
|
|
9769
|
+
this.riffWriter.writeU32(0);
|
|
9770
|
+
}
|
|
9727
9771
|
this.riffWriter.writeAscii("WAVE");
|
|
9772
|
+
if (this.isRf64) {
|
|
9773
|
+
this.riffWriter.writeAscii("ds64");
|
|
9774
|
+
this.riffWriter.writeU32(28);
|
|
9775
|
+
this.riffWriter.writeU64(0);
|
|
9776
|
+
this.riffWriter.writeU64(0);
|
|
9777
|
+
this.riffWriter.writeU64(0);
|
|
9778
|
+
this.riffWriter.writeU32(0);
|
|
9779
|
+
}
|
|
9728
9780
|
this.riffWriter.writeAscii("fmt ");
|
|
9729
9781
|
this.riffWriter.writeU32(16);
|
|
9730
9782
|
this.riffWriter.writeU16(format);
|
|
@@ -9734,7 +9786,11 @@ ${cue.notes ?? ""}`;
|
|
|
9734
9786
|
this.riffWriter.writeU16(blockSize);
|
|
9735
9787
|
this.riffWriter.writeU16(8 * pcmInfo.sampleSize);
|
|
9736
9788
|
this.riffWriter.writeAscii("data");
|
|
9737
|
-
this.
|
|
9789
|
+
if (this.isRf64) {
|
|
9790
|
+
this.riffWriter.writeU32(4294967295);
|
|
9791
|
+
} else {
|
|
9792
|
+
this.riffWriter.writeU32(0);
|
|
9793
|
+
}
|
|
9738
9794
|
if (this.format._options.onHeader) {
|
|
9739
9795
|
const { data, start } = this.writer.stopTrackingWrites();
|
|
9740
9796
|
this.format._options.onHeader(data, start);
|
|
@@ -9743,10 +9799,19 @@ ${cue.notes ?? ""}`;
|
|
|
9743
9799
|
async finalize() {
|
|
9744
9800
|
const release = await this.mutex.acquire();
|
|
9745
9801
|
const endPos = this.writer.getPos();
|
|
9746
|
-
this.
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9802
|
+
if (this.isRf64) {
|
|
9803
|
+
this.writer.seek(20);
|
|
9804
|
+
this.riffWriter.writeU64(endPos - 8);
|
|
9805
|
+
this.writer.seek(28);
|
|
9806
|
+
this.riffWriter.writeU64(this.dataSize);
|
|
9807
|
+
this.writer.seek(36);
|
|
9808
|
+
this.riffWriter.writeU64(this.sampleCount);
|
|
9809
|
+
} else {
|
|
9810
|
+
this.writer.seek(4);
|
|
9811
|
+
this.riffWriter.writeU32(endPos - 8);
|
|
9812
|
+
this.writer.seek(40);
|
|
9813
|
+
this.riffWriter.writeU32(this.dataSize);
|
|
9814
|
+
}
|
|
9750
9815
|
this.writer.seek(endPos);
|
|
9751
9816
|
release();
|
|
9752
9817
|
}
|
|
@@ -10005,6 +10070,9 @@ ${cue.notes ?? ""}`;
|
|
|
10005
10070
|
if (!options || typeof options !== "object") {
|
|
10006
10071
|
throw new TypeError("options must be an object.");
|
|
10007
10072
|
}
|
|
10073
|
+
if (options.large !== void 0 && typeof options.large !== "boolean") {
|
|
10074
|
+
throw new TypeError("options.large, when provided, must be a boolean.");
|
|
10075
|
+
}
|
|
10008
10076
|
if (options.onHeader !== void 0 && typeof options.onHeader !== "function") {
|
|
10009
10077
|
throw new TypeError("options.onHeader, when provided, must be a function.");
|
|
10010
10078
|
}
|
|
@@ -13649,7 +13717,7 @@ ${cue.notes ?? ""}`;
|
|
|
13649
13717
|
return this.readMetadataPromise ??= (async () => {
|
|
13650
13718
|
this.metadataReader.pos = 0;
|
|
13651
13719
|
const fileSize = await this.input.source.getSize();
|
|
13652
|
-
while (this.metadataReader.pos
|
|
13720
|
+
while (this.metadataReader.pos <= fileSize - MIN_HEADER_SIZE) {
|
|
13653
13721
|
await this.metadataReader.reader.loadRange(
|
|
13654
13722
|
this.metadataReader.pos,
|
|
13655
13723
|
this.metadataReader.pos + MAX_HEADER_SIZE
|
|
@@ -13898,7 +13966,7 @@ ${cue.notes ?? ""}`;
|
|
|
13898
13966
|
}
|
|
13899
13967
|
readContiguousElements(reader, totalSize) {
|
|
13900
13968
|
const startIndex = reader.pos;
|
|
13901
|
-
while (reader.pos - startIndex
|
|
13969
|
+
while (reader.pos - startIndex <= totalSize - MIN_HEADER_SIZE) {
|
|
13902
13970
|
this.traverseElement(reader);
|
|
13903
13971
|
}
|
|
13904
13972
|
}
|
|
@@ -14712,7 +14780,7 @@ ${cue.notes ?? ""}`;
|
|
|
14712
14780
|
size = (nextElementPos ?? segment.elementEndPos) - dataStartPos;
|
|
14713
14781
|
}
|
|
14714
14782
|
const endPos = dataStartPos + size;
|
|
14715
|
-
if (endPos
|
|
14783
|
+
if (endPos > segment.elementEndPos - MIN_HEADER_SIZE) {
|
|
14716
14784
|
break;
|
|
14717
14785
|
} else {
|
|
14718
14786
|
clusterReader.pos = endPos;
|
|
@@ -15973,7 +16041,7 @@ ${cue.notes ?? ""}`;
|
|
|
15973
16041
|
}
|
|
15974
16042
|
const riffReader = new RiffReader(input._mainReader);
|
|
15975
16043
|
const riffType = riffReader.readAscii(4);
|
|
15976
|
-
if (riffType !== "RIFF" && riffType !== "RIFX") {
|
|
16044
|
+
if (riffType !== "RIFF" && riffType !== "RIFX" && riffType !== "RF64") {
|
|
15977
16045
|
return false;
|
|
15978
16046
|
}
|
|
15979
16047
|
riffReader.pos = 8;
|