mediabunny 1.42.0 → 1.43.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 +242 -44
- package/dist/bundles/mediabunny.min.cjs +14 -14
- package/dist/bundles/mediabunny.min.mjs +14 -14
- package/dist/bundles/mediabunny.mjs +242 -44
- package/dist/bundles/mediabunny.node.cjs +242 -44
- package/dist/mediabunny.d.ts +12 -0
- package/dist/modules/src/codec-data.d.ts +2 -0
- package/dist/modules/src/codec-data.d.ts.map +1 -1
- package/dist/modules/src/codec-data.js +103 -0
- package/dist/modules/src/conversion.d.ts +7 -0
- package/dist/modules/src/conversion.d.ts.map +1 -1
- package/dist/modules/src/conversion.js +25 -11
- package/dist/modules/src/encode.d.ts +5 -0
- package/dist/modules/src/encode.d.ts.map +1 -1
- package/dist/modules/src/encode.js +5 -1
- package/dist/modules/src/index.d.ts +20 -20
- package/dist/modules/src/index.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts +2 -0
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.js +36 -4
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts +4 -2
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.js +47 -21
- package/dist/modules/src/media-sink.d.ts.map +1 -1
- package/dist/modules/src/media-sink.js +20 -11
- package/dist/modules/src/media-source.d.ts.map +1 -1
- package/dist/modules/src/media-source.js +14 -1
- package/dist/modules/src/sample.d.ts +2 -0
- package/dist/modules/src/sample.d.ts.map +1 -1
- package/dist/modules/src/sample.js +27 -0
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/codec-data.ts +112 -0
- package/src/conversion.ts +45 -11
- package/src/encode.ts +12 -1
- package/src/index.ts +82 -82
- package/src/isobmff/isobmff-boxes.ts +46 -8
- package/src/isobmff/isobmff-muxer.ts +71 -28
- package/src/media-sink.ts +20 -11
- package/src/media-source.ts +26 -1
- package/src/sample.ts +30 -0
|
@@ -3064,6 +3064,16 @@ var Mediabunny = (() => {
|
|
|
3064
3064
|
bitstream.skipBits(5);
|
|
3065
3065
|
bitstream.skipBits(5);
|
|
3066
3066
|
};
|
|
3067
|
+
var concatHevcNalUnits = (nalUnits, decoderConfig) => {
|
|
3068
|
+
if (decoderConfig.description) {
|
|
3069
|
+
const bytes2 = toUint8Array(decoderConfig.description);
|
|
3070
|
+
const lengthSizeMinusOne = bytes2[21] & 3;
|
|
3071
|
+
const lengthSize = lengthSizeMinusOne + 1;
|
|
3072
|
+
return concatNalUnitsInLengthPrefixed(nalUnits, lengthSize);
|
|
3073
|
+
} else {
|
|
3074
|
+
return concatNalUnitsInAnnexB(nalUnits);
|
|
3075
|
+
}
|
|
3076
|
+
};
|
|
3067
3077
|
var iterateHevcNalUnits = (packetData, decoderConfig) => {
|
|
3068
3078
|
if (decoderConfig.description) {
|
|
3069
3079
|
const bytes2 = toUint8Array(decoderConfig.description);
|
|
@@ -3663,6 +3673,70 @@ var Mediabunny = (() => {
|
|
|
3663
3673
|
return null;
|
|
3664
3674
|
}
|
|
3665
3675
|
};
|
|
3676
|
+
var sanitizeHevcPacketForChromium = (packetData, decoderConfig) => {
|
|
3677
|
+
const removedNalUnits = /* @__PURE__ */ new Set();
|
|
3678
|
+
let orderState = 0 /* audAllowed */;
|
|
3679
|
+
for (const loc of iterateHevcNalUnits(packetData, decoderConfig)) {
|
|
3680
|
+
if (orderState === 4 /* noMoreDataAllowed */) {
|
|
3681
|
+
removedNalUnits.add(loc.offset);
|
|
3682
|
+
continue;
|
|
3683
|
+
}
|
|
3684
|
+
const type = extractNalUnitTypeForHevc(packetData[loc.offset]);
|
|
3685
|
+
if (orderState === 3 /* eoBitstreamAllowed */ && type !== 37) {
|
|
3686
|
+
removedNalUnits.add(loc.offset);
|
|
3687
|
+
continue;
|
|
3688
|
+
}
|
|
3689
|
+
let remove = false;
|
|
3690
|
+
if (type === 35) {
|
|
3691
|
+
if (orderState > 0 /* audAllowed */) {
|
|
3692
|
+
remove = true;
|
|
3693
|
+
} else {
|
|
3694
|
+
orderState = 1 /* beforeFirstVcl */;
|
|
3695
|
+
}
|
|
3696
|
+
} else if (type <= 31) {
|
|
3697
|
+
if (orderState > 2 /* afterFirstVcl */) {
|
|
3698
|
+
remove = true;
|
|
3699
|
+
} else {
|
|
3700
|
+
orderState = 2 /* afterFirstVcl */;
|
|
3701
|
+
}
|
|
3702
|
+
} else if (type === 36) {
|
|
3703
|
+
if (orderState !== 2 /* afterFirstVcl */) {
|
|
3704
|
+
remove = true;
|
|
3705
|
+
} else {
|
|
3706
|
+
orderState = 3 /* eoBitstreamAllowed */;
|
|
3707
|
+
}
|
|
3708
|
+
} else if (type === 37) {
|
|
3709
|
+
if (orderState < 2 /* afterFirstVcl */) {
|
|
3710
|
+
remove = true;
|
|
3711
|
+
} else {
|
|
3712
|
+
orderState = 4 /* noMoreDataAllowed */;
|
|
3713
|
+
}
|
|
3714
|
+
} else if (type === 32 || type === 33 || type === 34 || type === 39 || type >= 41 && type <= 44 || type >= 48 && type <= 55) {
|
|
3715
|
+
if (orderState > 1 /* beforeFirstVcl */) {
|
|
3716
|
+
remove = true;
|
|
3717
|
+
} else {
|
|
3718
|
+
orderState = 1 /* beforeFirstVcl */;
|
|
3719
|
+
}
|
|
3720
|
+
} else if (type === 38 || type === 40 || type >= 45 && type <= 47 || type >= 56 && type <= 63) {
|
|
3721
|
+
if (orderState < 2 /* afterFirstVcl */) {
|
|
3722
|
+
remove = true;
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
if (remove) {
|
|
3726
|
+
removedNalUnits.add(loc.offset);
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
if (removedNalUnits.size === 0) {
|
|
3730
|
+
return null;
|
|
3731
|
+
}
|
|
3732
|
+
const filteredNalUnits = [];
|
|
3733
|
+
for (const loc of iterateHevcNalUnits(packetData, decoderConfig)) {
|
|
3734
|
+
if (!removedNalUnits.has(loc.offset)) {
|
|
3735
|
+
filteredNalUnits.push(packetData.subarray(loc.offset, loc.offset + loc.length));
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
return concatHevcNalUnits(filteredNalUnits, decoderConfig);
|
|
3739
|
+
};
|
|
3666
3740
|
var extractVp9CodecInfoFromPacket = (packet) => {
|
|
3667
3741
|
const bitstream = new Bitstream(packet);
|
|
3668
3742
|
const frameMarker = bitstream.readBits(2);
|
|
@@ -20021,6 +20095,20 @@ var Mediabunny = (() => {
|
|
|
20021
20095
|
var isAudioData = (x) => {
|
|
20022
20096
|
return typeof AudioData !== "undefined" && x instanceof AudioData;
|
|
20023
20097
|
};
|
|
20098
|
+
var toInterleavedAudioFormat = (format) => {
|
|
20099
|
+
switch (format) {
|
|
20100
|
+
case "u8-planar":
|
|
20101
|
+
return "u8";
|
|
20102
|
+
case "s16-planar":
|
|
20103
|
+
return "s16";
|
|
20104
|
+
case "s32-planar":
|
|
20105
|
+
return "s32";
|
|
20106
|
+
case "f32-planar":
|
|
20107
|
+
return "f32";
|
|
20108
|
+
default:
|
|
20109
|
+
return format;
|
|
20110
|
+
}
|
|
20111
|
+
};
|
|
20024
20112
|
var doAudioDataCopyToWebKitWorkaround = (audioData, destView, srcFormat, destFormat, numChannels, planeIndex, frameOffset, copyFrameCount) => {
|
|
20025
20113
|
const readFn = getReadFunction(srcFormat);
|
|
20026
20114
|
const writeFn = getWriteFunction(destFormat);
|
|
@@ -20100,6 +20188,19 @@ var Mediabunny = (() => {
|
|
|
20100
20188
|
}
|
|
20101
20189
|
}
|
|
20102
20190
|
};
|
|
20191
|
+
var audioSampleToInterleavedFormat = (sample, format) => {
|
|
20192
|
+
const size = sample.allocationSize({ format, planeIndex: 0 });
|
|
20193
|
+
const buffer = new ArrayBuffer(size);
|
|
20194
|
+
sample.copyTo(buffer, { format, planeIndex: 0 });
|
|
20195
|
+
return new AudioSample({
|
|
20196
|
+
data: buffer,
|
|
20197
|
+
format,
|
|
20198
|
+
numberOfChannels: sample.numberOfChannels,
|
|
20199
|
+
sampleRate: sample.sampleRate,
|
|
20200
|
+
timestamp: sample.timestamp,
|
|
20201
|
+
duration: sample.duration
|
|
20202
|
+
});
|
|
20203
|
+
};
|
|
20103
20204
|
|
|
20104
20205
|
// src/encode.ts
|
|
20105
20206
|
var canEncodeVideoMemo = /* @__PURE__ */ new Map();
|
|
@@ -20233,7 +20334,7 @@ var Mediabunny = (() => {
|
|
|
20233
20334
|
if (!AUDIO_CODECS.includes(config.codec)) {
|
|
20234
20335
|
throw new TypeError(`Invalid audio codec '${config.codec}'. Must be one of: ${AUDIO_CODECS.join(", ")}.`);
|
|
20235
20336
|
}
|
|
20236
|
-
if (config.bitrate === void 0 && (
|
|
20337
|
+
if (config.bitrate === void 0 && !(PCM_AUDIO_CODECS.includes(config.codec) || config.codec === "flac")) {
|
|
20237
20338
|
throw new TypeError("config.bitrate must be provided for compressed audio codecs.");
|
|
20238
20339
|
}
|
|
20239
20340
|
if (config.bitrate !== void 0 && !(config.bitrate instanceof Quality) && (!Number.isInteger(config.bitrate) || config.bitrate <= 0)) {
|
|
@@ -20249,6 +20350,9 @@ var Mediabunny = (() => {
|
|
|
20249
20350
|
if (config.transform.sampleRate !== void 0 && (!Number.isInteger(config.transform.sampleRate) || config.transform.sampleRate <= 0)) {
|
|
20250
20351
|
throw new TypeError("config.transform.sampleRate, when provided, must be a positive integer.");
|
|
20251
20352
|
}
|
|
20353
|
+
if (config.transform.sampleFormat !== void 0 && !["u8", "s16", "s32", "f32"].includes(config.transform.sampleFormat)) {
|
|
20354
|
+
throw new TypeError("config.transform.sampleFormat, when provided, must be one of: u8, s16, s32, f32.");
|
|
20355
|
+
}
|
|
20252
20356
|
if (config.transform.process !== void 0 && typeof config.transform.process !== "function") {
|
|
20253
20357
|
throw new TypeError("config.transform.process, when provided, must be a function.");
|
|
20254
20358
|
}
|
|
@@ -21389,16 +21493,23 @@ var Mediabunny = (() => {
|
|
|
21389
21493
|
if (!isWebKit()) {
|
|
21390
21494
|
insertSorted(this.inputTimestamps, packet.timestamp, (x) => x);
|
|
21391
21495
|
}
|
|
21392
|
-
if (isChromium() && this.currentPacketIndex === 0
|
|
21393
|
-
|
|
21394
|
-
|
|
21395
|
-
const
|
|
21396
|
-
|
|
21397
|
-
|
|
21496
|
+
if (isChromium() && this.currentPacketIndex === 0) {
|
|
21497
|
+
if (this.codec === "avc") {
|
|
21498
|
+
const filteredNalUnits = [];
|
|
21499
|
+
for (const loc of iterateAvcNalUnits(packet.data, this.decoderConfig)) {
|
|
21500
|
+
const type = extractNalUnitTypeForAvc(packet.data[loc.offset]);
|
|
21501
|
+
if (!(type >= 20 && type <= 31)) {
|
|
21502
|
+
filteredNalUnits.push(packet.data.subarray(loc.offset, loc.offset + loc.length));
|
|
21503
|
+
}
|
|
21504
|
+
}
|
|
21505
|
+
const newData = concatAvcNalUnits(filteredNalUnits, this.decoderConfig);
|
|
21506
|
+
packet = new EncodedPacket(newData, packet.type, packet.timestamp, packet.duration);
|
|
21507
|
+
} else if (this.codec === "hevc") {
|
|
21508
|
+
const sanitizedData = sanitizeHevcPacketForChromium(packet.data, this.decoderConfig);
|
|
21509
|
+
if (sanitizedData) {
|
|
21510
|
+
packet = new EncodedPacket(sanitizedData, packet.type, packet.timestamp, packet.duration);
|
|
21398
21511
|
}
|
|
21399
21512
|
}
|
|
21400
|
-
const newData = concatAvcNalUnits(filteredNalUnits, this.decoderConfig);
|
|
21401
|
-
packet = new EncodedPacket(newData, packet.type, packet.timestamp, packet.duration);
|
|
21402
21513
|
}
|
|
21403
21514
|
this.decoder.decode(packet.toEncodedVideoChunk());
|
|
21404
21515
|
this.decodeAlphaData(packet);
|
|
@@ -25266,6 +25377,11 @@ var Mediabunny = (() => {
|
|
|
25266
25377
|
view.setUint32(4, value, false);
|
|
25267
25378
|
return [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]];
|
|
25268
25379
|
};
|
|
25380
|
+
var i64 = (value) => {
|
|
25381
|
+
view.setInt32(0, Math.floor(value / 2 ** 32), false);
|
|
25382
|
+
view.setUint32(4, value, false);
|
|
25383
|
+
return [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]];
|
|
25384
|
+
};
|
|
25269
25385
|
var fixed_8_8 = (value) => {
|
|
25270
25386
|
view.setInt16(0, 2 ** 8 * value, false);
|
|
25271
25387
|
return [bytes[0], bytes[1]];
|
|
@@ -25436,10 +25552,10 @@ var Mediabunny = (() => {
|
|
|
25436
25552
|
udta(muxer)
|
|
25437
25553
|
]);
|
|
25438
25554
|
var mvhd = (creationTime, trackDatas) => {
|
|
25439
|
-
const duration =
|
|
25555
|
+
const duration = Math.max(
|
|
25440
25556
|
0,
|
|
25441
|
-
...trackDatas.map((
|
|
25442
|
-
)
|
|
25557
|
+
...trackDatas.map((trackData) => intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(trackData.startTimestampOffset ?? 0, GLOBAL_TIMESCALE))
|
|
25558
|
+
);
|
|
25443
25559
|
const nextTrackId = Math.max(0, ...trackDatas.map((x) => x.track.id)) + 1;
|
|
25444
25560
|
const needsU64 = !isU32(creationTime) || !isU32(duration);
|
|
25445
25561
|
const u32OrU64 = needsU64 ? u64 : u32;
|
|
@@ -25472,7 +25588,8 @@ var Mediabunny = (() => {
|
|
|
25472
25588
|
}
|
|
25473
25589
|
let minTimestamp = Infinity;
|
|
25474
25590
|
let maxEndTimestamp = -Infinity;
|
|
25475
|
-
for (
|
|
25591
|
+
for (let i = 0; i < trackData.samples.length; i++) {
|
|
25592
|
+
const sample = trackData.samples[i];
|
|
25476
25593
|
if (sample.timestamp < minTimestamp) {
|
|
25477
25594
|
minTimestamp = sample.timestamp;
|
|
25478
25595
|
}
|
|
@@ -25487,8 +25604,10 @@ var Mediabunny = (() => {
|
|
|
25487
25604
|
};
|
|
25488
25605
|
var trak = (trackData, creationTime) => {
|
|
25489
25606
|
const trackMetadata = getTrackMetadata(trackData);
|
|
25607
|
+
const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset > 0;
|
|
25490
25608
|
return box("trak", void 0, [
|
|
25491
25609
|
tkhd(trackData, creationTime),
|
|
25610
|
+
needsEditList ? edts(trackData, trackData.startTimestampOffset) : null,
|
|
25492
25611
|
mdia(trackData, creationTime),
|
|
25493
25612
|
trackMetadata.name !== void 0 ? box("udta", void 0, [
|
|
25494
25613
|
box("name", [
|
|
@@ -25499,10 +25618,7 @@ var Mediabunny = (() => {
|
|
|
25499
25618
|
]);
|
|
25500
25619
|
};
|
|
25501
25620
|
var tkhd = (trackData, creationTime) => {
|
|
25502
|
-
const durationInGlobalTimescale = intoTimescale(
|
|
25503
|
-
presentationSpan(trackData),
|
|
25504
|
-
GLOBAL_TIMESCALE
|
|
25505
|
-
);
|
|
25621
|
+
const durationInGlobalTimescale = intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(trackData.startTimestampOffset ?? 0, GLOBAL_TIMESCALE);
|
|
25506
25622
|
const needsU64 = !isU32(creationTime) || !isU32(durationInGlobalTimescale);
|
|
25507
25623
|
const u32OrU64 = needsU64 ? u64 : u32;
|
|
25508
25624
|
let matrix;
|
|
@@ -25545,6 +25661,33 @@ var Mediabunny = (() => {
|
|
|
25545
25661
|
// Track height
|
|
25546
25662
|
]);
|
|
25547
25663
|
};
|
|
25664
|
+
var edts = (trackData, offset) => {
|
|
25665
|
+
const startOffset = intoTimescale(offset, GLOBAL_TIMESCALE);
|
|
25666
|
+
const mediaDuration = intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE);
|
|
25667
|
+
const needs64Bits = !isU32(startOffset) || !isU32(mediaDuration);
|
|
25668
|
+
const u32OrU64 = needs64Bits ? u64 : u32;
|
|
25669
|
+
const i32OrI64 = needs64Bits ? i64 : i32;
|
|
25670
|
+
return box("edts", void 0, [
|
|
25671
|
+
fullBox("elst", needs64Bits ? 1 : 0, 0, [
|
|
25672
|
+
u32(2),
|
|
25673
|
+
// Entry count
|
|
25674
|
+
// #1
|
|
25675
|
+
u32OrU64(startOffset),
|
|
25676
|
+
// Segment duration
|
|
25677
|
+
i32OrI64(-1),
|
|
25678
|
+
// Media time
|
|
25679
|
+
fixed_16_16(1),
|
|
25680
|
+
// Media rate
|
|
25681
|
+
// #2
|
|
25682
|
+
u32OrU64(mediaDuration),
|
|
25683
|
+
// Segment duration
|
|
25684
|
+
i32OrI64(0),
|
|
25685
|
+
// Media time
|
|
25686
|
+
fixed_16_16(1)
|
|
25687
|
+
// Media rate
|
|
25688
|
+
])
|
|
25689
|
+
]);
|
|
25690
|
+
};
|
|
25548
25691
|
var mdia = (trackData, creationTime) => box("mdia", void 0, [
|
|
25549
25692
|
mdhd(trackData, creationTime),
|
|
25550
25693
|
hdlr(true, TRACK_TYPE_TO_COMPONENT_SUBTYPE[trackData.type], TRACK_TYPE_TO_HANDLER_NAME[trackData.type]),
|
|
@@ -27473,7 +27616,7 @@ var Mediabunny = (() => {
|
|
|
27473
27616
|
};
|
|
27474
27617
|
|
|
27475
27618
|
// src/isobmff/isobmff-muxer.ts
|
|
27476
|
-
var GLOBAL_TIMESCALE =
|
|
27619
|
+
var GLOBAL_TIMESCALE = 57600;
|
|
27477
27620
|
var TIMESTAMP_OFFSET = 2082844800;
|
|
27478
27621
|
var getTrackMetadata = (trackData) => {
|
|
27479
27622
|
const metadata = {};
|
|
@@ -27641,7 +27784,10 @@ var Mediabunny = (() => {
|
|
|
27641
27784
|
decoderConfig.description = serializeHevcDecoderConfigurationRecord(decoderConfigurationRecord);
|
|
27642
27785
|
requiresAnnexBTransformation = true;
|
|
27643
27786
|
}
|
|
27644
|
-
const timescale = computeRationalApproximation(
|
|
27787
|
+
const timescale = computeRationalApproximation(
|
|
27788
|
+
1 / (track.metadata.frameRate ?? GLOBAL_TIMESCALE),
|
|
27789
|
+
1e6
|
|
27790
|
+
).denominator;
|
|
27645
27791
|
const displayAspectWidth = decoderConfig.displayAspectWidth;
|
|
27646
27792
|
const displayAspectHeight = decoderConfig.displayAspectHeight;
|
|
27647
27793
|
const pixelAspectRatio = displayAspectWidth === void 0 || displayAspectHeight === void 0 ? { num: 1, den: 1 } : simplifyRational({
|
|
@@ -27667,6 +27813,7 @@ var Mediabunny = (() => {
|
|
|
27667
27813
|
compositionTimeOffsetTable: [],
|
|
27668
27814
|
lastTimescaleUnits: null,
|
|
27669
27815
|
lastSample: null,
|
|
27816
|
+
startTimestampOffset: null,
|
|
27670
27817
|
finalizedChunks: [],
|
|
27671
27818
|
currentChunk: null,
|
|
27672
27819
|
compactlyCodedChunkTable: [],
|
|
@@ -27717,6 +27864,7 @@ var Mediabunny = (() => {
|
|
|
27717
27864
|
sampleRate: meta.decoderConfig.sampleRate,
|
|
27718
27865
|
decoderConfig,
|
|
27719
27866
|
requiresPcmTransformation: !this.isFragmented && PCM_AUDIO_CODECS.includes(track.source._codec),
|
|
27867
|
+
expectedNextPcmPacketTimestamp: null,
|
|
27720
27868
|
requiresAdtsStripping,
|
|
27721
27869
|
firstPacket: packet
|
|
27722
27870
|
},
|
|
@@ -27728,6 +27876,7 @@ var Mediabunny = (() => {
|
|
|
27728
27876
|
compositionTimeOffsetTable: [],
|
|
27729
27877
|
lastTimescaleUnits: null,
|
|
27730
27878
|
lastSample: null,
|
|
27879
|
+
startTimestampOffset: null,
|
|
27731
27880
|
finalizedChunks: [],
|
|
27732
27881
|
currentChunk: null,
|
|
27733
27882
|
compactlyCodedChunkTable: [],
|
|
@@ -27764,6 +27913,7 @@ var Mediabunny = (() => {
|
|
|
27764
27913
|
compositionTimeOffsetTable: [],
|
|
27765
27914
|
lastTimescaleUnits: null,
|
|
27766
27915
|
lastSample: null,
|
|
27916
|
+
startTimestampOffset: null,
|
|
27767
27917
|
finalizedChunks: [],
|
|
27768
27918
|
currentChunk: null,
|
|
27769
27919
|
compactlyCodedChunkTable: [],
|
|
@@ -27824,31 +27974,48 @@ var Mediabunny = (() => {
|
|
|
27824
27974
|
const headerLength = adtsFrame.crcCheck === null ? MIN_ADTS_FRAME_HEADER_SIZE : MAX_ADTS_FRAME_HEADER_SIZE;
|
|
27825
27975
|
packetData = packetData.subarray(headerLength);
|
|
27826
27976
|
}
|
|
27827
|
-
|
|
27977
|
+
let timestamp = this.validateAndNormalizeTimestamp(
|
|
27828
27978
|
trackData.track,
|
|
27829
27979
|
packet.timestamp,
|
|
27830
27980
|
packet.type === "key"
|
|
27831
27981
|
);
|
|
27982
|
+
let duration = packet.duration;
|
|
27983
|
+
if (trackData.info.requiresPcmTransformation) {
|
|
27984
|
+
const pcmInfo = parsePcmCodec(
|
|
27985
|
+
trackData.info.decoderConfig.codec
|
|
27986
|
+
);
|
|
27987
|
+
const frameSize = pcmInfo.sampleSize * trackData.info.numberOfChannels;
|
|
27988
|
+
duration = packetData.byteLength / frameSize / trackData.info.sampleRate;
|
|
27989
|
+
if (trackData.info.expectedNextPcmPacketTimestamp !== null) {
|
|
27990
|
+
const diff = timestamp - trackData.info.expectedNextPcmPacketTimestamp;
|
|
27991
|
+
if (diff < 0.01) {
|
|
27992
|
+
timestamp = trackData.info.expectedNextPcmPacketTimestamp;
|
|
27993
|
+
} else {
|
|
27994
|
+
const paddedDuration = await this.padWithSilence(
|
|
27995
|
+
trackData,
|
|
27996
|
+
trackData.info.expectedNextPcmPacketTimestamp,
|
|
27997
|
+
diff
|
|
27998
|
+
);
|
|
27999
|
+
timestamp = trackData.info.expectedNextPcmPacketTimestamp + paddedDuration;
|
|
28000
|
+
}
|
|
28001
|
+
}
|
|
28002
|
+
trackData.info.expectedNextPcmPacketTimestamp = timestamp + duration;
|
|
28003
|
+
}
|
|
27832
28004
|
const internalSample = this.createSampleForTrack(
|
|
27833
28005
|
trackData,
|
|
27834
28006
|
packetData,
|
|
27835
28007
|
timestamp,
|
|
27836
|
-
|
|
28008
|
+
duration,
|
|
27837
28009
|
packet.type
|
|
27838
28010
|
);
|
|
27839
|
-
if (trackData.info.requiresPcmTransformation) {
|
|
27840
|
-
await this.maybePadWithSilence(trackData, timestamp);
|
|
27841
|
-
}
|
|
27842
28011
|
await this.registerSample(trackData, internalSample);
|
|
27843
28012
|
} finally {
|
|
27844
28013
|
release();
|
|
27845
28014
|
}
|
|
27846
28015
|
}
|
|
27847
|
-
async
|
|
27848
|
-
const
|
|
27849
|
-
|
|
27850
|
-
const delta = untilTimestamp - lastEndTimestamp;
|
|
27851
|
-
const deltaInTimescale = intoTimescale(delta, trackData.timescale);
|
|
28016
|
+
async padWithSilence(trackData, timestamp, duration) {
|
|
28017
|
+
const deltaInTimescale = intoTimescale(duration, trackData.timescale);
|
|
28018
|
+
duration = deltaInTimescale / trackData.timescale;
|
|
27852
28019
|
if (deltaInTimescale > 0) {
|
|
27853
28020
|
const { sampleSize, silentValue } = parsePcmCodec(
|
|
27854
28021
|
trackData.info.decoderConfig.codec
|
|
@@ -27858,12 +28025,13 @@ var Mediabunny = (() => {
|
|
|
27858
28025
|
const paddingSample = this.createSampleForTrack(
|
|
27859
28026
|
trackData,
|
|
27860
28027
|
new Uint8Array(data.buffer),
|
|
27861
|
-
|
|
27862
|
-
|
|
28028
|
+
timestamp,
|
|
28029
|
+
duration,
|
|
27863
28030
|
"key"
|
|
27864
28031
|
);
|
|
27865
28032
|
await this.registerSample(trackData, paddingSample);
|
|
27866
28033
|
}
|
|
28034
|
+
return duration;
|
|
27867
28035
|
}
|
|
27868
28036
|
async addSubtitleCue(track, cue, meta) {
|
|
27869
28037
|
const release = await this.mutex.acquire();
|
|
@@ -27964,6 +28132,9 @@ var Mediabunny = (() => {
|
|
|
27964
28132
|
return;
|
|
27965
28133
|
}
|
|
27966
28134
|
if (trackData.type === "audio" && trackData.info.requiresPcmTransformation) {
|
|
28135
|
+
if (!this.isFragmented) {
|
|
28136
|
+
trackData.startTimestampOffset ??= trackData.timestampProcessingQueue[0].timestamp;
|
|
28137
|
+
}
|
|
27967
28138
|
let totalDuration = 0;
|
|
27968
28139
|
for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {
|
|
27969
28140
|
const sample = trackData.timestampProcessingQueue[i];
|
|
@@ -27983,12 +28154,12 @@ var Mediabunny = (() => {
|
|
|
27983
28154
|
return;
|
|
27984
28155
|
}
|
|
27985
28156
|
const sortedTimestamps = trackData.timestampProcessingQueue.map((x) => x.timestamp).sort((a, b) => a - b);
|
|
28157
|
+
if (!this.isFragmented) {
|
|
28158
|
+
trackData.startTimestampOffset ??= sortedTimestamps[0];
|
|
28159
|
+
}
|
|
27986
28160
|
for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {
|
|
27987
28161
|
const sample = trackData.timestampProcessingQueue[i];
|
|
27988
28162
|
sample.decodeTimestamp = sortedTimestamps[i];
|
|
27989
|
-
if (!this.isFragmented && trackData.lastTimescaleUnits === null) {
|
|
27990
|
-
sample.decodeTimestamp = 0;
|
|
27991
|
-
}
|
|
27992
28163
|
const sampleCompositionTimeOffset = intoTimescale(sample.timestamp - sample.decodeTimestamp, trackData.timescale);
|
|
27993
28164
|
const durationInTimescale = intoTimescale(sample.duration, trackData.timescale);
|
|
27994
28165
|
if (trackData.lastTimescaleUnits !== null) {
|
|
@@ -28352,6 +28523,12 @@ var Mediabunny = (() => {
|
|
|
28352
28523
|
} else {
|
|
28353
28524
|
for (const trackData of this.trackDatas) {
|
|
28354
28525
|
await this.finalizeCurrentChunk(trackData);
|
|
28526
|
+
assert(trackData.startTimestampOffset !== null);
|
|
28527
|
+
for (let i = 0; i < trackData.samples.length; i++) {
|
|
28528
|
+
const sample = trackData.samples[i];
|
|
28529
|
+
sample.timestamp -= trackData.startTimestampOffset;
|
|
28530
|
+
sample.decodeTimestamp -= trackData.startTimestampOffset;
|
|
28531
|
+
}
|
|
28355
28532
|
}
|
|
28356
28533
|
}
|
|
28357
28534
|
assert(this.writer);
|
|
@@ -32320,6 +32497,14 @@ ${cue.notes ?? ""}`;
|
|
|
32320
32497
|
*/
|
|
32321
32498
|
async processAndEncode(audioSample, shouldClose) {
|
|
32322
32499
|
const config = this.encodingConfig;
|
|
32500
|
+
if (config.transform?.sampleFormat !== void 0 && toInterleavedAudioFormat(audioSample.format) !== config.transform.sampleFormat) {
|
|
32501
|
+
const newSample = audioSampleToInterleavedFormat(audioSample, config.transform.sampleFormat);
|
|
32502
|
+
if (shouldClose) {
|
|
32503
|
+
audioSample.close();
|
|
32504
|
+
}
|
|
32505
|
+
audioSample = newSample;
|
|
32506
|
+
shouldClose = true;
|
|
32507
|
+
}
|
|
32323
32508
|
if (config.transform?.process) {
|
|
32324
32509
|
let processed = config.transform.process(audioSample);
|
|
32325
32510
|
if (processed instanceof Promise) {
|
|
@@ -32339,6 +32524,9 @@ ${cue.notes ?? ""}`;
|
|
|
32339
32524
|
}
|
|
32340
32525
|
await this.encodeSample(sample, true);
|
|
32341
32526
|
}
|
|
32527
|
+
if (shouldClose) {
|
|
32528
|
+
audioSample.close();
|
|
32529
|
+
}
|
|
32342
32530
|
} else {
|
|
32343
32531
|
await this.encodeSample(audioSample, shouldClose);
|
|
32344
32532
|
}
|
|
@@ -35418,6 +35606,9 @@ ${cue.notes ?? ""}`;
|
|
|
35418
35606
|
if (audioOptions?.sampleRate !== void 0 && (!Number.isInteger(audioOptions.sampleRate) || audioOptions.sampleRate <= 0)) {
|
|
35419
35607
|
throw new TypeError("options.audio.sampleRate, when provided, must be a positive integer.");
|
|
35420
35608
|
}
|
|
35609
|
+
if (audioOptions?.sampleFormat !== void 0 && !["u8", "s16", "s32", "f32"].includes(audioOptions.sampleFormat)) {
|
|
35610
|
+
throw new TypeError("options.audio.sampleFormat, when provided, must be one of: u8, s16, s32, f32.");
|
|
35611
|
+
}
|
|
35421
35612
|
if (audioOptions?.process !== void 0 && typeof audioOptions.process !== "function") {
|
|
35422
35613
|
throw new TypeError("options.audio.process, when provided, must be a function.");
|
|
35423
35614
|
}
|
|
@@ -36036,7 +36227,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36036
36227
|
timestamp: lastCanvasTimestamp + i / frameRate,
|
|
36037
36228
|
duration: 1 / frameRate
|
|
36038
36229
|
});
|
|
36039
|
-
await this._registerVideoSample(
|
|
36230
|
+
await this._registerVideoSample(trackOptions, outputTrackId, source, sample);
|
|
36040
36231
|
sample.close();
|
|
36041
36232
|
}
|
|
36042
36233
|
};
|
|
@@ -36063,7 +36254,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36063
36254
|
timestamp: adjustedSampleTimestamp,
|
|
36064
36255
|
duration: frameRate !== void 0 ? 1 / frameRate : duration
|
|
36065
36256
|
});
|
|
36066
|
-
await this._registerVideoSample(
|
|
36257
|
+
await this._registerVideoSample(trackOptions, outputTrackId, source, sample);
|
|
36067
36258
|
sample.close();
|
|
36068
36259
|
if (frameRate !== void 0) {
|
|
36069
36260
|
lastCanvas = canvas;
|
|
@@ -36093,7 +36284,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36093
36284
|
for (let i = 1; i < frameDifference; i++) {
|
|
36094
36285
|
lastSample.setTimestamp(lastSampleTimestamp + i / frameRate);
|
|
36095
36286
|
lastSample.setDuration(1 / frameRate);
|
|
36096
|
-
await this._registerVideoSample(
|
|
36287
|
+
await this._registerVideoSample(trackOptions, outputTrackId, source, lastSample);
|
|
36097
36288
|
}
|
|
36098
36289
|
lastSample.close();
|
|
36099
36290
|
};
|
|
@@ -36121,7 +36312,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36121
36312
|
sample.setDuration(1 / frameRate);
|
|
36122
36313
|
}
|
|
36123
36314
|
sample.setTimestamp(adjustedSampleTimestamp);
|
|
36124
|
-
await this._registerVideoSample(
|
|
36315
|
+
await this._registerVideoSample(trackOptions, outputTrackId, source, sample);
|
|
36125
36316
|
if (frameRate !== void 0) {
|
|
36126
36317
|
lastSample = sample;
|
|
36127
36318
|
lastSampleTimestamp = adjustedSampleTimestamp;
|
|
@@ -36160,7 +36351,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36160
36351
|
this._outputOwnTrackGroups.push(ownGroup);
|
|
36161
36352
|
}
|
|
36162
36353
|
/** @internal */
|
|
36163
|
-
async _registerVideoSample(
|
|
36354
|
+
async _registerVideoSample(trackOptions, outputTrackId, source, sample) {
|
|
36164
36355
|
if (this._canceled) {
|
|
36165
36356
|
return;
|
|
36166
36357
|
}
|
|
@@ -36224,7 +36415,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36224
36415
|
let sampleRate = trackOptions.sampleRate ?? originalSampleRate;
|
|
36225
36416
|
let needsResample = numberOfChannels !== originalNumberOfChannels || sampleRate !== originalSampleRate || firstTimestamp < this._startTimestamp || firstTimestamp > this._startTimestamp && !this.output.format.supportsTimestampedMediaData;
|
|
36226
36417
|
let audioCodecs = this.output.format.getSupportedAudioCodecs();
|
|
36227
|
-
if (!trackOptions.forceTranscode && !trackOptions.bitrate && !needsResample && audioCodecs.includes(sourceCodec) && (!trackOptions.codec || trackOptions.codec === sourceCodec) && !trackOptions.process) {
|
|
36418
|
+
if (!trackOptions.forceTranscode && !trackOptions.bitrate && !needsResample && audioCodecs.includes(sourceCodec) && (!trackOptions.codec || trackOptions.codec === sourceCodec) && !trackOptions.process && trackOptions.sampleFormat === void 0) {
|
|
36228
36419
|
const source = new EncodedAudioPacketSource(sourceCodec);
|
|
36229
36420
|
audioSource = source;
|
|
36230
36421
|
this._trackPromises.push((async () => {
|
|
@@ -36321,7 +36512,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36321
36512
|
return;
|
|
36322
36513
|
}
|
|
36323
36514
|
sample.setTimestamp(sample.timestamp - this._startTimestamp);
|
|
36324
|
-
await this._registerAudioSample(
|
|
36515
|
+
await this._registerAudioSample(trackOptions, outputTrackId, source, sample);
|
|
36325
36516
|
sample.close();
|
|
36326
36517
|
}
|
|
36327
36518
|
source.close();
|
|
@@ -36348,10 +36539,14 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36348
36539
|
this._outputOwnTrackGroups.push(ownGroup);
|
|
36349
36540
|
}
|
|
36350
36541
|
/** @internal */
|
|
36351
|
-
async _registerAudioSample(
|
|
36542
|
+
async _registerAudioSample(trackOptions, outputTrackId, source, inputSample) {
|
|
36352
36543
|
if (this._canceled) {
|
|
36353
36544
|
return;
|
|
36354
36545
|
}
|
|
36546
|
+
let sample = inputSample;
|
|
36547
|
+
if (trackOptions.sampleFormat !== void 0 && toInterleavedAudioFormat(sample.format) !== trackOptions.sampleFormat) {
|
|
36548
|
+
sample = audioSampleToInterleavedFormat(sample, trackOptions.sampleFormat);
|
|
36549
|
+
}
|
|
36355
36550
|
this._reportProgress(outputTrackId, sample.timestamp + sample.duration);
|
|
36356
36551
|
let finalSamples;
|
|
36357
36552
|
if (!trackOptions.process) {
|
|
@@ -36380,8 +36575,11 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36380
36575
|
}
|
|
36381
36576
|
}
|
|
36382
36577
|
} finally {
|
|
36578
|
+
if (sample !== inputSample) {
|
|
36579
|
+
sample.close();
|
|
36580
|
+
}
|
|
36383
36581
|
for (const finalSample of finalSamples) {
|
|
36384
|
-
if (finalSample !==
|
|
36582
|
+
if (finalSample !== inputSample) {
|
|
36385
36583
|
finalSample.close();
|
|
36386
36584
|
}
|
|
36387
36585
|
}
|
|
@@ -36402,7 +36600,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
36402
36600
|
endTime: this._endTimestamp,
|
|
36403
36601
|
onSample: async (sample) => {
|
|
36404
36602
|
sample.setTimestamp(sample.timestamp - this._startTimestamp);
|
|
36405
|
-
await this._registerAudioSample(
|
|
36603
|
+
await this._registerAudioSample(trackOptions, outputTrackId, source, sample);
|
|
36406
36604
|
sample.close();
|
|
36407
36605
|
}
|
|
36408
36606
|
});
|