mediabunny 1.58.1 → 1.59.1
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 +137 -56
- package/dist/bundles/mediabunny.min.cjs +12 -12
- package/dist/bundles/mediabunny.min.mjs +12 -12
- package/dist/bundles/mediabunny.mjs +137 -56
- package/dist/bundles/mediabunny.node.cjs +137 -56
- package/dist/mediabunny.d.ts +2 -0
- package/dist/modules/src/codec-data.d.ts.map +1 -1
- package/dist/modules/src/codec-data.js +15 -0
- package/dist/modules/src/conversion.d.ts.map +1 -1
- package/dist/modules/src/conversion.js +8 -1
- package/dist/modules/src/hls/hls-demuxer.d.ts.map +1 -1
- package/dist/modules/src/hls/hls-demuxer.js +4 -28
- package/dist/modules/src/id3.d.ts.map +1 -1
- package/dist/modules/src/id3.js +18 -0
- package/dist/modules/src/input-track.d.ts.map +1 -1
- package/dist/modules/src/input-track.js +0 -2
- package/dist/modules/src/isobmff/isobmff-boxes.js +13 -0
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-demuxer.js +11 -2
- package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-demuxer.js +40 -2
- package/dist/modules/src/matroska/matroska-muxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-muxer.js +7 -0
- package/dist/modules/src/media-source.js +0 -6
- package/dist/modules/src/metadata.d.ts +2 -0
- package/dist/modules/src/metadata.d.ts.map +1 -1
- package/dist/modules/src/metadata.js +5 -0
- package/dist/modules/src/resample.d.ts +1 -0
- package/dist/modules/src/resample.d.ts.map +1 -1
- package/dist/modules/src/resample.js +20 -9
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/dist/modules/src/wave/wave-muxer.d.ts.map +1 -1
- package/dist/modules/src/wave/wave-muxer.js +1 -0
- package/package.json +1 -1
- package/src/codec-data.ts +11 -0
- package/src/conversion.ts +10 -1
- package/src/hls/hls-demuxer.ts +6 -45
- package/src/id3.ts +15 -0
- package/src/input-track.ts +2 -6
- package/src/isobmff/isobmff-boxes.ts +11 -0
- package/src/isobmff/isobmff-demuxer.ts +11 -4
- package/src/matroska/matroska-demuxer.ts +49 -4
- package/src/matroska/matroska-muxer.ts +5 -0
- package/src/media-source.ts +3 -3
- package/src/metadata.ts +9 -0
- package/src/mpeg-ts/mpeg-ts-demuxer.ts +2 -2
- package/src/resample.ts +25 -11
- package/src/segmented-input.ts +2 -2
- package/src/wave/wave-muxer.ts +1 -0
|
@@ -1491,6 +1491,9 @@ var Mediabunny = (() => {
|
|
|
1491
1491
|
if (tags.date !== void 0 && (!(tags.date instanceof Date) || Number.isNaN(tags.date.getTime()))) {
|
|
1492
1492
|
throw new TypeError("tags.date, when provided, must be a valid Date.");
|
|
1493
1493
|
}
|
|
1494
|
+
if (tags.beatsPerMinute !== void 0 && (!Number.isInteger(tags.beatsPerMinute) || tags.beatsPerMinute <= 0)) {
|
|
1495
|
+
throw new TypeError("tags.beatsPerMinute, when provided, must be a positive integer.");
|
|
1496
|
+
}
|
|
1494
1497
|
if (tags.lyrics !== void 0 && typeof tags.lyrics !== "string") {
|
|
1495
1498
|
throw new TypeError("tags.lyrics, when provided, must be a string.");
|
|
1496
1499
|
}
|
|
@@ -1530,7 +1533,7 @@ var Mediabunny = (() => {
|
|
|
1530
1533
|
}
|
|
1531
1534
|
};
|
|
1532
1535
|
var metadataTagsAreEmpty = (tags) => {
|
|
1533
|
-
return tags.title === void 0 && tags.description === void 0 && tags.artist === void 0 && tags.album === void 0 && tags.albumArtist === void 0 && tags.trackNumber === void 0 && tags.tracksTotal === void 0 && tags.discNumber === void 0 && tags.discsTotal === void 0 && tags.genre === void 0 && tags.date === void 0 && tags.lyrics === void 0 && (!tags.images || tags.images.length === 0) && tags.comment === void 0 && (tags.raw === void 0 || Object.keys(tags.raw).length === 0);
|
|
1536
|
+
return tags.title === void 0 && tags.description === void 0 && tags.artist === void 0 && tags.album === void 0 && tags.albumArtist === void 0 && tags.trackNumber === void 0 && tags.tracksTotal === void 0 && tags.discNumber === void 0 && tags.discsTotal === void 0 && tags.genre === void 0 && tags.beatsPerMinute === void 0 && tags.date === void 0 && tags.lyrics === void 0 && (!tags.images || tags.images.length === 0) && tags.comment === void 0 && (tags.raw === void 0 || Object.keys(tags.raw).length === 0);
|
|
1534
1537
|
};
|
|
1535
1538
|
var DEFAULT_TRACK_DISPOSITION = {
|
|
1536
1539
|
default: true,
|
|
@@ -3814,6 +3817,15 @@ var Mediabunny = (() => {
|
|
|
3814
3817
|
}
|
|
3815
3818
|
;
|
|
3816
3819
|
break;
|
|
3820
|
+
case "BPM":
|
|
3821
|
+
{
|
|
3822
|
+
const bpm = Number.parseInt(value, 10);
|
|
3823
|
+
if (Number.isInteger(bpm) && bpm > 0) {
|
|
3824
|
+
metadataTags.beatsPerMinute ??= bpm;
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
;
|
|
3828
|
+
break;
|
|
3817
3829
|
case "GENRE":
|
|
3818
3830
|
{
|
|
3819
3831
|
metadataTags.genre ??= value;
|
|
@@ -3953,6 +3965,12 @@ var Mediabunny = (() => {
|
|
|
3953
3965
|
}
|
|
3954
3966
|
;
|
|
3955
3967
|
break;
|
|
3968
|
+
case "beatsPerMinute":
|
|
3969
|
+
{
|
|
3970
|
+
addCommentTag("BPM", value.toString());
|
|
3971
|
+
}
|
|
3972
|
+
;
|
|
3973
|
+
break;
|
|
3956
3974
|
case "images":
|
|
3957
3975
|
{
|
|
3958
3976
|
if (!writeImages) {
|
|
@@ -8592,6 +8610,17 @@ var Mediabunny = (() => {
|
|
|
8592
8610
|
}
|
|
8593
8611
|
;
|
|
8594
8612
|
break;
|
|
8613
|
+
case "tmpo":
|
|
8614
|
+
{
|
|
8615
|
+
if (data instanceof Uint8Array && data.length >= 2) {
|
|
8616
|
+
const bpm = toDataView(data).getInt16(0, false);
|
|
8617
|
+
if (bpm > 0) {
|
|
8618
|
+
this.metadataTags.beatsPerMinute ??= bpm;
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
}
|
|
8622
|
+
;
|
|
8623
|
+
break;
|
|
8595
8624
|
case "covr":
|
|
8596
8625
|
case "com.apple.quicktime.artwork":
|
|
8597
8626
|
{
|
|
@@ -9099,7 +9128,6 @@ var Mediabunny = (() => {
|
|
|
9099
9128
|
constructor(internalTrack) {
|
|
9100
9129
|
super(internalTrack);
|
|
9101
9130
|
this.decoderConfigPromise = null;
|
|
9102
|
-
this.internalTrack = internalTrack;
|
|
9103
9131
|
}
|
|
9104
9132
|
getType() {
|
|
9105
9133
|
return "video";
|
|
@@ -9198,7 +9226,6 @@ var Mediabunny = (() => {
|
|
|
9198
9226
|
constructor(internalTrack) {
|
|
9199
9227
|
super(internalTrack);
|
|
9200
9228
|
this.decoderConfigPromise = null;
|
|
9201
|
-
this.internalTrack = internalTrack;
|
|
9202
9229
|
}
|
|
9203
9230
|
getType() {
|
|
9204
9231
|
return "audio";
|
|
@@ -10251,6 +10278,7 @@ var Mediabunny = (() => {
|
|
|
10251
10278
|
};
|
|
10252
10279
|
this.segments.push(this.currentSegment);
|
|
10253
10280
|
let currentPos = segmentDataStart;
|
|
10281
|
+
const visitedSeekHeadPositions = /* @__PURE__ */ new Set();
|
|
10254
10282
|
while (this.currentSegment.elementEndPos === null || currentPos < this.currentSegment.elementEndPos) {
|
|
10255
10283
|
let slice = this.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
|
|
10256
10284
|
if (isThenable(slice)) slice = await slice;
|
|
@@ -10277,6 +10305,9 @@ var Mediabunny = (() => {
|
|
|
10277
10305
|
if (metadataElementIndex !== -1) {
|
|
10278
10306
|
const field = METADATA_ELEMENTS[metadataElementIndex].flag;
|
|
10279
10307
|
this.currentSegment[field] = true;
|
|
10308
|
+
if (id === 290298740 /* SeekHead */) {
|
|
10309
|
+
visitedSeekHeadPositions.add(elementStartPos - segmentDataStart);
|
|
10310
|
+
}
|
|
10280
10311
|
assertDefinedSize(size);
|
|
10281
10312
|
let slice2 = this.reader.requestSlice(dataStartPos, size);
|
|
10282
10313
|
if (isThenable(slice2)) slice2 = await slice2;
|
|
@@ -10305,6 +10336,32 @@ var Mediabunny = (() => {
|
|
|
10305
10336
|
currentPos = dataStartPos + size;
|
|
10306
10337
|
}
|
|
10307
10338
|
}
|
|
10339
|
+
if (this.reader.fileSize !== null) {
|
|
10340
|
+
while (true) {
|
|
10341
|
+
const seekEntry = this.currentSegment.seekEntries.find(
|
|
10342
|
+
(x) => x.id === 290298740 /* SeekHead */ && !visitedSeekHeadPositions.has(x.segmentPosition)
|
|
10343
|
+
);
|
|
10344
|
+
if (!seekEntry) {
|
|
10345
|
+
break;
|
|
10346
|
+
}
|
|
10347
|
+
visitedSeekHeadPositions.add(seekEntry.segmentPosition);
|
|
10348
|
+
let slice = this.reader.requestSliceRange(
|
|
10349
|
+
segmentDataStart + seekEntry.segmentPosition,
|
|
10350
|
+
MIN_HEADER_SIZE,
|
|
10351
|
+
MAX_HEADER_SIZE
|
|
10352
|
+
);
|
|
10353
|
+
if (isThenable(slice)) slice = await slice;
|
|
10354
|
+
if (!slice) continue;
|
|
10355
|
+
const header = readElementHeader(slice);
|
|
10356
|
+
if (!header || header.id !== 290298740 /* SeekHead */) continue;
|
|
10357
|
+
const { size } = header;
|
|
10358
|
+
assertDefinedSize(size);
|
|
10359
|
+
let dataSlice = this.reader.requestSlice(slice.filePos, size);
|
|
10360
|
+
if (isThenable(dataSlice)) dataSlice = await dataSlice;
|
|
10361
|
+
if (!dataSlice) continue;
|
|
10362
|
+
this.readContiguousElements(dataSlice);
|
|
10363
|
+
}
|
|
10364
|
+
}
|
|
10308
10365
|
this.currentSegment.seekEntries.sort((a, b) => a.segmentPosition - b.segmentPosition);
|
|
10309
10366
|
if (this.reader.fileSize !== null) {
|
|
10310
10367
|
for (const seekEntry of this.currentSegment.seekEntries) {
|
|
@@ -11608,6 +11665,15 @@ var Mediabunny = (() => {
|
|
|
11608
11665
|
}
|
|
11609
11666
|
;
|
|
11610
11667
|
break;
|
|
11668
|
+
case "bpm":
|
|
11669
|
+
{
|
|
11670
|
+
const bpm = Number.parseInt(value, 10);
|
|
11671
|
+
if (Number.isInteger(bpm) && bpm > 0) {
|
|
11672
|
+
metadataTags.beatsPerMinute ??= bpm;
|
|
11673
|
+
}
|
|
11674
|
+
}
|
|
11675
|
+
;
|
|
11676
|
+
break;
|
|
11611
11677
|
case "comment":
|
|
11612
11678
|
{
|
|
11613
11679
|
metadataTags.comment ??= value;
|
|
@@ -12060,7 +12126,6 @@ var Mediabunny = (() => {
|
|
|
12060
12126
|
constructor(internalTrack) {
|
|
12061
12127
|
super(internalTrack);
|
|
12062
12128
|
this.decoderConfigPromise = null;
|
|
12063
|
-
this.internalTrack = internalTrack;
|
|
12064
12129
|
}
|
|
12065
12130
|
getType() {
|
|
12066
12131
|
return "video";
|
|
@@ -12154,7 +12219,6 @@ var Mediabunny = (() => {
|
|
|
12154
12219
|
constructor(internalTrack) {
|
|
12155
12220
|
super(internalTrack);
|
|
12156
12221
|
this.decoderConfigPromise = null;
|
|
12157
|
-
this.internalTrack = internalTrack;
|
|
12158
12222
|
}
|
|
12159
12223
|
getType() {
|
|
12160
12224
|
return "audio";
|
|
@@ -19574,16 +19638,6 @@ var Mediabunny = (() => {
|
|
|
19574
19638
|
return;
|
|
19575
19639
|
}
|
|
19576
19640
|
}
|
|
19577
|
-
const videoGroupIds = [
|
|
19578
|
-
...new Set(
|
|
19579
|
-
mediaTags.filter((tag) => tag.attributes.get("type").toLowerCase() === "video").map((tag) => tag.attributes.get("group-id"))
|
|
19580
|
-
)
|
|
19581
|
-
];
|
|
19582
|
-
const audioGroupIds = [
|
|
19583
|
-
...new Set(
|
|
19584
|
-
mediaTags.filter((tag) => tag.attributes.get("type").toLowerCase() === "audio").map((tag) => tag.attributes.get("group-id"))
|
|
19585
|
-
)
|
|
19586
|
-
];
|
|
19587
19641
|
const internalTracksByVariant = await Promise.all(variantStreams.map(async (variantStream, i) => {
|
|
19588
19642
|
const result = [];
|
|
19589
19643
|
const codecsList = variantStream.attributes.get("codecs");
|
|
@@ -19609,11 +19663,6 @@ var Mediabunny = (() => {
|
|
|
19609
19663
|
(x) => AUDIO_CODECS.includes(inferCodecFromCodecString(x))
|
|
19610
19664
|
);
|
|
19611
19665
|
if (videoGroupId !== null && !containsVideoCodecs) {
|
|
19612
|
-
if (!videoGroupIds.includes(videoGroupId)) {
|
|
19613
|
-
throw new Error(
|
|
19614
|
-
`Invalid M3U8 file; variant stream references video group "${videoGroupId}" which is not defined in any #EXT-X-MEDIA tags.`
|
|
19615
|
-
);
|
|
19616
|
-
}
|
|
19617
19666
|
const matchingVideoMediaTag = mediaTags.find((mediaTag) => {
|
|
19618
19667
|
const groupId = mediaTag.attributes.get("group-id");
|
|
19619
19668
|
const type = mediaTag.attributes.get("type");
|
|
@@ -19638,11 +19687,6 @@ var Mediabunny = (() => {
|
|
|
19638
19687
|
}
|
|
19639
19688
|
}
|
|
19640
19689
|
if (audioGroupId !== null && !containsAudioCodecs) {
|
|
19641
|
-
if (!audioGroupIds.includes(audioGroupId)) {
|
|
19642
|
-
throw new Error(
|
|
19643
|
-
`Invalid M3U8 file; variant stream references audio group "${audioGroupId}" which is not defined in any #EXT-X-MEDIA tags.`
|
|
19644
|
-
);
|
|
19645
|
-
}
|
|
19646
19690
|
const matchingAudioMediaTag = mediaTags.find((tag) => {
|
|
19647
19691
|
const groupId = tag.attributes.get("group-id");
|
|
19648
19692
|
const type = tag.attributes.get("type");
|
|
@@ -19719,11 +19763,6 @@ var Mediabunny = (() => {
|
|
|
19719
19763
|
}
|
|
19720
19764
|
});
|
|
19721
19765
|
} else {
|
|
19722
|
-
if (!videoGroupIds.includes(videoGroupId2)) {
|
|
19723
|
-
throw new Error(
|
|
19724
|
-
`Invalid M3U8 file; variant stream references video group "${videoGroupId2}" which is not defined in any #EXT-X-MEDIA tags.`
|
|
19725
|
-
);
|
|
19726
|
-
}
|
|
19727
19766
|
for (const mediaTag of mediaTags) {
|
|
19728
19767
|
const groupId = mediaTag.attributes.get("group-id");
|
|
19729
19768
|
const type = mediaTag.attributes.get("type");
|
|
@@ -19752,8 +19791,8 @@ var Mediabunny = (() => {
|
|
|
19752
19791
|
fullPath: mediaTag.fullPath ?? variantStream.fullPath,
|
|
19753
19792
|
fullCodecString: videoCodecString,
|
|
19754
19793
|
pairingMask: 1n << BigInt(i),
|
|
19755
|
-
peakBitrate: null,
|
|
19756
|
-
averageBitrate: null,
|
|
19794
|
+
peakBitrate: mediaTag.fullPath === null ? bandwidth : null,
|
|
19795
|
+
averageBitrate: mediaTag.fullPath === null ? averageBandwidth : null,
|
|
19757
19796
|
name: mediaTag.attributes.get("name"),
|
|
19758
19797
|
hasOnlyKeyPackets: variantStream.hasOnlyKeyPackets,
|
|
19759
19798
|
info: {
|
|
@@ -19796,11 +19835,6 @@ var Mediabunny = (() => {
|
|
|
19796
19835
|
}
|
|
19797
19836
|
});
|
|
19798
19837
|
} else {
|
|
19799
|
-
if (!audioGroupIds.includes(audioGroupId2)) {
|
|
19800
|
-
throw new Error(
|
|
19801
|
-
`Invalid M3U8 file; variant stream references audio group "${audioGroupId2}" which is not defined in any #EXT-X-MEDIA tags.`
|
|
19802
|
-
);
|
|
19803
|
-
}
|
|
19804
19838
|
for (const mediaTag of mediaTags) {
|
|
19805
19839
|
const groupId = mediaTag.attributes.get("group-id");
|
|
19806
19840
|
const type = mediaTag.attributes.get("type");
|
|
@@ -19821,8 +19855,8 @@ var Mediabunny = (() => {
|
|
|
19821
19855
|
fullPath: mediaTag.fullPath ?? variantStream.fullPath,
|
|
19822
19856
|
fullCodecString: audioCodecString,
|
|
19823
19857
|
pairingMask: 1n << BigInt(i),
|
|
19824
|
-
peakBitrate: null,
|
|
19825
|
-
averageBitrate: null,
|
|
19858
|
+
peakBitrate: mediaTag.fullPath === null ? bandwidth : null,
|
|
19859
|
+
averageBitrate: mediaTag.fullPath === null ? averageBandwidth : null,
|
|
19826
19860
|
name: mediaTag.attributes.get("name"),
|
|
19827
19861
|
hasOnlyKeyPackets: variantStream.hasOnlyKeyPackets,
|
|
19828
19862
|
info: {
|
|
@@ -26088,7 +26122,6 @@ var Mediabunny = (() => {
|
|
|
26088
26122
|
super(input, backing);
|
|
26089
26123
|
/** @internal */
|
|
26090
26124
|
this._pixelAspectRatioCache = null;
|
|
26091
|
-
this._backing = backing;
|
|
26092
26125
|
}
|
|
26093
26126
|
get type() {
|
|
26094
26127
|
return "video";
|
|
@@ -26427,7 +26460,6 @@ var Mediabunny = (() => {
|
|
|
26427
26460
|
/** @internal */
|
|
26428
26461
|
constructor(input, backing) {
|
|
26429
26462
|
super(input, backing);
|
|
26430
|
-
this._backing = backing;
|
|
26431
26463
|
}
|
|
26432
26464
|
get type() {
|
|
26433
26465
|
return "audio";
|
|
@@ -27907,6 +27939,17 @@ var Mediabunny = (() => {
|
|
|
27907
27939
|
}
|
|
27908
27940
|
;
|
|
27909
27941
|
break;
|
|
27942
|
+
case "TBPM":
|
|
27943
|
+
case "TBP":
|
|
27944
|
+
{
|
|
27945
|
+
const bpmText = reader.readId3V2EncodingAndText(frameEndPos);
|
|
27946
|
+
const bpm = Number.parseInt(bpmText, 10);
|
|
27947
|
+
if (Number.isInteger(bpm)) {
|
|
27948
|
+
tags.beatsPerMinute ??= bpm;
|
|
27949
|
+
}
|
|
27950
|
+
}
|
|
27951
|
+
;
|
|
27952
|
+
break;
|
|
27910
27953
|
case "USLT":
|
|
27911
27954
|
case "ULT":
|
|
27912
27955
|
{
|
|
@@ -28236,6 +28279,13 @@ var Mediabunny = (() => {
|
|
|
28236
28279
|
}
|
|
28237
28280
|
;
|
|
28238
28281
|
break;
|
|
28282
|
+
case "beatsPerMinute":
|
|
28283
|
+
{
|
|
28284
|
+
this.writeId3V2TextFrame("TBPM", `${value}`);
|
|
28285
|
+
writtenTags.add("TBPM");
|
|
28286
|
+
}
|
|
28287
|
+
;
|
|
28288
|
+
break;
|
|
28239
28289
|
case "lyrics":
|
|
28240
28290
|
{
|
|
28241
28291
|
this.writeId3V2LyricsFrame(value);
|
|
@@ -30255,6 +30305,7 @@ var Mediabunny = (() => {
|
|
|
30255
30305
|
case "discsTotal":
|
|
30256
30306
|
case "trackNumber":
|
|
30257
30307
|
case "tracksTotal":
|
|
30308
|
+
case "beatsPerMinute":
|
|
30258
30309
|
case "images":
|
|
30259
30310
|
{
|
|
30260
30311
|
}
|
|
@@ -30337,6 +30388,20 @@ var Mediabunny = (() => {
|
|
|
30337
30388
|
}
|
|
30338
30389
|
;
|
|
30339
30390
|
break;
|
|
30391
|
+
case "beatsPerMinute":
|
|
30392
|
+
{
|
|
30393
|
+
if (!isMdta) {
|
|
30394
|
+
pairs.push({ key: "tmpo", value: box("data", [
|
|
30395
|
+
u32(21),
|
|
30396
|
+
// Type indicator
|
|
30397
|
+
u32(0),
|
|
30398
|
+
// Locale indicator
|
|
30399
|
+
u16(value)
|
|
30400
|
+
]) });
|
|
30401
|
+
}
|
|
30402
|
+
}
|
|
30403
|
+
;
|
|
30404
|
+
break;
|
|
30340
30405
|
case "lyrics":
|
|
30341
30406
|
{
|
|
30342
30407
|
pairs.push({ key: isMdta ? "lyrics" : "\xA9lyr", value: dataStringBoxLong(value) });
|
|
@@ -32800,6 +32865,13 @@ var Mediabunny = (() => {
|
|
|
32800
32865
|
}
|
|
32801
32866
|
;
|
|
32802
32867
|
break;
|
|
32868
|
+
case "beatsPerMinute":
|
|
32869
|
+
{
|
|
32870
|
+
addSimpleTag("BPM", value.toString());
|
|
32871
|
+
writtenTags.add("BPM");
|
|
32872
|
+
}
|
|
32873
|
+
;
|
|
32874
|
+
break;
|
|
32803
32875
|
case "comment":
|
|
32804
32876
|
{
|
|
32805
32877
|
addSimpleTag("COMMENT", value);
|
|
@@ -34904,6 +34976,7 @@ ${cue.notes ?? ""}`;
|
|
|
34904
34976
|
case "discNumber":
|
|
34905
34977
|
case "tracksTotal":
|
|
34906
34978
|
case "discsTotal":
|
|
34979
|
+
case "beatsPerMinute":
|
|
34907
34980
|
case "description":
|
|
34908
34981
|
case "lyrics":
|
|
34909
34982
|
case "images":
|
|
@@ -34999,7 +35072,6 @@ ${cue.notes ?? ""}`;
|
|
|
34999
35072
|
this.onSample = options.onSample;
|
|
35000
35073
|
this.bufferSizeInFrames = Math.floor(this.targetSampleRate * 5);
|
|
35001
35074
|
this.bufferSizeInSamples = this.bufferSizeInFrames * this.targetNumberOfChannels;
|
|
35002
|
-
this.outputBuffer = new Float32Array(this.bufferSizeInSamples);
|
|
35003
35075
|
}
|
|
35004
35076
|
/**
|
|
35005
35077
|
* Sets up the channel mixer to handle up/downmixing in the case where input and output channel counts don't match.
|
|
@@ -35090,6 +35162,11 @@ ${cue.notes ?? ""}`;
|
|
|
35090
35162
|
this.sourceSampleRate = audioSample.sampleRate;
|
|
35091
35163
|
this.sourceNumberOfChannels = audioSample.numberOfChannels;
|
|
35092
35164
|
this.startTime = audioSample.timestamp;
|
|
35165
|
+
const overflowFrames = Math.ceil(this.targetSampleRate / this.sourceSampleRate);
|
|
35166
|
+
this.bufferCapacityInFrames = this.bufferSizeInFrames + overflowFrames;
|
|
35167
|
+
this.outputBuffer = new Float32Array(
|
|
35168
|
+
this.bufferCapacityInFrames * this.targetNumberOfChannels
|
|
35169
|
+
);
|
|
35093
35170
|
this.tempSourceBuffer = new Float32Array(this.sourceSampleRate * this.sourceNumberOfChannels);
|
|
35094
35171
|
this.doChannelMixerSetup();
|
|
35095
35172
|
}
|
|
@@ -35107,12 +35184,12 @@ ${cue.notes ?? ""}`;
|
|
|
35107
35184
|
if (outputFrame < this.bufferStartFrame) {
|
|
35108
35185
|
continue;
|
|
35109
35186
|
}
|
|
35110
|
-
while (outputFrame >= this.bufferStartFrame + this.
|
|
35187
|
+
while (outputFrame >= this.bufferStartFrame + this.bufferCapacityInFrames) {
|
|
35111
35188
|
await this.finalizeCurrentBuffer();
|
|
35112
35189
|
this.bufferStartFrame += this.bufferSizeInFrames;
|
|
35113
35190
|
}
|
|
35114
35191
|
const bufferFrameIndex = outputFrame - this.bufferStartFrame;
|
|
35115
|
-
assert(bufferFrameIndex < this.
|
|
35192
|
+
assert(bufferFrameIndex < this.bufferCapacityInFrames);
|
|
35116
35193
|
const outputTime = outputFrame / this.targetSampleRate;
|
|
35117
35194
|
const inputTime = outputTime - inputStartTime;
|
|
35118
35195
|
const sourcePosition = inputTime * this.sourceSampleRate;
|
|
@@ -35144,7 +35221,7 @@ ${cue.notes ?? ""}`;
|
|
|
35144
35221
|
return;
|
|
35145
35222
|
}
|
|
35146
35223
|
assert(this.startTime !== null);
|
|
35147
|
-
const samplesWritten = (this.maxWrittenFrame + 1) * this.targetNumberOfChannels;
|
|
35224
|
+
const samplesWritten = Math.min(this.maxWrittenFrame + 1, this.bufferSizeInFrames) * this.targetNumberOfChannels;
|
|
35148
35225
|
const outputData = new Float32Array(samplesWritten);
|
|
35149
35226
|
outputData.set(this.outputBuffer.subarray(0, samplesWritten));
|
|
35150
35227
|
const audioSample = new AudioSample({
|
|
@@ -35155,11 +35232,15 @@ ${cue.notes ?? ""}`;
|
|
|
35155
35232
|
data: outputData
|
|
35156
35233
|
});
|
|
35157
35234
|
await this.onSample(audioSample);
|
|
35158
|
-
this.outputBuffer.
|
|
35159
|
-
this.
|
|
35235
|
+
this.outputBuffer.copyWithin(0, this.bufferSizeInSamples);
|
|
35236
|
+
this.outputBuffer.fill(0, this.outputBuffer.length - this.bufferSizeInSamples);
|
|
35237
|
+
this.maxWrittenFrame = this.maxWrittenFrame >= this.bufferSizeInFrames ? this.maxWrittenFrame - this.bufferSizeInFrames : null;
|
|
35160
35238
|
}
|
|
35161
|
-
finalize() {
|
|
35162
|
-
|
|
35239
|
+
async finalize() {
|
|
35240
|
+
while (this.maxWrittenFrame !== null) {
|
|
35241
|
+
await this.finalizeCurrentBuffer();
|
|
35242
|
+
this.bufferStartFrame += this.bufferSizeInFrames;
|
|
35243
|
+
}
|
|
35163
35244
|
}
|
|
35164
35245
|
};
|
|
35165
35246
|
|
|
@@ -35240,8 +35321,6 @@ ${cue.notes ?? ""}`;
|
|
|
35240
35321
|
/** Internal constructor. */
|
|
35241
35322
|
constructor(codec) {
|
|
35242
35323
|
super();
|
|
35243
|
-
/** @internal */
|
|
35244
|
-
this._connectedTrack = null;
|
|
35245
35324
|
if (!VIDEO_CODECS.includes(codec)) {
|
|
35246
35325
|
throw new TypeError(`Invalid video codec '${codec}'. Must be one of: ${VIDEO_CODECS.join(", ")}.`);
|
|
35247
35326
|
}
|
|
@@ -36382,8 +36461,6 @@ ${cue.notes ?? ""}`;
|
|
|
36382
36461
|
/** Internal constructor. */
|
|
36383
36462
|
constructor(codec) {
|
|
36384
36463
|
super();
|
|
36385
|
-
/** @internal */
|
|
36386
|
-
this._connectedTrack = null;
|
|
36387
36464
|
if (!AUDIO_CODECS.includes(codec)) {
|
|
36388
36465
|
throw new TypeError(`Invalid audio codec '${codec}'. Must be one of: ${AUDIO_CODECS.join(", ")}.`);
|
|
36389
36466
|
}
|
|
@@ -37264,8 +37341,6 @@ ${cue.notes ?? ""}`;
|
|
|
37264
37341
|
/** Internal constructor. */
|
|
37265
37342
|
constructor(codec) {
|
|
37266
37343
|
super();
|
|
37267
|
-
/** @internal */
|
|
37268
|
-
this._connectedTrack = null;
|
|
37269
37344
|
if (!SUBTITLE_CODECS.includes(codec)) {
|
|
37270
37345
|
throw new TypeError(`Invalid subtitle codec '${codec}'. Must be one of: ${SUBTITLE_CODECS.join(", ")}.`);
|
|
37271
37346
|
}
|
|
@@ -40927,6 +41002,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40927
41002
|
const sink = new EncodedPacketSink(track);
|
|
40928
41003
|
const decoderConfig = await track.getDecoderConfig();
|
|
40929
41004
|
const meta = { decoderConfig: decoderConfig ?? void 0 };
|
|
41005
|
+
let maxTimestamp = null;
|
|
40930
41006
|
if (copyStartPacket) for await (const packet of sink.packets(copyStartPacket)) {
|
|
40931
41007
|
if (this._state === "canceled") {
|
|
40932
41008
|
break;
|
|
@@ -40937,8 +41013,13 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40937
41013
|
if (this._copyBoundaryPolicy === "shrink" && packet.timestamp + packet.duration > this._endTimestamp) {
|
|
40938
41014
|
break;
|
|
40939
41015
|
}
|
|
41016
|
+
const packetTimestamp = packet.timestamp + this._timestampOffset;
|
|
41017
|
+
if (maxTimestamp !== null && packetTimestamp < maxTimestamp) {
|
|
41018
|
+
continue;
|
|
41019
|
+
}
|
|
41020
|
+
maxTimestamp = packetTimestamp;
|
|
40940
41021
|
const modifiedPacket = packet.clone({
|
|
40941
|
-
timestamp:
|
|
41022
|
+
timestamp: packetTimestamp,
|
|
40942
41023
|
duration: packet.duration
|
|
40943
41024
|
});
|
|
40944
41025
|
this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
|