mediabunny 1.55.7 → 1.56.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 +529 -180
- package/dist/bundles/mediabunny.min.cjs +12 -12
- package/dist/bundles/mediabunny.min.mjs +12 -12
- package/dist/bundles/mediabunny.mjs +529 -180
- package/dist/bundles/mediabunny.node.cjs +529 -180
- package/dist/mediabunny.d.ts +106 -19
- package/dist/modules/src/conversion.d.ts +57 -12
- package/dist/modules/src/conversion.d.ts.map +1 -1
- package/dist/modules/src/conversion.js +353 -119
- package/dist/modules/src/index.d.ts +2 -2
- package/dist/modules/src/index.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.js +59 -29
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-demuxer.js +0 -4
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.js +14 -6
- package/dist/modules/src/matroska/matroska-demuxer.d.ts +1 -0
- package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-demuxer.js +20 -8
- package/dist/modules/src/matroska/matroska-muxer.d.ts +1 -0
- package/dist/modules/src/matroska/matroska-muxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-muxer.js +10 -1
- package/dist/modules/src/media-source.d.ts +17 -5
- package/dist/modules/src/media-source.d.ts.map +1 -1
- package/dist/modules/src/media-source.js +14 -9
- package/dist/modules/src/misc.d.ts +2 -0
- package/dist/modules/src/misc.d.ts.map +1 -1
- package/dist/modules/src/misc.js +6 -0
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.d.ts +5 -0
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.d.ts.map +1 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.js +37 -16
- package/dist/modules/src/mpeg-ts/mpeg-ts-misc.d.ts +1 -0
- package/dist/modules/src/mpeg-ts/mpeg-ts-misc.d.ts.map +1 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-misc.js +1 -0
- package/dist/modules/src/mpeg-ts/mpeg-ts-muxer.d.ts.map +1 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-muxer.js +14 -10
- package/dist/modules/src/muxer.d.ts.map +1 -1
- package/dist/modules/src/muxer.js +0 -3
- package/dist/modules/src/output-format.d.ts +17 -0
- package/dist/modules/src/output-format.d.ts.map +1 -1
- package/dist/modules/src/output-format.js +39 -1
- package/dist/modules/src/sample.d.ts +2 -2
- package/dist/modules/src/sample.d.ts.map +1 -1
- package/dist/modules/src/sample.js +16 -16
- package/dist/modules/src/source.d.ts +10 -0
- package/dist/modules/src/source.d.ts.map +1 -1
- package/dist/modules/src/source.js +38 -3
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/conversion.ts +460 -99
- package/src/index.ts +2 -0
- package/src/isobmff/isobmff-boxes.ts +76 -32
- package/src/isobmff/isobmff-demuxer.ts +0 -5
- package/src/isobmff/isobmff-muxer.ts +22 -12
- package/src/matroska/matroska-demuxer.ts +24 -11
- package/src/matroska/matroska-muxer.ts +14 -1
- package/src/media-source.ts +28 -8
- package/src/misc.ts +8 -0
- package/src/mpeg-ts/mpeg-ts-demuxer.ts +52 -14
- package/src/mpeg-ts/mpeg-ts-misc.ts +1 -0
- package/src/mpeg-ts/mpeg-ts-muxer.ts +20 -10
- package/src/muxer.ts +0 -4
- package/src/output-format.ts +58 -1
- package/src/sample.ts +16 -16
- package/src/source.ts +55 -3
|
@@ -259,6 +259,9 @@ var Mediabunny = (() => {
|
|
|
259
259
|
var isU32 = (value) => {
|
|
260
260
|
return value >= 0 && value < 2 ** 32;
|
|
261
261
|
};
|
|
262
|
+
var isI32 = (value) => {
|
|
263
|
+
return value >= -(2 ** 31) && value < 2 ** 31;
|
|
264
|
+
};
|
|
262
265
|
var readExpGolomb = (bitstream) => {
|
|
263
266
|
let leadingZeroBits = 0;
|
|
264
267
|
while (bitstream.readBits(1) === 0 && leadingZeroBits < 32) {
|
|
@@ -570,6 +573,9 @@ var Mediabunny = (() => {
|
|
|
570
573
|
var lerp = (from, to, t) => {
|
|
571
574
|
return from + (to - from) * t;
|
|
572
575
|
};
|
|
576
|
+
var modEuclid = (value, modulus) => {
|
|
577
|
+
return value - Math.floor(value / modulus) * modulus;
|
|
578
|
+
};
|
|
573
579
|
var UNDETERMINED_LANGUAGE = "und";
|
|
574
580
|
var roundIfAlmostInteger = (value) => {
|
|
575
581
|
const rounded = Math.round(value);
|
|
@@ -6657,9 +6663,6 @@ var Mediabunny = (() => {
|
|
|
6657
6663
|
const segmentDuration = version === 1 ? readU64Be(slice) : readU32Be(slice);
|
|
6658
6664
|
const mediaTime = version === 1 ? readI64Be(slice) : readI32Be(slice);
|
|
6659
6665
|
const mediaRate = readFixed_16_16(slice);
|
|
6660
|
-
if (segmentDuration === 0) {
|
|
6661
|
-
continue;
|
|
6662
|
-
}
|
|
6663
6666
|
if (relevantEntryFound) {
|
|
6664
6667
|
Logging._warn(
|
|
6665
6668
|
"Unsupported edit list: multiple edits are not currently supported. Only using first edit."
|
|
@@ -11321,6 +11324,22 @@ var Mediabunny = (() => {
|
|
|
11321
11324
|
}
|
|
11322
11325
|
}
|
|
11323
11326
|
}
|
|
11327
|
+
async getDurationFromMetadata(segment) {
|
|
11328
|
+
if (segment.duration <= 0) {
|
|
11329
|
+
return null;
|
|
11330
|
+
}
|
|
11331
|
+
let minTimestamp = null;
|
|
11332
|
+
for (const track of segment.tracks) {
|
|
11333
|
+
assert(track.trackBacking);
|
|
11334
|
+
const firstPacket = await track.trackBacking.getFirstPacket({ metadataOnly: true });
|
|
11335
|
+
if (firstPacket) {
|
|
11336
|
+
minTimestamp = Math.min(minTimestamp ?? Infinity, firstPacket.timestamp);
|
|
11337
|
+
}
|
|
11338
|
+
}
|
|
11339
|
+
let endTimestamp = segment.duration / segment.timestampFactor;
|
|
11340
|
+
endTimestamp += minTimestamp ?? 0;
|
|
11341
|
+
return endTimestamp;
|
|
11342
|
+
}
|
|
11324
11343
|
};
|
|
11325
11344
|
var MatroskaTrackBacking = class {
|
|
11326
11345
|
constructor(internalTrack) {
|
|
@@ -11380,14 +11399,7 @@ var Mediabunny = (() => {
|
|
|
11380
11399
|
return null;
|
|
11381
11400
|
}
|
|
11382
11401
|
async getDurationFromMetadata() {
|
|
11383
|
-
|
|
11384
|
-
if (segment.duration <= 0) {
|
|
11385
|
-
return null;
|
|
11386
|
-
}
|
|
11387
|
-
let endTimestamp = segment.duration / segment.timestampFactor;
|
|
11388
|
-
const firstPacket = await this.getFirstPacket({ metadataOnly: true });
|
|
11389
|
-
endTimestamp += firstPacket?.timestamp ?? 0;
|
|
11390
|
-
return endTimestamp;
|
|
11402
|
+
return this.internalTrack.demuxer.getDurationFromMetadata(this.internalTrack.segment);
|
|
11391
11403
|
}
|
|
11392
11404
|
async getLiveRefreshInterval() {
|
|
11393
11405
|
return null;
|
|
@@ -14474,6 +14486,7 @@ var Mediabunny = (() => {
|
|
|
14474
14486
|
|
|
14475
14487
|
// src/mpeg-ts/mpeg-ts-misc.ts
|
|
14476
14488
|
var TIMESCALE = 9e4;
|
|
14489
|
+
var TIMESTAMP_MODULUS = 2 ** 33;
|
|
14477
14490
|
var TS_PACKET_SIZE = 188;
|
|
14478
14491
|
var buildMpegTsMimeType = (codecStrings) => {
|
|
14479
14492
|
let string = "video/MP2T";
|
|
@@ -14508,6 +14521,7 @@ var Mediabunny = (() => {
|
|
|
14508
14521
|
this.seekChunkSize = 5 * 1024 * 1024;
|
|
14509
14522
|
// 5 MiB, picked because most HLS segments are below this size
|
|
14510
14523
|
this.minReferencePointByteDistance = -1;
|
|
14524
|
+
this.timestampWrapInfo = null;
|
|
14511
14525
|
this.reader = input._reader;
|
|
14512
14526
|
}
|
|
14513
14527
|
async readMetadata() {
|
|
@@ -14765,7 +14779,7 @@ var Mediabunny = (() => {
|
|
|
14765
14779
|
const elementaryStream = this.elementaryStreams.find((x) => x.pid === section.pid);
|
|
14766
14780
|
outer:
|
|
14767
14781
|
if (elementaryStream && !elementaryStream.initialized) {
|
|
14768
|
-
const pesPacket = readPesPacket(section, true);
|
|
14782
|
+
const pesPacket = readPesPacket(this, section, true);
|
|
14769
14783
|
if (!pesPacket) {
|
|
14770
14784
|
throw new Error(
|
|
14771
14785
|
`Couldn't read first PES packet for Elementary Stream with PID ${elementaryStream.pid}`
|
|
@@ -15160,8 +15174,22 @@ var Mediabunny = (() => {
|
|
|
15160
15174
|
body: bytes2.subarray(4)
|
|
15161
15175
|
};
|
|
15162
15176
|
}
|
|
15177
|
+
normalizeTimestamp(timestamp) {
|
|
15178
|
+
if (!this.timestampWrapInfo) {
|
|
15179
|
+
const tolerance = 60 * TIMESCALE;
|
|
15180
|
+
this.timestampWrapInfo = {
|
|
15181
|
+
reference: timestamp - tolerance,
|
|
15182
|
+
offset: timestamp >= TIMESTAMP_MODULUS - tolerance ? -TIMESTAMP_MODULUS : TIMESTAMP_MODULUS
|
|
15183
|
+
};
|
|
15184
|
+
}
|
|
15185
|
+
const { reference, offset } = this.timestampWrapInfo;
|
|
15186
|
+
if (offset < 0 && timestamp >= reference || offset > 0 && timestamp < reference) {
|
|
15187
|
+
return timestamp + offset;
|
|
15188
|
+
}
|
|
15189
|
+
return timestamp;
|
|
15190
|
+
}
|
|
15163
15191
|
};
|
|
15164
|
-
var readPesPacketHeader = (section, expectPts) => {
|
|
15192
|
+
var readPesPacketHeader = (demuxer, section, expectPts) => {
|
|
15165
15193
|
if (section.payload.byteLength < 3) {
|
|
15166
15194
|
return null;
|
|
15167
15195
|
}
|
|
@@ -15187,6 +15215,7 @@ var Mediabunny = (() => {
|
|
|
15187
15215
|
pts += bitstream.readBits(15) * (1 << 15);
|
|
15188
15216
|
bitstream.skipBits(1);
|
|
15189
15217
|
pts += bitstream.readBits(15);
|
|
15218
|
+
pts = demuxer.normalizeTimestamp(pts);
|
|
15190
15219
|
} else {
|
|
15191
15220
|
if (expectPts) {
|
|
15192
15221
|
throw new Error(MISSING_PTS_ERROR_MESSAGE);
|
|
@@ -15199,9 +15228,9 @@ var Mediabunny = (() => {
|
|
|
15199
15228
|
randomAccessIndicator: section.randomAccessIndicator
|
|
15200
15229
|
};
|
|
15201
15230
|
};
|
|
15202
|
-
var readPesPacket = (section, expectPts) => {
|
|
15231
|
+
var readPesPacket = (demuxer, section, expectPts) => {
|
|
15203
15232
|
assert(section.endPos !== null);
|
|
15204
|
-
const header = readPesPacketHeader(section, expectPts);
|
|
15233
|
+
const header = readPesPacketHeader(demuxer, section, expectPts);
|
|
15205
15234
|
if (!header) {
|
|
15206
15235
|
return null;
|
|
15207
15236
|
}
|
|
@@ -15313,7 +15342,7 @@ var Mediabunny = (() => {
|
|
|
15313
15342
|
async getFirstPacket(options) {
|
|
15314
15343
|
const section = this.elementaryStream.firstSection;
|
|
15315
15344
|
assert(section);
|
|
15316
|
-
const pesPacket = readPesPacket(section, true);
|
|
15345
|
+
const pesPacket = readPesPacket(this.elementaryStream.demuxer, section, true);
|
|
15317
15346
|
assert(pesPacket);
|
|
15318
15347
|
const context = new PacketReadingContext(this.elementaryStream, pesPacket);
|
|
15319
15348
|
const buffer = new PacketBuffer(this, context);
|
|
@@ -15346,7 +15375,7 @@ var Mediabunny = (() => {
|
|
|
15346
15375
|
const demuxer = this.elementaryStream.demuxer;
|
|
15347
15376
|
const section = await demuxer.readSection(sectionStartPos, true);
|
|
15348
15377
|
assert(section);
|
|
15349
|
-
const pesPacket = readPesPacket(section, true);
|
|
15378
|
+
const pesPacket = readPesPacket(demuxer, section, true);
|
|
15350
15379
|
assert(pesPacket);
|
|
15351
15380
|
const context = new PacketReadingContext(this.elementaryStream, pesPacket);
|
|
15352
15381
|
buffer = new PacketBuffer(this, context);
|
|
@@ -15404,7 +15433,7 @@ var Mediabunny = (() => {
|
|
|
15404
15433
|
if (!section) {
|
|
15405
15434
|
return null;
|
|
15406
15435
|
}
|
|
15407
|
-
const pesPacketHeader = readPesPacketHeader(section, false);
|
|
15436
|
+
const pesPacketHeader = readPesPacketHeader(demuxer, section, false);
|
|
15408
15437
|
if (pesPacketHeader && pesPacketHeader.pts !== null) {
|
|
15409
15438
|
return {
|
|
15410
15439
|
pesPacketHeader,
|
|
@@ -15418,7 +15447,7 @@ var Mediabunny = (() => {
|
|
|
15418
15447
|
};
|
|
15419
15448
|
const firstSection = this.elementaryStream.firstSection;
|
|
15420
15449
|
assert(firstSection);
|
|
15421
|
-
const firstPesPacketHeader = readPesPacketHeader(firstSection, true);
|
|
15450
|
+
const firstPesPacketHeader = readPesPacketHeader(demuxer, firstSection, true);
|
|
15422
15451
|
assert(firstPesPacketHeader);
|
|
15423
15452
|
if (searchPts < firstPesPacketHeader.pts) {
|
|
15424
15453
|
return null;
|
|
@@ -15473,7 +15502,7 @@ var Mediabunny = (() => {
|
|
|
15473
15502
|
const retrieveEncodedPacket = async (sectionStartPos, predicate) => {
|
|
15474
15503
|
const section = await demuxer.readSection(sectionStartPos, true);
|
|
15475
15504
|
assert(section);
|
|
15476
|
-
const pesPacket = readPesPacket(section, true);
|
|
15505
|
+
const pesPacket = readPesPacket(demuxer, section, true);
|
|
15477
15506
|
assert(pesPacket);
|
|
15478
15507
|
const context = new PacketReadingContext(this.elementaryStream, pesPacket);
|
|
15479
15508
|
const buffer = new PacketBuffer(this, context);
|
|
@@ -15516,7 +15545,7 @@ var Mediabunny = (() => {
|
|
|
15516
15545
|
if (packetHeader.pid === pid && packetHeader.payloadUnitStartIndicator === 1) {
|
|
15517
15546
|
const section = await demuxer.readSection(currentPos, false);
|
|
15518
15547
|
if (section) {
|
|
15519
|
-
const nextPesHeader = readPesPacketHeader(section, false);
|
|
15548
|
+
const nextPesHeader = readPesPacketHeader(demuxer, section, false);
|
|
15520
15549
|
if (nextPesHeader && nextPesHeader.pts !== null) {
|
|
15521
15550
|
if (nextPesHeader.pts > searchPts) {
|
|
15522
15551
|
break outer;
|
|
@@ -15541,7 +15570,7 @@ var Mediabunny = (() => {
|
|
|
15541
15570
|
if (packetHeader.pid === pid && packetHeader.payloadUnitStartIndicator === 1) {
|
|
15542
15571
|
const section = await demuxer.readSection(pos, false);
|
|
15543
15572
|
if (section) {
|
|
15544
|
-
const header = readPesPacketHeader(section, false);
|
|
15573
|
+
const header = readPesPacketHeader(demuxer, section, false);
|
|
15545
15574
|
if (header && header.pts !== null) {
|
|
15546
15575
|
currentPesHeader = header;
|
|
15547
15576
|
break;
|
|
@@ -15586,7 +15615,7 @@ var Mediabunny = (() => {
|
|
|
15586
15615
|
isKeyPacket = pesHeader.randomAccessIndicator === 1;
|
|
15587
15616
|
} else {
|
|
15588
15617
|
assert(pesHeaderSection);
|
|
15589
|
-
const pesPacket = readPesPacket(pesHeaderSection, true);
|
|
15618
|
+
const pesPacket = readPesPacket(demuxer, pesHeaderSection, true);
|
|
15590
15619
|
assert(pesPacket);
|
|
15591
15620
|
const context = new PacketReadingContext(this.elementaryStream, pesPacket);
|
|
15592
15621
|
await context.markNextPacket();
|
|
@@ -15614,7 +15643,7 @@ var Mediabunny = (() => {
|
|
|
15614
15643
|
if (packetHeader.pid === pid && packetHeader.payloadUnitStartIndicator === 1) {
|
|
15615
15644
|
const section = await demuxer.readSection(currentPos, readSectionsInFull);
|
|
15616
15645
|
if (section) {
|
|
15617
|
-
const nextPesHeader = readPesPacketHeader(section, false);
|
|
15646
|
+
const nextPesHeader = readPesPacketHeader(demuxer, section, false);
|
|
15618
15647
|
if (nextPesHeader && nextPesHeader.pts !== null) {
|
|
15619
15648
|
pesHeader = nextPesHeader;
|
|
15620
15649
|
pesHeaderSection = section;
|
|
@@ -15640,7 +15669,7 @@ var Mediabunny = (() => {
|
|
|
15640
15669
|
if (packetHeader.pid === pid && packetHeader.payloadUnitStartIndicator === 1) {
|
|
15641
15670
|
const section = await demuxer.readSection(pos, readSectionsInFull);
|
|
15642
15671
|
if (section) {
|
|
15643
|
-
const header = readPesPacketHeader(section, false);
|
|
15672
|
+
const header = readPesPacketHeader(demuxer, section, false);
|
|
15644
15673
|
if (header && header.pts !== null) {
|
|
15645
15674
|
startPesHeader = header;
|
|
15646
15675
|
break;
|
|
@@ -15812,7 +15841,7 @@ var Mediabunny = (() => {
|
|
|
15812
15841
|
if (!nextSection) {
|
|
15813
15842
|
return;
|
|
15814
15843
|
}
|
|
15815
|
-
const nextPesPacket = readPesPacket(nextSection, false);
|
|
15844
|
+
const nextPesPacket = readPesPacket(this.demuxer, nextSection, false);
|
|
15816
15845
|
if (nextPesPacket) {
|
|
15817
15846
|
pesPacket = nextPesPacket;
|
|
15818
15847
|
break;
|
|
@@ -17084,6 +17113,9 @@ var Mediabunny = (() => {
|
|
|
17084
17113
|
if (options.useStreamReader !== void 0 && typeof options.useStreamReader !== "boolean") {
|
|
17085
17114
|
throw new TypeError("options.useStreamReader, when provided, must be a boolean.");
|
|
17086
17115
|
}
|
|
17116
|
+
if (options.handleUnhandledError !== void 0 && typeof options.handleUnhandledError !== "function") {
|
|
17117
|
+
throw new TypeError("options.handleUnhandledError, when provided, must be a function.");
|
|
17118
|
+
}
|
|
17087
17119
|
super();
|
|
17088
17120
|
/** @internal */
|
|
17089
17121
|
this._readers = /* @__PURE__ */ new WeakMap();
|
|
@@ -17102,7 +17134,8 @@ var Mediabunny = (() => {
|
|
|
17102
17134
|
});
|
|
17103
17135
|
}
|
|
17104
17136
|
},
|
|
17105
|
-
prefetchProfile: PREFETCH_PROFILES.fileSystem
|
|
17137
|
+
prefetchProfile: PREFETCH_PROFILES.fileSystem,
|
|
17138
|
+
handleUnhandledError: options.handleUnhandledError
|
|
17106
17139
|
});
|
|
17107
17140
|
this._orchestrator.fileSize = blob.size;
|
|
17108
17141
|
}
|
|
@@ -17210,6 +17243,9 @@ var Mediabunny = (() => {
|
|
|
17210
17243
|
if (options.fetchFn !== void 0 && typeof options.fetchFn !== "function") {
|
|
17211
17244
|
throw new TypeError("options.fetchFn, when provided, must be a function.");
|
|
17212
17245
|
}
|
|
17246
|
+
if (options.handleUnhandledError !== void 0 && typeof options.handleUnhandledError !== "function") {
|
|
17247
|
+
throw new TypeError("options.handleUnhandledError, when provided, must be a function.");
|
|
17248
|
+
}
|
|
17213
17249
|
const urlString = url2 instanceof Request ? url2.url : url2 instanceof URL ? url2.href : url2;
|
|
17214
17250
|
super(
|
|
17215
17251
|
urlString,
|
|
@@ -17266,7 +17302,8 @@ var Mediabunny = (() => {
|
|
|
17266
17302
|
maxCacheSize: options.maxCacheSize ?? 64 * 2 ** 20,
|
|
17267
17303
|
maxWorkerCount: options.parallelism ?? DEFAULT_PARALLELISM,
|
|
17268
17304
|
runWorker: this._runWorker.bind(this),
|
|
17269
|
-
prefetchProfile: PREFETCH_PROFILES.network
|
|
17305
|
+
prefetchProfile: PREFETCH_PROFILES.network,
|
|
17306
|
+
handleUnhandledError: options.handleUnhandledError
|
|
17270
17307
|
});
|
|
17271
17308
|
}
|
|
17272
17309
|
/** @internal */
|
|
@@ -17329,7 +17366,7 @@ var Mediabunny = (() => {
|
|
|
17329
17366
|
this.rootPath = response.url;
|
|
17330
17367
|
}
|
|
17331
17368
|
outer:
|
|
17332
|
-
if (this._orchestrator.fileSize === null) {
|
|
17369
|
+
if (this._orchestrator.fileSize === null && (response.status === 206 || response.type === "basic" && !response.headers.has("Content-Encoding"))) {
|
|
17333
17370
|
const contentRange = response.headers.get("Content-Range");
|
|
17334
17371
|
if (contentRange) {
|
|
17335
17372
|
const match = /\/(\d+)/.exec(contentRange);
|
|
@@ -17485,7 +17522,8 @@ var Mediabunny = (() => {
|
|
|
17485
17522
|
cancel: () => currentReader.cancel()
|
|
17486
17523
|
});
|
|
17487
17524
|
const backing = new ReadableStreamSource(wrappedStream, {
|
|
17488
|
-
maxCacheSize: this._orchestrator.options.maxCacheSize
|
|
17525
|
+
maxCacheSize: this._orchestrator.options.maxCacheSize,
|
|
17526
|
+
handleUnhandledError: this._options.handleUnhandledError
|
|
17489
17527
|
});
|
|
17490
17528
|
backing._endIndex = this._orchestrator.fileSize;
|
|
17491
17529
|
backing._cacheMissErrorMessage = "Attempted to read data from an already-evicted part of the cache. Because the HTTP server did not honor the range request, data can only be read sequentially, with old data being evicted from the cache. To fix this issue, either ensure your server responds to range requests with 206 Partial Content, or set maxCacheSize to Infinity in the UrlSource options. Note that the latter will store the entire file in the cache if needed, no matter how large.";
|
|
@@ -17585,7 +17623,8 @@ var Mediabunny = (() => {
|
|
|
17585
17623
|
return buffer;
|
|
17586
17624
|
},
|
|
17587
17625
|
maxCacheSize: options.maxCacheSize,
|
|
17588
|
-
prefetchProfile: "fileSystem"
|
|
17626
|
+
prefetchProfile: "fileSystem",
|
|
17627
|
+
handleUnhandledError: options.handleUnhandledError
|
|
17589
17628
|
});
|
|
17590
17629
|
}
|
|
17591
17630
|
/** @internal */
|
|
@@ -17621,6 +17660,9 @@ var Mediabunny = (() => {
|
|
|
17621
17660
|
if (options.dispose !== void 0 && typeof options.dispose !== "function") {
|
|
17622
17661
|
throw new TypeError("options.dispose, when provided, must be a function.");
|
|
17623
17662
|
}
|
|
17663
|
+
if (options.handleUnhandledError !== void 0 && typeof options.handleUnhandledError !== "function") {
|
|
17664
|
+
throw new TypeError("options.handleUnhandledError, when provided, must be a function.");
|
|
17665
|
+
}
|
|
17624
17666
|
if (options.maxCacheSize !== void 0 && (!isNumber(options.maxCacheSize) || options.maxCacheSize < 0)) {
|
|
17625
17667
|
throw new TypeError("options.maxCacheSize, when provided, must be a non-negative number.");
|
|
17626
17668
|
}
|
|
@@ -17636,7 +17678,8 @@ var Mediabunny = (() => {
|
|
|
17636
17678
|
maxWorkerCount: 2,
|
|
17637
17679
|
// Fixed for now, *should* be fine
|
|
17638
17680
|
prefetchProfile: PREFETCH_PROFILES[options.prefetchProfile ?? "none"],
|
|
17639
|
-
runWorker: this._runWorker.bind(this)
|
|
17681
|
+
runWorker: this._runWorker.bind(this),
|
|
17682
|
+
handleUnhandledError: options.handleUnhandledError
|
|
17640
17683
|
});
|
|
17641
17684
|
}
|
|
17642
17685
|
/** @internal */
|
|
@@ -17728,6 +17771,9 @@ var Mediabunny = (() => {
|
|
|
17728
17771
|
if (!options || typeof options !== "object") {
|
|
17729
17772
|
throw new TypeError("options must be an object.");
|
|
17730
17773
|
}
|
|
17774
|
+
if (options.handleUnhandledError !== void 0 && typeof options.handleUnhandledError !== "function") {
|
|
17775
|
+
throw new TypeError("options.handleUnhandledError, when provided, must be a function.");
|
|
17776
|
+
}
|
|
17731
17777
|
if (options.maxCacheSize !== void 0 && (!isNumber(options.maxCacheSize) || options.maxCacheSize < 0)) {
|
|
17732
17778
|
throw new TypeError("options.maxCacheSize, when provided, must be a non-negative number.");
|
|
17733
17779
|
}
|
|
@@ -17755,6 +17801,7 @@ var Mediabunny = (() => {
|
|
|
17755
17801
|
this._cacheMissErrorMessage = "Attempted to read data from an already-evicted part of the cache. With ReadableStreamSource, you must access the data more sequentially or increase the size of its cache.";
|
|
17756
17802
|
this._stream = stream;
|
|
17757
17803
|
this._maxCacheSize = options.maxCacheSize ?? 32 * 2 ** 20;
|
|
17804
|
+
this._handleUnhandledError = options.handleUnhandledError;
|
|
17758
17805
|
}
|
|
17759
17806
|
/** @internal */
|
|
17760
17807
|
_getFileSize() {
|
|
@@ -17823,6 +17870,8 @@ var Mediabunny = (() => {
|
|
|
17823
17870
|
if (this._pendingSlices.length > 0) {
|
|
17824
17871
|
this._pendingSlices.forEach((x) => x.reject(error));
|
|
17825
17872
|
this._pendingSlices.length = 0;
|
|
17873
|
+
} else if (this._handleUnhandledError) {
|
|
17874
|
+
this._handleUnhandledError(error);
|
|
17826
17875
|
} else {
|
|
17827
17876
|
throw error;
|
|
17828
17877
|
}
|
|
@@ -18106,7 +18155,11 @@ var Mediabunny = (() => {
|
|
|
18106
18155
|
if (this.disposed) {
|
|
18107
18156
|
return;
|
|
18108
18157
|
}
|
|
18109
|
-
|
|
18158
|
+
if (this.options.handleUnhandledError) {
|
|
18159
|
+
this.options.handleUnhandledError(error);
|
|
18160
|
+
} else {
|
|
18161
|
+
throw error;
|
|
18162
|
+
}
|
|
18110
18163
|
});
|
|
18111
18164
|
}
|
|
18112
18165
|
return result;
|
|
@@ -18194,7 +18247,11 @@ var Mediabunny = (() => {
|
|
|
18194
18247
|
worker.pendingSlices.forEach((x) => x.reject(error));
|
|
18195
18248
|
worker.pendingSlices.length = 0;
|
|
18196
18249
|
} else if (!worker.aborted && !this.disposed) {
|
|
18197
|
-
|
|
18250
|
+
if (this.options.handleUnhandledError) {
|
|
18251
|
+
this.options.handleUnhandledError(error);
|
|
18252
|
+
} else {
|
|
18253
|
+
throw error;
|
|
18254
|
+
}
|
|
18198
18255
|
}
|
|
18199
18256
|
}).finally(() => {
|
|
18200
18257
|
if (worker.running) {
|
|
@@ -22098,30 +22155,30 @@ var Mediabunny = (() => {
|
|
|
22098
22155
|
}
|
|
22099
22156
|
}
|
|
22100
22157
|
/**
|
|
22101
|
-
* Returns a new {@link AudioSample} containing only the frames in the range [
|
|
22158
|
+
* Returns a new {@link AudioSample} containing only the frames in the range [startFrame, endFrame). Both bounds
|
|
22102
22159
|
* must lie within this sample's range of frames. The returned sample's timestamp is shifted to match the start of
|
|
22103
22160
|
* the trimmed section.
|
|
22104
22161
|
*/
|
|
22105
|
-
trim(
|
|
22106
|
-
if (!Number.isInteger(
|
|
22107
|
-
throw new TypeError("
|
|
22162
|
+
trim(startFrame, endFrame = this.numberOfFrames) {
|
|
22163
|
+
if (!Number.isInteger(startFrame) || startFrame < 0) {
|
|
22164
|
+
throw new TypeError("startFrame must be a non-negative integer.");
|
|
22108
22165
|
}
|
|
22109
|
-
if (!Number.isInteger(
|
|
22110
|
-
throw new TypeError("
|
|
22166
|
+
if (!Number.isInteger(endFrame) || endFrame < 0) {
|
|
22167
|
+
throw new TypeError("endFrame must be a non-negative integer.");
|
|
22111
22168
|
}
|
|
22112
|
-
if (
|
|
22113
|
-
throw new RangeError("
|
|
22169
|
+
if (startFrame > this.numberOfFrames) {
|
|
22170
|
+
throw new RangeError("startFrame out of range.");
|
|
22114
22171
|
}
|
|
22115
|
-
if (
|
|
22116
|
-
throw new RangeError("
|
|
22172
|
+
if (endFrame > this.numberOfFrames) {
|
|
22173
|
+
throw new RangeError("endFrame out of range.");
|
|
22117
22174
|
}
|
|
22118
|
-
if (
|
|
22119
|
-
throw new RangeError("
|
|
22175
|
+
if (endFrame < startFrame) {
|
|
22176
|
+
throw new RangeError("endFrame must not be less than startFrame.");
|
|
22120
22177
|
}
|
|
22121
22178
|
if (this._closed) {
|
|
22122
22179
|
throw new Error("AudioSample is closed.");
|
|
22123
22180
|
}
|
|
22124
|
-
const frameCount =
|
|
22181
|
+
const frameCount = endFrame - startFrame;
|
|
22125
22182
|
const bytesPerSample = getBytesPerSample(this.format);
|
|
22126
22183
|
let data;
|
|
22127
22184
|
if (formatIsPlanar(this.format)) {
|
|
@@ -22132,7 +22189,7 @@ var Mediabunny = (() => {
|
|
|
22132
22189
|
this.copyTo(data.subarray(i * planeSize, (i + 1) * planeSize), {
|
|
22133
22190
|
planeIndex: i,
|
|
22134
22191
|
format: this.format,
|
|
22135
|
-
frameOffset:
|
|
22192
|
+
frameOffset: startFrame,
|
|
22136
22193
|
frameCount
|
|
22137
22194
|
});
|
|
22138
22195
|
}
|
|
@@ -22143,7 +22200,7 @@ var Mediabunny = (() => {
|
|
|
22143
22200
|
this.copyTo(data, {
|
|
22144
22201
|
planeIndex: 0,
|
|
22145
22202
|
format: this.format,
|
|
22146
|
-
frameOffset:
|
|
22203
|
+
frameOffset: startFrame,
|
|
22147
22204
|
frameCount
|
|
22148
22205
|
});
|
|
22149
22206
|
}
|
|
@@ -22153,7 +22210,7 @@ var Mediabunny = (() => {
|
|
|
22153
22210
|
format: this.format,
|
|
22154
22211
|
sampleRate: this.sampleRate,
|
|
22155
22212
|
numberOfChannels: this.numberOfChannels,
|
|
22156
|
-
timestamp: this.timestamp +
|
|
22213
|
+
timestamp: this.timestamp + startFrame / this.sampleRate
|
|
22157
22214
|
});
|
|
22158
22215
|
}
|
|
22159
22216
|
/**
|
|
@@ -27886,9 +27943,6 @@ var Mediabunny = (() => {
|
|
|
27886
27943
|
onTrackClose(track) {
|
|
27887
27944
|
}
|
|
27888
27945
|
validateTimestamp(track, timestampInSeconds, isKeyPacket) {
|
|
27889
|
-
if (timestampInSeconds < 0) {
|
|
27890
|
-
throw new Error(`Timestamps must be non-negative (got ${timestampInSeconds}s).`);
|
|
27891
|
-
}
|
|
27892
27946
|
let timestampInfo = this.trackTimestampInfo.get(track);
|
|
27893
27947
|
if (!timestampInfo) {
|
|
27894
27948
|
if (!isKeyPacket) {
|
|
@@ -28564,7 +28618,8 @@ var Mediabunny = (() => {
|
|
|
28564
28618
|
ascii("dash")
|
|
28565
28619
|
]);
|
|
28566
28620
|
var sidx = (muxer, referencedSize) => {
|
|
28567
|
-
|
|
28621
|
+
const earliestPresentationTime = Math.max(0, muxer.minWrittenTimestamp);
|
|
28622
|
+
let duration = Math.max(0, muxer.maxWrittenEndTimestamp - earliestPresentationTime);
|
|
28568
28623
|
if (!Number.isFinite(duration)) {
|
|
28569
28624
|
duration = 0;
|
|
28570
28625
|
}
|
|
@@ -28573,7 +28628,7 @@ var Mediabunny = (() => {
|
|
|
28573
28628
|
// Reference ID
|
|
28574
28629
|
u32(GLOBAL_TIMESCALE),
|
|
28575
28630
|
// Timescale
|
|
28576
|
-
u64(intoTimescale(
|
|
28631
|
+
u64(intoTimescale(earliestPresentationTime, GLOBAL_TIMESCALE)),
|
|
28577
28632
|
// Earliest presentation time
|
|
28578
28633
|
u64(0),
|
|
28579
28634
|
// First offset
|
|
@@ -28602,7 +28657,13 @@ var Mediabunny = (() => {
|
|
|
28602
28657
|
var mvhd = (creationTime, trackDatas) => {
|
|
28603
28658
|
const duration = Math.max(
|
|
28604
28659
|
0,
|
|
28605
|
-
...trackDatas.map((trackData) =>
|
|
28660
|
+
...trackDatas.map((trackData) => (
|
|
28661
|
+
// Round separately to match the edit list
|
|
28662
|
+
Math.max(
|
|
28663
|
+
0,
|
|
28664
|
+
intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(trackData.startTimestampOffset ?? 0, GLOBAL_TIMESCALE)
|
|
28665
|
+
)
|
|
28666
|
+
))
|
|
28606
28667
|
);
|
|
28607
28668
|
const nextTrackId = Math.max(0, ...trackDatas.map((x) => x.track.id)) + 1;
|
|
28608
28669
|
const needsU64 = !isU32(creationTime) || !isU32(duration);
|
|
@@ -28652,10 +28713,10 @@ var Mediabunny = (() => {
|
|
|
28652
28713
|
};
|
|
28653
28714
|
var trak = (trackData, creationTime) => {
|
|
28654
28715
|
const trackMetadata = getTrackMetadata(trackData);
|
|
28655
|
-
const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset
|
|
28716
|
+
const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset !== 0;
|
|
28656
28717
|
return box("trak", void 0, [
|
|
28657
28718
|
tkhd(trackData, creationTime),
|
|
28658
|
-
needsEditList ? edts(trackData
|
|
28719
|
+
needsEditList ? edts(trackData) : null,
|
|
28659
28720
|
mdia(trackData, creationTime),
|
|
28660
28721
|
trackMetadata.name !== void 0 ? box("udta", void 0, [
|
|
28661
28722
|
box("name", [
|
|
@@ -28666,7 +28727,10 @@ var Mediabunny = (() => {
|
|
|
28666
28727
|
]);
|
|
28667
28728
|
};
|
|
28668
28729
|
var tkhd = (trackData, creationTime) => {
|
|
28669
|
-
const durationInGlobalTimescale =
|
|
28730
|
+
const durationInGlobalTimescale = Math.max(
|
|
28731
|
+
0,
|
|
28732
|
+
intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(trackData.startTimestampOffset ?? 0, GLOBAL_TIMESCALE)
|
|
28733
|
+
);
|
|
28670
28734
|
const needsU64 = !isU32(creationTime) || !isU32(durationInGlobalTimescale);
|
|
28671
28735
|
const u32OrU64 = needsU64 ? u64 : u32;
|
|
28672
28736
|
let matrix;
|
|
@@ -28710,32 +28774,58 @@ var Mediabunny = (() => {
|
|
|
28710
28774
|
// Track height
|
|
28711
28775
|
]);
|
|
28712
28776
|
};
|
|
28713
|
-
var edts = (trackData
|
|
28714
|
-
const
|
|
28715
|
-
|
|
28716
|
-
|
|
28717
|
-
|
|
28718
|
-
|
|
28719
|
-
|
|
28720
|
-
|
|
28721
|
-
|
|
28722
|
-
|
|
28723
|
-
|
|
28724
|
-
|
|
28725
|
-
|
|
28726
|
-
|
|
28727
|
-
|
|
28728
|
-
|
|
28729
|
-
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
28733
|
-
|
|
28734
|
-
|
|
28735
|
-
|
|
28736
|
-
|
|
28737
|
-
|
|
28738
|
-
|
|
28777
|
+
var edts = (trackData) => {
|
|
28778
|
+
const offset = trackData.startTimestampOffset;
|
|
28779
|
+
assert(offset !== null);
|
|
28780
|
+
if (offset > 0) {
|
|
28781
|
+
const startOffset = intoTimescale(offset, GLOBAL_TIMESCALE);
|
|
28782
|
+
const mediaDuration = intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE);
|
|
28783
|
+
const needs64Bits = !isU32(startOffset) || !isU32(mediaDuration);
|
|
28784
|
+
const u32OrU64 = needs64Bits ? u64 : u32;
|
|
28785
|
+
const i32OrI64 = needs64Bits ? i64 : i32;
|
|
28786
|
+
return box("edts", void 0, [
|
|
28787
|
+
fullBox("elst", needs64Bits ? 1 : 0, 0, [
|
|
28788
|
+
u32(2),
|
|
28789
|
+
// Entry count
|
|
28790
|
+
// #1
|
|
28791
|
+
u32OrU64(startOffset),
|
|
28792
|
+
// Segment duration
|
|
28793
|
+
i32OrI64(-1),
|
|
28794
|
+
// Media time
|
|
28795
|
+
fixed_16_16(1),
|
|
28796
|
+
// Media rate
|
|
28797
|
+
// #2
|
|
28798
|
+
u32OrU64(mediaDuration),
|
|
28799
|
+
// Segment duration
|
|
28800
|
+
i32OrI64(0),
|
|
28801
|
+
// Media time
|
|
28802
|
+
fixed_16_16(1)
|
|
28803
|
+
// Media rate
|
|
28804
|
+
])
|
|
28805
|
+
]);
|
|
28806
|
+
} else {
|
|
28807
|
+
const mediaTime = intoTimescale(-offset, trackData.timescale);
|
|
28808
|
+
const mediaDuration = Math.max(
|
|
28809
|
+
0,
|
|
28810
|
+
intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(offset, GLOBAL_TIMESCALE)
|
|
28811
|
+
);
|
|
28812
|
+
const needs64Bits = !isI32(mediaTime) || !isU32(mediaDuration);
|
|
28813
|
+
const u32OrU64 = needs64Bits ? u64 : u32;
|
|
28814
|
+
const i32OrI64 = needs64Bits ? i64 : i32;
|
|
28815
|
+
return box("edts", void 0, [
|
|
28816
|
+
fullBox("elst", needs64Bits ? 1 : 0, 0, [
|
|
28817
|
+
u32(1),
|
|
28818
|
+
// Entry count
|
|
28819
|
+
// #1
|
|
28820
|
+
u32OrU64(mediaDuration),
|
|
28821
|
+
// Segment duration
|
|
28822
|
+
i32OrI64(mediaTime),
|
|
28823
|
+
// Media time
|
|
28824
|
+
fixed_16_16(1)
|
|
28825
|
+
// Media rate
|
|
28826
|
+
])
|
|
28827
|
+
]);
|
|
28828
|
+
}
|
|
28739
28829
|
};
|
|
28740
28830
|
var mdia = (trackData, creationTime) => box("mdia", void 0, [
|
|
28741
28831
|
mdhd(trackData, creationTime),
|
|
@@ -31044,7 +31134,7 @@ var Mediabunny = (() => {
|
|
|
31044
31134
|
currentChunk: null,
|
|
31045
31135
|
compactlyCodedChunkTable: [],
|
|
31046
31136
|
closed: false,
|
|
31047
|
-
lastCueEndTimestamp:
|
|
31137
|
+
lastCueEndTimestamp: null,
|
|
31048
31138
|
cueQueue: [],
|
|
31049
31139
|
nextSourceId: 0,
|
|
31050
31140
|
cueToSourceId: /* @__PURE__ */ new WeakMap()
|
|
@@ -31176,6 +31266,7 @@ var Mediabunny = (() => {
|
|
|
31176
31266
|
}
|
|
31177
31267
|
async processWebVTTCues(trackData, until) {
|
|
31178
31268
|
while (trackData.cueQueue.length > 0) {
|
|
31269
|
+
trackData.lastCueEndTimestamp ??= Math.min(0, trackData.cueQueue[0].timestamp);
|
|
31179
31270
|
const timestamps = /* @__PURE__ */ new Set([]);
|
|
31180
31271
|
for (const cue of trackData.cueQueue) {
|
|
31181
31272
|
assert(cue.timestamp <= until);
|
|
@@ -31259,9 +31350,8 @@ var Mediabunny = (() => {
|
|
|
31259
31350
|
return;
|
|
31260
31351
|
}
|
|
31261
31352
|
if (trackData.type === "audio" && trackData.info.requiresPcmTransformation) {
|
|
31262
|
-
|
|
31263
|
-
|
|
31264
|
-
}
|
|
31353
|
+
assert(!this.isFragmented);
|
|
31354
|
+
trackData.startTimestampOffset ??= trackData.timestampProcessingQueue[0].timestamp;
|
|
31265
31355
|
let totalDuration = 0;
|
|
31266
31356
|
for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {
|
|
31267
31357
|
const sample = trackData.timestampProcessingQueue[i];
|
|
@@ -31281,7 +31371,9 @@ var Mediabunny = (() => {
|
|
|
31281
31371
|
return;
|
|
31282
31372
|
}
|
|
31283
31373
|
const sortedTimestamps = trackData.timestampProcessingQueue.map((x) => x.timestamp).sort((a, b) => a - b);
|
|
31284
|
-
if (
|
|
31374
|
+
if (this.isFragmented) {
|
|
31375
|
+
trackData.startTimestampOffset ??= Math.min(sortedTimestamps[0], 0);
|
|
31376
|
+
} else {
|
|
31285
31377
|
trackData.startTimestampOffset ??= sortedTimestamps[0];
|
|
31286
31378
|
}
|
|
31287
31379
|
for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {
|
|
@@ -31532,11 +31624,16 @@ var Mediabunny = (() => {
|
|
|
31532
31624
|
let fragmentStartTimestamp = Infinity;
|
|
31533
31625
|
for (let i = 0; i < tracksInFragment.length; i++) {
|
|
31534
31626
|
const trackData = tracksInFragment[i];
|
|
31627
|
+
assert(trackData.currentChunk);
|
|
31628
|
+
assert(trackData.startTimestampOffset !== null);
|
|
31535
31629
|
trackData.currentChunk.offset = currentPos;
|
|
31536
31630
|
trackData.currentChunk.moofOffset = moofOffset;
|
|
31537
31631
|
trackData.currentChunk.trafIndex = i;
|
|
31632
|
+
trackData.currentChunk.startTimestamp -= trackData.startTimestampOffset;
|
|
31538
31633
|
for (const sample of trackData.currentChunk.samples) {
|
|
31539
31634
|
currentPos += sample.size;
|
|
31635
|
+
sample.timestamp -= trackData.startTimestampOffset;
|
|
31636
|
+
sample.decodeTimestamp -= trackData.startTimestampOffset;
|
|
31540
31637
|
}
|
|
31541
31638
|
fragmentStartTimestamp = Math.min(fragmentStartTimestamp, trackData.currentChunk.startTimestamp);
|
|
31542
31639
|
}
|
|
@@ -31838,6 +31935,7 @@ var Mediabunny = (() => {
|
|
|
31838
31935
|
this.trackDatasInCurrentCluster = /* @__PURE__ */ new Map();
|
|
31839
31936
|
this.startTimestamp = Infinity;
|
|
31840
31937
|
this.endTimestamp = -Infinity;
|
|
31938
|
+
this.warnedAboutTooNegativeTimestamp = false;
|
|
31841
31939
|
this.format = format;
|
|
31842
31940
|
}
|
|
31843
31941
|
async start() {
|
|
@@ -32635,6 +32733,13 @@ ${cue.notes ?? ""}`;
|
|
|
32635
32733
|
}
|
|
32636
32734
|
const relativeTimestamp = msTimestamp - this.currentClusterStartMsTimestamp;
|
|
32637
32735
|
if (relativeTimestamp < MIN_CLUSTER_TIMESTAMP_MS) {
|
|
32736
|
+
if (!this.warnedAboutTooNegativeTimestamp) {
|
|
32737
|
+
const formatName = this.format instanceof WebMOutputFormat ? "WebM" : "Matroska";
|
|
32738
|
+
Logging._warn(
|
|
32739
|
+
`Packets had to be discarded because their timestamp is too negative to represent in ${formatName}.`
|
|
32740
|
+
);
|
|
32741
|
+
this.warnedAboutTooNegativeTimestamp = true;
|
|
32742
|
+
}
|
|
32638
32743
|
return;
|
|
32639
32744
|
}
|
|
32640
32745
|
const prelude = new Uint8Array(4);
|
|
@@ -32683,6 +32788,7 @@ ${cue.notes ?? ""}`;
|
|
|
32683
32788
|
}
|
|
32684
32789
|
/** Creates a new Cluster element to contain media chunks. */
|
|
32685
32790
|
createNewCluster(msTimestamp) {
|
|
32791
|
+
msTimestamp = Math.max(0, msTimestamp);
|
|
32686
32792
|
if (this.currentCluster) {
|
|
32687
32793
|
this.finalizeCurrentCluster();
|
|
32688
32794
|
}
|
|
@@ -32727,7 +32833,8 @@ ${cue.notes ?? ""}`;
|
|
|
32727
32833
|
for (const [msTimestamp, trackDatas] of groupedAndSortedByTimestamp) {
|
|
32728
32834
|
assert(this.cues);
|
|
32729
32835
|
this.cues.data.push({ id: 187 /* CuePoint */, data: [
|
|
32730
|
-
{ id: 179 /* CueTime */, data: msTimestamp },
|
|
32836
|
+
{ id: 179 /* CueTime */, data: Math.max(0, msTimestamp) },
|
|
32837
|
+
// CueTime is unsigned
|
|
32731
32838
|
// Create CueTrackPositions for each track that starts at this timestamp
|
|
32732
32839
|
...trackDatas.map((trackData) => {
|
|
32733
32840
|
return { id: 183 /* CueTrackPositions */, data: [
|
|
@@ -33786,24 +33893,26 @@ ${cue.notes ?? ""}`;
|
|
|
33786
33893
|
pesView.setUint8(6, 132);
|
|
33787
33894
|
pesView.setUint8(7, includeDts ? 192 : 128);
|
|
33788
33895
|
pesView.setUint8(8, headerDataLength);
|
|
33789
|
-
const
|
|
33896
|
+
const unwrappedPts = Math.round(queuedPacket.presentationTimestamp * TIMESCALE);
|
|
33897
|
+
const pts = modEuclid(unwrappedPts, TIMESTAMP_MODULUS);
|
|
33790
33898
|
ptsDtsBitstream.pos = 0;
|
|
33791
33899
|
ptsDtsBitstream.writeBits(4, includeDts ? 3 : 2);
|
|
33792
|
-
ptsDtsBitstream.writeBits(3, pts
|
|
33900
|
+
ptsDtsBitstream.writeBits(3, Math.floor(pts / 2 ** 30));
|
|
33793
33901
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33794
|
-
ptsDtsBitstream.writeBits(15, pts
|
|
33902
|
+
ptsDtsBitstream.writeBits(15, Math.floor(pts / 2 ** 15) % 2 ** 15);
|
|
33795
33903
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33796
|
-
ptsDtsBitstream.writeBits(15, pts
|
|
33904
|
+
ptsDtsBitstream.writeBits(15, pts % 2 ** 15);
|
|
33797
33905
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33798
33906
|
if (includeDts) {
|
|
33799
33907
|
assert(queuedPacket.decodeTimestamp !== null);
|
|
33800
|
-
const
|
|
33908
|
+
const unwrappedDts = Math.round(queuedPacket.decodeTimestamp * TIMESCALE);
|
|
33909
|
+
const dts = modEuclid(unwrappedDts, TIMESTAMP_MODULUS);
|
|
33801
33910
|
ptsDtsBitstream.writeBits(4, 1);
|
|
33802
|
-
ptsDtsBitstream.writeBits(3, dts
|
|
33911
|
+
ptsDtsBitstream.writeBits(3, Math.floor(dts / 2 ** 30));
|
|
33803
33912
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33804
|
-
ptsDtsBitstream.writeBits(15, dts
|
|
33913
|
+
ptsDtsBitstream.writeBits(15, Math.floor(dts / 2 ** 15) % 2 ** 15);
|
|
33805
33914
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33806
|
-
ptsDtsBitstream.writeBits(15, dts
|
|
33915
|
+
ptsDtsBitstream.writeBits(15, dts % 2 ** 15);
|
|
33807
33916
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33808
33917
|
}
|
|
33809
33918
|
const totalLength = pesHeaderBuffer.length + queuedPacket.data.length;
|
|
@@ -35390,8 +35499,8 @@ ${cue.notes ?? ""}`;
|
|
|
35390
35499
|
* to respect writer and encoder backpressure.
|
|
35391
35500
|
*/
|
|
35392
35501
|
add(timestamp, duration = 0, encodeOptions) {
|
|
35393
|
-
if (!Number.isFinite(timestamp)
|
|
35394
|
-
throw new TypeError("timestamp must be a
|
|
35502
|
+
if (!Number.isFinite(timestamp)) {
|
|
35503
|
+
throw new TypeError("timestamp must be a finite number.");
|
|
35395
35504
|
}
|
|
35396
35505
|
if (!Number.isFinite(duration) || duration < 0) {
|
|
35397
35506
|
throw new TypeError("duration must be a non-negative number.");
|
|
@@ -36236,19 +36345,24 @@ ${cue.notes ?? ""}`;
|
|
|
36236
36345
|
var AudioBufferSource = class extends AudioSource {
|
|
36237
36346
|
/**
|
|
36238
36347
|
* Creates a new {@link AudioBufferSource} whose `AudioBuffer` instances are encoded according to the specified
|
|
36239
|
-
* {@link AudioEncodingConfig}.
|
|
36348
|
+
* {@link AudioEncodingConfig} and {@link AudioBufferSourceOptions}.
|
|
36240
36349
|
*/
|
|
36241
|
-
constructor(encodingConfig) {
|
|
36350
|
+
constructor(encodingConfig, options = {}) {
|
|
36242
36351
|
validateAudioEncodingConfig(encodingConfig);
|
|
36352
|
+
if (typeof options !== "object" || !options) {
|
|
36353
|
+
throw new TypeError("options must be an object.");
|
|
36354
|
+
}
|
|
36355
|
+
if (options.startTimestamp !== void 0 && !Number.isFinite(options.startTimestamp)) {
|
|
36356
|
+
throw new TypeError("options.startTimestamp, when provided, must be a finite number.");
|
|
36357
|
+
}
|
|
36243
36358
|
super(encodingConfig.codec);
|
|
36244
|
-
/** @internal */
|
|
36245
|
-
this._accumulatedTime = 0;
|
|
36246
36359
|
this._encoder = new AudioEncoderWrapper(this, encodingConfig);
|
|
36360
|
+
this._accumulatedTime = options.startTimestamp ?? 0;
|
|
36247
36361
|
}
|
|
36248
36362
|
/**
|
|
36249
|
-
* Converts an AudioBuffer to audio samples, encodes them and adds them to the output. The first AudioBuffer will
|
|
36250
|
-
* be played at timestamp 0, and
|
|
36251
|
-
*
|
|
36363
|
+
* Converts an AudioBuffer to audio samples, encodes them and adds them to the output. The first `AudioBuffer` will
|
|
36364
|
+
* be played at the configured start timestamp (the default is 0), and each subsequent `AudioBuffer` will be placed
|
|
36365
|
+
* directly after the previous one.
|
|
36252
36366
|
*
|
|
36253
36367
|
* @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise
|
|
36254
36368
|
* to respect writer and encoder backpressure.
|
|
@@ -37830,6 +37944,9 @@ ${cue.notes ?? ""}`;
|
|
|
37830
37944
|
get supportsTimestampedMediaData() {
|
|
37831
37945
|
return true;
|
|
37832
37946
|
}
|
|
37947
|
+
get negativeTimestampSupport() {
|
|
37948
|
+
return "full";
|
|
37949
|
+
}
|
|
37833
37950
|
/** @internal */
|
|
37834
37951
|
_createMuxer(output) {
|
|
37835
37952
|
return new IsobmffMuxer2(output, this);
|
|
@@ -38004,6 +38121,9 @@ ${cue.notes ?? ""}`;
|
|
|
38004
38121
|
get supportsTimestampedMediaData() {
|
|
38005
38122
|
return true;
|
|
38006
38123
|
}
|
|
38124
|
+
get negativeTimestampSupport() {
|
|
38125
|
+
return "prefer-non-negative";
|
|
38126
|
+
}
|
|
38007
38127
|
};
|
|
38008
38128
|
var WebMOutputFormat = class extends MkvOutputFormat2 {
|
|
38009
38129
|
/** Creates a new {@link WebMOutputFormat} configured with the specified `options`. */
|
|
@@ -38081,6 +38201,9 @@ ${cue.notes ?? ""}`;
|
|
|
38081
38201
|
get supportsTimestampedMediaData() {
|
|
38082
38202
|
return false;
|
|
38083
38203
|
}
|
|
38204
|
+
get negativeTimestampSupport() {
|
|
38205
|
+
return null;
|
|
38206
|
+
}
|
|
38084
38207
|
};
|
|
38085
38208
|
var WavOutputFormat = class extends OutputFormat {
|
|
38086
38209
|
/** Creates a new {@link WavOutputFormat} configured with the specified `options`. */
|
|
@@ -38135,6 +38258,9 @@ ${cue.notes ?? ""}`;
|
|
|
38135
38258
|
get supportsTimestampedMediaData() {
|
|
38136
38259
|
return false;
|
|
38137
38260
|
}
|
|
38261
|
+
get negativeTimestampSupport() {
|
|
38262
|
+
return null;
|
|
38263
|
+
}
|
|
38138
38264
|
};
|
|
38139
38265
|
var OggOutputFormat = class extends OutputFormat {
|
|
38140
38266
|
/** Creates a new {@link OggOutputFormat} configured with the specified `options`. */
|
|
@@ -38185,6 +38311,9 @@ ${cue.notes ?? ""}`;
|
|
|
38185
38311
|
get supportsTimestampedMediaData() {
|
|
38186
38312
|
return false;
|
|
38187
38313
|
}
|
|
38314
|
+
get negativeTimestampSupport() {
|
|
38315
|
+
return null;
|
|
38316
|
+
}
|
|
38188
38317
|
};
|
|
38189
38318
|
var AdtsOutputFormat = class extends OutputFormat {
|
|
38190
38319
|
/** Creates a new {@link AdtsOutputFormat} configured with the specified `options`. */
|
|
@@ -38229,6 +38358,9 @@ ${cue.notes ?? ""}`;
|
|
|
38229
38358
|
get supportsTimestampedMediaData() {
|
|
38230
38359
|
return false;
|
|
38231
38360
|
}
|
|
38361
|
+
get negativeTimestampSupport() {
|
|
38362
|
+
return null;
|
|
38363
|
+
}
|
|
38232
38364
|
};
|
|
38233
38365
|
var FlacOutputFormat = class extends OutputFormat {
|
|
38234
38366
|
/** Creates a new {@link FlacOutputFormat} configured with the specified `options`. */
|
|
@@ -38273,6 +38405,9 @@ ${cue.notes ?? ""}`;
|
|
|
38273
38405
|
get supportsTimestampedMediaData() {
|
|
38274
38406
|
return false;
|
|
38275
38407
|
}
|
|
38408
|
+
get negativeTimestampSupport() {
|
|
38409
|
+
return null;
|
|
38410
|
+
}
|
|
38276
38411
|
};
|
|
38277
38412
|
var MpegTsOutputFormat = class extends OutputFormat {
|
|
38278
38413
|
/** Creates a new {@link MpegTsOutputFormat} configured with the specified `options`. */
|
|
@@ -38323,6 +38458,9 @@ ${cue.notes ?? ""}`;
|
|
|
38323
38458
|
get supportsTimestampedMediaData() {
|
|
38324
38459
|
return true;
|
|
38325
38460
|
}
|
|
38461
|
+
get negativeTimestampSupport() {
|
|
38462
|
+
return "prefer-non-negative";
|
|
38463
|
+
}
|
|
38326
38464
|
};
|
|
38327
38465
|
var HlsOutputFormat = class extends OutputFormat {
|
|
38328
38466
|
/** Creates a new {@link HlsOutputFormat} configured with the specified `options`. */
|
|
@@ -38416,6 +38554,19 @@ ${cue.notes ?? ""}`;
|
|
|
38416
38554
|
get supportsTimestampedMediaData() {
|
|
38417
38555
|
return true;
|
|
38418
38556
|
}
|
|
38557
|
+
get negativeTimestampSupport() {
|
|
38558
|
+
const formats = toArray(this._options.segmentFormat);
|
|
38559
|
+
if (formats.some((format) => format.negativeTimestampSupport === "none")) {
|
|
38560
|
+
return "none";
|
|
38561
|
+
}
|
|
38562
|
+
if (formats.some((format) => format.negativeTimestampSupport === "prefer-non-negative")) {
|
|
38563
|
+
return "prefer-non-negative";
|
|
38564
|
+
}
|
|
38565
|
+
if (formats.some((format) => format.negativeTimestampSupport === "full")) {
|
|
38566
|
+
return "full";
|
|
38567
|
+
}
|
|
38568
|
+
return null;
|
|
38569
|
+
}
|
|
38419
38570
|
/** @internal */
|
|
38420
38571
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
38421
38572
|
_codecUnsupportedHint(codec) {
|
|
@@ -39154,15 +39305,16 @@ ${cue.notes ?? ""}`;
|
|
|
39154
39305
|
var Conversion = class _Conversion {
|
|
39155
39306
|
/** Creates a new Conversion instance (duh). */
|
|
39156
39307
|
constructor(options) {
|
|
39157
|
-
/**
|
|
39158
|
-
|
|
39159
|
-
|
|
39160
|
-
|
|
39161
|
-
|
|
39162
|
-
|
|
39163
|
-
|
|
39164
|
-
|
|
39165
|
-
|
|
39308
|
+
/** @internal */
|
|
39309
|
+
this._state = "idle";
|
|
39310
|
+
/** @internal */
|
|
39311
|
+
this._timestampOffset = 0;
|
|
39312
|
+
/** @internal */
|
|
39313
|
+
this._timestampOffsetAdjusted = false;
|
|
39314
|
+
/** @internal */
|
|
39315
|
+
this._copyTimestampPossible = /* @__PURE__ */ new Map();
|
|
39316
|
+
/** @internal */
|
|
39317
|
+
this._copyStartPackets = /* @__PURE__ */ new Map();
|
|
39166
39318
|
/** @internal */
|
|
39167
39319
|
this._nextOutputTrackId = 0;
|
|
39168
39320
|
/** @internal */
|
|
@@ -39233,6 +39385,22 @@ ${cue.notes ?? ""}`;
|
|
|
39233
39385
|
if (options.composable !== void 0 && typeof options.composable !== "boolean") {
|
|
39234
39386
|
throw new TypeError("options.composable, when provided, must be a boolean.");
|
|
39235
39387
|
}
|
|
39388
|
+
if (options.copy !== void 0 && options.copy !== false) {
|
|
39389
|
+
if (!options.copy || typeof options.copy !== "object") {
|
|
39390
|
+
throw new TypeError("options.copy, when provided, must be an object or false.");
|
|
39391
|
+
}
|
|
39392
|
+
if (options.copy.mode !== void 0 && !["forced", "preferred"].includes(options.copy.mode)) {
|
|
39393
|
+
throw new TypeError("options.copy.mode, when provided, must be 'forced' or 'preferred'.");
|
|
39394
|
+
}
|
|
39395
|
+
if (options.copy.shiftTolerance !== void 0 && (!isNumber(options.copy.shiftTolerance) || options.copy.shiftTolerance < 0)) {
|
|
39396
|
+
throw new TypeError("options.copy.shiftTolerance, when provided, must be a non-negative number.");
|
|
39397
|
+
}
|
|
39398
|
+
if (options.copy.boundaryPolicy !== void 0 && !["expand", "shrink"].includes(options.copy.boundaryPolicy)) {
|
|
39399
|
+
throw new TypeError(
|
|
39400
|
+
"options.copy.boundaryPolicy, when provided, must be 'expand' or 'shrink'."
|
|
39401
|
+
);
|
|
39402
|
+
}
|
|
39403
|
+
}
|
|
39236
39404
|
const composable = options.composable ?? false;
|
|
39237
39405
|
if (!composable) {
|
|
39238
39406
|
if (options.output.tracks.length > 0 || Object.keys(options.output._metadataTags).length > 0 || options.output.state !== "pending") {
|
|
@@ -39274,8 +39442,8 @@ ${cue.notes ?? ""}`;
|
|
|
39274
39442
|
if (options.trim?.start !== void 0 && !Number.isFinite(options.trim.start)) {
|
|
39275
39443
|
throw new TypeError("options.trim.start, when provided, must be a finite number.");
|
|
39276
39444
|
}
|
|
39277
|
-
if (options.trim?.end !== void 0 && !
|
|
39278
|
-
throw new TypeError("options.trim.end, when provided, must be a
|
|
39445
|
+
if (options.trim?.end !== void 0 && !isNumber(options.trim.end)) {
|
|
39446
|
+
throw new TypeError("options.trim.end, when provided, must be a number.");
|
|
39279
39447
|
}
|
|
39280
39448
|
if (options.trim?.start !== void 0 && options.trim.end !== void 0 && options.trim.start >= options.trim.end) {
|
|
39281
39449
|
throw new TypeError("options.trim.start must be less than options.trim.end.");
|
|
@@ -39290,10 +39458,24 @@ ${cue.notes ?? ""}`;
|
|
|
39290
39458
|
throw new TypeError("options.showWarnings, when provided, must be a boolean.");
|
|
39291
39459
|
}
|
|
39292
39460
|
this._options = options;
|
|
39461
|
+
this._copyMode = options.copy === false ? false : options.copy?.mode ?? "preferred";
|
|
39462
|
+
this._copyTimestampShiftTolerance = options.copy === false ? 0 : options.copy?.shiftTolerance ?? 0;
|
|
39463
|
+
this._copyBoundaryPolicy = options.copy === false ? "expand" : options.copy?.boundaryPolicy ?? "expand";
|
|
39293
39464
|
this._composable = composable;
|
|
39294
39465
|
this.input = options.input;
|
|
39295
39466
|
this.output = options.output;
|
|
39296
39467
|
}
|
|
39468
|
+
/**
|
|
39469
|
+
* The current state of the conversion.
|
|
39470
|
+
*
|
|
39471
|
+
* - `'idle'`: The conversion is not currently executing and isn't done; `execute` can be called.
|
|
39472
|
+
* - `'executing'`: A call to `execute` is currently running.
|
|
39473
|
+
* - `'canceled'`: The conversion has been canceled and can no longer be executed.
|
|
39474
|
+
* - `'done'`: The conversion has run to completion. Subsequent calls to `execute` do nothing.
|
|
39475
|
+
*/
|
|
39476
|
+
get state() {
|
|
39477
|
+
return this._state;
|
|
39478
|
+
}
|
|
39297
39479
|
/** Initializes a new conversion process without starting the conversion. */
|
|
39298
39480
|
static async init(options) {
|
|
39299
39481
|
const conversion = new _Conversion(options);
|
|
@@ -39400,6 +39582,7 @@ ${cue.notes ?? ""}`;
|
|
|
39400
39582
|
);
|
|
39401
39583
|
}
|
|
39402
39584
|
this._endTimestamp = Math.max(this._options.trim?.end ?? Infinity, this._startTimestamp);
|
|
39585
|
+
this._timestampOffset = -this._startTimestamp;
|
|
39403
39586
|
for (let i = 0; i < filteredTracks.length; i++) {
|
|
39404
39587
|
const track = filteredTracks[i];
|
|
39405
39588
|
const options = filteredTrackOptions[i];
|
|
@@ -39578,13 +39761,13 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39578
39761
|
"Cannot execute this conversion because its output configuration is invalid. Make sure to always check the isValid field before executing a conversion.\n" + this._getInvalidityExplanation().join("")
|
|
39579
39762
|
);
|
|
39580
39763
|
}
|
|
39581
|
-
if (this.
|
|
39764
|
+
if (this._state === "executing") {
|
|
39582
39765
|
throw new Error("Cannot call execute() while a previous call to execute() is still running.");
|
|
39583
39766
|
}
|
|
39584
|
-
if (this.
|
|
39767
|
+
if (this._state === "canceled") {
|
|
39585
39768
|
throw new ConversionCanceledError();
|
|
39586
39769
|
}
|
|
39587
|
-
if (this.
|
|
39770
|
+
if (this._state === "done") {
|
|
39588
39771
|
return;
|
|
39589
39772
|
}
|
|
39590
39773
|
if (this._composable && this.output.state === "pending") {
|
|
@@ -39592,11 +39775,11 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39592
39775
|
"A composable conversion requires the output to be started. Call start() on the output before executing the conversion."
|
|
39593
39776
|
);
|
|
39594
39777
|
}
|
|
39595
|
-
this.
|
|
39778
|
+
this._state = "executing";
|
|
39596
39779
|
this._executionUntil = options.until ?? Infinity;
|
|
39597
39780
|
this._pauseRequested = options.pauseSignal?.aborted ?? false;
|
|
39598
39781
|
const onPause = () => {
|
|
39599
|
-
if (this.
|
|
39782
|
+
if (this._state !== "executing") {
|
|
39600
39783
|
return;
|
|
39601
39784
|
}
|
|
39602
39785
|
this._pauseRequested = true;
|
|
@@ -39646,18 +39829,18 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39646
39829
|
try {
|
|
39647
39830
|
await Promise.all(this._trackPumps.map((x) => x.resolvers.promise));
|
|
39648
39831
|
} catch (error) {
|
|
39649
|
-
if (this.
|
|
39832
|
+
if (this._state !== "canceled") {
|
|
39650
39833
|
void this.cancel();
|
|
39651
39834
|
}
|
|
39652
39835
|
throw error;
|
|
39653
39836
|
} finally {
|
|
39654
39837
|
options.pauseSignal?.removeEventListener("abort", onPause);
|
|
39655
39838
|
}
|
|
39656
|
-
if (this.
|
|
39839
|
+
if (this._state === "canceled") {
|
|
39657
39840
|
throw new ConversionCanceledError();
|
|
39658
39841
|
}
|
|
39659
39842
|
const isDone = this._trackPumps.every((x) => x.done);
|
|
39660
|
-
this.
|
|
39843
|
+
this._state = isDone ? "done" : "idle";
|
|
39661
39844
|
if (isDone) {
|
|
39662
39845
|
if (!this._composable) {
|
|
39663
39846
|
await this.output.finalize();
|
|
@@ -39673,14 +39856,14 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39673
39856
|
* Does nothing if the conversion is already complete.
|
|
39674
39857
|
*/
|
|
39675
39858
|
async cancel() {
|
|
39676
|
-
if (this.
|
|
39859
|
+
if (this._state === "done") {
|
|
39677
39860
|
return;
|
|
39678
39861
|
}
|
|
39679
|
-
if (this.
|
|
39862
|
+
if (this._state === "canceled") {
|
|
39680
39863
|
Logging._warn("Conversion already canceled.");
|
|
39681
39864
|
return;
|
|
39682
39865
|
}
|
|
39683
|
-
this.
|
|
39866
|
+
this._state = "canceled";
|
|
39684
39867
|
for (const pump of this._trackPumps) {
|
|
39685
39868
|
pump.wake?.();
|
|
39686
39869
|
}
|
|
@@ -39726,10 +39909,63 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39726
39909
|
width = ceilToMultipleOfTwo(trackOptions.width);
|
|
39727
39910
|
height = ceilToMultipleOfTwo(trackOptions.height);
|
|
39728
39911
|
}
|
|
39729
|
-
const firstTimestamp = await track.getFirstTimestamp();
|
|
39730
39912
|
let videoCodecs = this.output.format.getSupportedVideoCodecs();
|
|
39731
|
-
const needsTranscode = !!trackOptions.forceTranscode || firstTimestamp < this._startTimestamp || !!trackOptions.frameRate || trackOptions.keyFrameInterval !== void 0 || trackOptions.process !== void 0 || trackOptions.quality !== void 0 || trackOptions.bitrate !== void 0 || !videoCodecs.includes(sourceCodec) || trackOptions.codec && trackOptions.codec !== sourceCodec || width !== originalWidth || height !== originalHeight || totalRotation !== 0 && !canUseRotationMetadata || !!crop;
|
|
39732
39913
|
const alpha = trackOptions.alpha ?? "discard";
|
|
39914
|
+
let needsTranscode = !this._copyMode || !!trackOptions.forceTranscode || !!trackOptions.frameRate || trackOptions.keyFrameInterval !== void 0 || trackOptions.process !== void 0 || trackOptions.quality !== void 0 || trackOptions.bitrate !== void 0 || !videoCodecs.includes(sourceCodec) || trackOptions.codec && trackOptions.codec !== sourceCodec || width !== originalWidth || height !== originalHeight || totalRotation !== 0 && !canUseRotationMetadata || !!crop;
|
|
39915
|
+
let copyStartPacket = null;
|
|
39916
|
+
if (!needsTranscode) {
|
|
39917
|
+
const sink = new EncodedPacketSink(track);
|
|
39918
|
+
let startPacket = await sink.getKeyPacket(this._startTimestamp, { verifyKeyPackets: true }) ?? await sink.getFirstKeyPacket({ verifyKeyPackets: true });
|
|
39919
|
+
if (startPacket && startPacket.timestamp < this._startTimestamp && startPacket.timestamp + startPacket.duration <= this._startTimestamp && this._copyBoundaryPolicy === "shrink") {
|
|
39920
|
+
startPacket = await sink.getNextKeyPacket(startPacket, { verifyKeyPackets: true });
|
|
39921
|
+
}
|
|
39922
|
+
copyStartPacket = startPacket;
|
|
39923
|
+
if (startPacket) {
|
|
39924
|
+
const effectiveStartTimestamp = this._copyBoundaryPolicy === "shrink" ? Math.max(startPacket.timestamp, this._startTimestamp) : startPacket.timestamp;
|
|
39925
|
+
if (!this.output.format.supportsTimestampedMediaData) {
|
|
39926
|
+
if (this._timestampOffsetAdjusted) {
|
|
39927
|
+
const isValid = effectiveStartTimestamp + this._timestampOffset === 0;
|
|
39928
|
+
if (!isValid) {
|
|
39929
|
+
needsTranscode = true;
|
|
39930
|
+
}
|
|
39931
|
+
} else {
|
|
39932
|
+
const correction = clamp(
|
|
39933
|
+
this._startTimestamp - effectiveStartTimestamp,
|
|
39934
|
+
-this._copyTimestampShiftTolerance,
|
|
39935
|
+
this._copyTimestampShiftTolerance
|
|
39936
|
+
);
|
|
39937
|
+
const shiftedStartTimestamp = effectiveStartTimestamp + correction;
|
|
39938
|
+
const isValid = shiftedStartTimestamp === this._startTimestamp;
|
|
39939
|
+
if (isValid) {
|
|
39940
|
+
this._timestampOffset = -this._startTimestamp + correction;
|
|
39941
|
+
this._timestampOffsetAdjusted = true;
|
|
39942
|
+
} else {
|
|
39943
|
+
needsTranscode = true;
|
|
39944
|
+
}
|
|
39945
|
+
}
|
|
39946
|
+
} else if (this.output.format.negativeTimestampSupport !== "full" && effectiveStartTimestamp < this._startTimestamp) {
|
|
39947
|
+
const correction = Math.min(
|
|
39948
|
+
this._startTimestamp - effectiveStartTimestamp,
|
|
39949
|
+
this._copyTimestampShiftTolerance
|
|
39950
|
+
);
|
|
39951
|
+
const shiftedStartTimestamp = effectiveStartTimestamp + correction;
|
|
39952
|
+
const isValid = shiftedStartTimestamp >= this._startTimestamp || this.output.format.negativeTimestampSupport === "prefer-non-negative" && this._copyMode === "forced";
|
|
39953
|
+
if (isValid) {
|
|
39954
|
+
this._timestampOffset = Math.max(this._timestampOffset, -this._startTimestamp + correction);
|
|
39955
|
+
} else {
|
|
39956
|
+
needsTranscode = true;
|
|
39957
|
+
}
|
|
39958
|
+
}
|
|
39959
|
+
}
|
|
39960
|
+
}
|
|
39961
|
+
if (needsTranscode && this._copyMode === "forced") {
|
|
39962
|
+
this.discardedTracks.push({
|
|
39963
|
+
track,
|
|
39964
|
+
reason: "cannot_copy",
|
|
39965
|
+
trackOptions
|
|
39966
|
+
});
|
|
39967
|
+
return;
|
|
39968
|
+
}
|
|
39733
39969
|
if (!needsTranscode) {
|
|
39734
39970
|
const source = new EncodedVideoPacketSource(sourceCodec);
|
|
39735
39971
|
videoSource = source;
|
|
@@ -39737,18 +39973,51 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39737
39973
|
const sink = new EncodedPacketSink(track);
|
|
39738
39974
|
const decoderConfig = await track.getDecoderConfig();
|
|
39739
39975
|
const meta = { decoderConfig: decoderConfig ?? void 0 };
|
|
39740
|
-
for await (const packet of sink.packets(
|
|
39741
|
-
|
|
39976
|
+
if (copyStartPacket) for await (const packet of sink.packets(
|
|
39977
|
+
copyStartPacket,
|
|
39978
|
+
void 0,
|
|
39979
|
+
{ verifyKeyPackets: true }
|
|
39980
|
+
)) {
|
|
39981
|
+
if (this._state === "canceled") {
|
|
39742
39982
|
break;
|
|
39743
39983
|
}
|
|
39744
39984
|
if (packet.timestamp >= this._endTimestamp) {
|
|
39745
|
-
|
|
39985
|
+
if (this._copyBoundaryPolicy === "shrink") {
|
|
39986
|
+
break;
|
|
39987
|
+
} else {
|
|
39988
|
+
let current = packet;
|
|
39989
|
+
let found = false;
|
|
39990
|
+
const lookahead = 6;
|
|
39991
|
+
for (let i = 0; i < lookahead; i++) {
|
|
39992
|
+
const next = await sink.getNextPacket(current, { metadataOnly: true });
|
|
39993
|
+
if (!next) {
|
|
39994
|
+
break;
|
|
39995
|
+
}
|
|
39996
|
+
if (next.timestamp < this._endTimestamp) {
|
|
39997
|
+
found = true;
|
|
39998
|
+
break;
|
|
39999
|
+
}
|
|
40000
|
+
current = next;
|
|
40001
|
+
}
|
|
40002
|
+
if (!found) {
|
|
40003
|
+
break;
|
|
40004
|
+
}
|
|
40005
|
+
}
|
|
39746
40006
|
}
|
|
40007
|
+
let packetStartTimestamp = packet.timestamp;
|
|
40008
|
+
let packetEndTimestamp = packet.timestamp + packet.duration;
|
|
40009
|
+
if (this._copyBoundaryPolicy === "shrink") {
|
|
40010
|
+
packetStartTimestamp = Math.max(packetStartTimestamp, this._startTimestamp);
|
|
40011
|
+
packetEndTimestamp = Math.min(packetEndTimestamp, this._endTimestamp);
|
|
40012
|
+
packetEndTimestamp = Math.max(packetEndTimestamp, packetStartTimestamp);
|
|
40013
|
+
}
|
|
40014
|
+
packetStartTimestamp += this._timestampOffset;
|
|
40015
|
+
packetEndTimestamp += this._timestampOffset;
|
|
39747
40016
|
const modifiedPacket = packet.clone({
|
|
39748
|
-
timestamp:
|
|
40017
|
+
timestamp: packetStartTimestamp,
|
|
40018
|
+
duration: packetEndTimestamp - packetStartTimestamp,
|
|
39749
40019
|
sideData: alpha === "discard" ? {} : packet.sideData
|
|
39750
40020
|
});
|
|
39751
|
-
assert(modifiedPacket.timestamp >= 0);
|
|
39752
40021
|
this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
|
|
39753
40022
|
await source.add(modifiedPacket, meta);
|
|
39754
40023
|
if (this._synchronizer.shouldWait(outputTrackId, modifiedPacket.timestamp)) {
|
|
@@ -39809,7 +40078,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39809
40078
|
tempOutput.addVideoTrack(tempSource);
|
|
39810
40079
|
await tempOutput.start();
|
|
39811
40080
|
const sink = new VideoSampleSink(track);
|
|
39812
|
-
const firstSample = __using(_stack, await sink.getSample(
|
|
40081
|
+
const firstSample = __using(_stack, await sink.getSample(await track.getFirstTimestamp()));
|
|
39813
40082
|
if (firstSample) {
|
|
39814
40083
|
try {
|
|
39815
40084
|
await tempSource.add(firstSample);
|
|
@@ -39860,11 +40129,16 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39860
40129
|
var _stack2 = [];
|
|
39861
40130
|
try {
|
|
39862
40131
|
const sample = __using(_stack2, _sample);
|
|
39863
|
-
if (this.
|
|
40132
|
+
if (this._state === "canceled") {
|
|
39864
40133
|
break;
|
|
39865
40134
|
}
|
|
39866
|
-
const
|
|
39867
|
-
sample.
|
|
40135
|
+
const clampedStartTimestamp = Math.max(this._startTimestamp, sample.timestamp);
|
|
40136
|
+
const clampedEndTimestamp = Math.min(this._endTimestamp, sample.timestamp + sample.duration);
|
|
40137
|
+
if (clampedStartTimestamp >= clampedEndTimestamp) {
|
|
40138
|
+
continue;
|
|
40139
|
+
}
|
|
40140
|
+
sample.setTimestamp(clampedStartTimestamp + this._timestampOffset);
|
|
40141
|
+
sample.setDuration(clampedEndTimestamp - clampedStartTimestamp);
|
|
39868
40142
|
this._reportProgress(outputTrackId, sample.timestamp + sample.duration);
|
|
39869
40143
|
await source.add(sample);
|
|
39870
40144
|
sample.close();
|
|
@@ -39889,12 +40163,14 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39889
40163
|
ownGroup = new OutputTrackGroup();
|
|
39890
40164
|
}
|
|
39891
40165
|
const videoTrackLanguageCode = await track.getLanguageCode();
|
|
40166
|
+
const trackName = await track.getName();
|
|
40167
|
+
const trackDisposition = await track.getDisposition();
|
|
39892
40168
|
this.output.addVideoTrack(videoSource, {
|
|
39893
40169
|
frameRate: trackOptions.frameRate,
|
|
39894
40170
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
39895
40171
|
languageCode: isIso639Dash2LanguageCode(videoTrackLanguageCode) ? videoTrackLanguageCode : void 0,
|
|
39896
|
-
name:
|
|
39897
|
-
disposition:
|
|
40172
|
+
name: trackName ?? void 0,
|
|
40173
|
+
disposition: trackDisposition,
|
|
39898
40174
|
rotation: outputTrackRotation,
|
|
39899
40175
|
group: ownGroup ?? trackOptions.group
|
|
39900
40176
|
});
|
|
@@ -39916,30 +40192,93 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39916
40192
|
let audioSource;
|
|
39917
40193
|
const originalNumberOfChannels = await track.getNumberOfChannels();
|
|
39918
40194
|
const originalSampleRate = await track.getSampleRate();
|
|
39919
|
-
const firstTimestamp = await track.getFirstTimestamp();
|
|
39920
40195
|
let numberOfChannels = trackOptions.numberOfChannels ?? originalNumberOfChannels;
|
|
39921
40196
|
let sampleRate = trackOptions.sampleRate ?? originalSampleRate;
|
|
39922
|
-
const needsTrimming = firstTimestamp < this._startTimestamp;
|
|
39923
|
-
let needsPadding = firstTimestamp > this._startTimestamp && !this.output.format.supportsTimestampedMediaData;
|
|
39924
40197
|
let audioCodecs = this.output.format.getSupportedAudioCodecs();
|
|
39925
|
-
|
|
40198
|
+
let needsTranscode = !this._copyMode || !!trackOptions.forceTranscode || !!trackOptions.quality || !!trackOptions.bitrate || numberOfChannels !== originalNumberOfChannels || sampleRate !== originalSampleRate || !audioCodecs.includes(sourceCodec) || !!trackOptions.codec && trackOptions.codec !== sourceCodec || trackOptions.process !== void 0 || trackOptions.sampleFormat !== void 0;
|
|
40199
|
+
let copyStartPacket = null;
|
|
40200
|
+
if (!needsTranscode) {
|
|
40201
|
+
const sink = new EncodedPacketSink(track);
|
|
40202
|
+
let startPacket = await sink.getKeyPacket(this._startTimestamp) ?? await sink.getFirstKeyPacket();
|
|
40203
|
+
if (startPacket && (this._copyBoundaryPolicy === "shrink" && startPacket.timestamp < this._startTimestamp || this._copyBoundaryPolicy === "expand" && startPacket.timestamp + startPacket.duration <= this._startTimestamp)) {
|
|
40204
|
+
startPacket = await sink.getNextKeyPacket(startPacket);
|
|
40205
|
+
}
|
|
40206
|
+
const hasDecoderWarmup = NON_PCM_AUDIO_CODECS.includes(sourceCodec) && sourceCodec !== "flac";
|
|
40207
|
+
if (startPacket && this._copyBoundaryPolicy === "expand" && hasDecoderWarmup) {
|
|
40208
|
+
const previousPacket = await sink.getKeyPacket(
|
|
40209
|
+
startPacket.timestamp - 1 / await track.getTimeResolution()
|
|
40210
|
+
);
|
|
40211
|
+
if (previousPacket) {
|
|
40212
|
+
startPacket = previousPacket;
|
|
40213
|
+
}
|
|
40214
|
+
}
|
|
40215
|
+
copyStartPacket = startPacket;
|
|
40216
|
+
if (startPacket) {
|
|
40217
|
+
if (!this.output.format.supportsTimestampedMediaData) {
|
|
40218
|
+
if (this._timestampOffsetAdjusted) {
|
|
40219
|
+
const isValid = startPacket.timestamp + this._timestampOffset === 0;
|
|
40220
|
+
if (!isValid) {
|
|
40221
|
+
needsTranscode = true;
|
|
40222
|
+
}
|
|
40223
|
+
} else {
|
|
40224
|
+
const correction = clamp(
|
|
40225
|
+
this._startTimestamp - startPacket.timestamp,
|
|
40226
|
+
-this._copyTimestampShiftTolerance,
|
|
40227
|
+
this._copyTimestampShiftTolerance
|
|
40228
|
+
);
|
|
40229
|
+
const shiftedStartTimestamp = startPacket.timestamp + correction;
|
|
40230
|
+
const isValid = shiftedStartTimestamp === this._startTimestamp;
|
|
40231
|
+
if (isValid) {
|
|
40232
|
+
this._timestampOffset = -this._startTimestamp + correction;
|
|
40233
|
+
this._timestampOffsetAdjusted = true;
|
|
40234
|
+
} else {
|
|
40235
|
+
needsTranscode = true;
|
|
40236
|
+
}
|
|
40237
|
+
}
|
|
40238
|
+
} else if (this.output.format.negativeTimestampSupport !== "full" && startPacket.timestamp < this._startTimestamp) {
|
|
40239
|
+
const correction = Math.min(
|
|
40240
|
+
this._startTimestamp - startPacket.timestamp,
|
|
40241
|
+
this._copyTimestampShiftTolerance
|
|
40242
|
+
);
|
|
40243
|
+
const shiftedStartTimestamp = startPacket.timestamp + correction;
|
|
40244
|
+
const isValid = shiftedStartTimestamp >= this._startTimestamp || this.output.format.negativeTimestampSupport === "prefer-non-negative" && this._copyMode === "forced";
|
|
40245
|
+
if (isValid) {
|
|
40246
|
+
this._timestampOffset = Math.max(this._timestampOffset, -this._startTimestamp + correction);
|
|
40247
|
+
} else {
|
|
40248
|
+
needsTranscode = true;
|
|
40249
|
+
}
|
|
40250
|
+
}
|
|
40251
|
+
}
|
|
40252
|
+
}
|
|
40253
|
+
if (needsTranscode && this._copyMode === "forced") {
|
|
40254
|
+
this.discardedTracks.push({
|
|
40255
|
+
track,
|
|
40256
|
+
reason: "cannot_copy",
|
|
40257
|
+
trackOptions
|
|
40258
|
+
});
|
|
40259
|
+
return;
|
|
40260
|
+
}
|
|
40261
|
+
if (!needsTranscode) {
|
|
39926
40262
|
const source = new EncodedAudioPacketSource(sourceCodec);
|
|
39927
40263
|
audioSource = source;
|
|
39928
40264
|
this._registerTrackPump(async (pump) => {
|
|
39929
40265
|
const sink = new EncodedPacketSink(track);
|
|
39930
40266
|
const decoderConfig = await track.getDecoderConfig();
|
|
39931
40267
|
const meta = { decoderConfig: decoderConfig ?? void 0 };
|
|
39932
|
-
for await (const packet of sink.packets()) {
|
|
39933
|
-
if (this.
|
|
40268
|
+
if (copyStartPacket) for await (const packet of sink.packets(copyStartPacket)) {
|
|
40269
|
+
if (this._state === "canceled") {
|
|
39934
40270
|
break;
|
|
39935
40271
|
}
|
|
39936
40272
|
if (packet.timestamp >= this._endTimestamp) {
|
|
39937
40273
|
break;
|
|
39938
40274
|
}
|
|
40275
|
+
if (this._copyBoundaryPolicy === "shrink" && packet.timestamp + packet.duration > this._endTimestamp) {
|
|
40276
|
+
break;
|
|
40277
|
+
}
|
|
39939
40278
|
const modifiedPacket = packet.clone({
|
|
39940
|
-
timestamp: packet.timestamp
|
|
40279
|
+
timestamp: packet.timestamp + this._timestampOffset,
|
|
40280
|
+
duration: packet.duration
|
|
39941
40281
|
});
|
|
39942
|
-
assert(modifiedPacket.timestamp >= 0);
|
|
39943
40282
|
this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
|
|
39944
40283
|
await source.add(modifiedPacket, meta);
|
|
39945
40284
|
if (this._synchronizer.shouldWait(outputTrackId, modifiedPacket.timestamp)) {
|
|
@@ -40015,6 +40354,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40015
40354
|
const source = new AudioSampleSource(encodingConfig);
|
|
40016
40355
|
audioSource = source;
|
|
40017
40356
|
this._registerTrackPump(async (pump) => {
|
|
40357
|
+
let needsPadding = null;
|
|
40018
40358
|
const sink = new AudioSampleSink(track);
|
|
40019
40359
|
for await (var _sample of sink.samples(this._startTimestamp, this._endTimestamp)) {
|
|
40020
40360
|
var _stack3 = [];
|
|
@@ -40022,13 +40362,42 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40022
40362
|
const sample = __using(_stack3, _sample);
|
|
40023
40363
|
var _stack2 = [];
|
|
40024
40364
|
try {
|
|
40025
|
-
if (this.
|
|
40365
|
+
if (this._state === "canceled") {
|
|
40026
40366
|
break;
|
|
40027
40367
|
}
|
|
40368
|
+
let startFrame = 0;
|
|
40369
|
+
let endFrame = sample.numberOfFrames;
|
|
40370
|
+
if (sample.timestamp < this._startTimestamp) {
|
|
40371
|
+
startFrame = Math.round((this._startTimestamp - sample.timestamp) * sample.sampleRate);
|
|
40372
|
+
}
|
|
40373
|
+
if (sample.timestamp + sample.duration > this._endTimestamp) {
|
|
40374
|
+
endFrame = Math.round((this._endTimestamp - sample.timestamp) * sample.sampleRate);
|
|
40375
|
+
}
|
|
40376
|
+
if (startFrame >= endFrame) {
|
|
40377
|
+
sample.close();
|
|
40378
|
+
continue;
|
|
40379
|
+
}
|
|
40380
|
+
let finalSampleLet;
|
|
40381
|
+
if (startFrame > 0 || endFrame < sample.numberOfFrames) {
|
|
40382
|
+
const trimmedSample = sample.trim(startFrame, endFrame);
|
|
40383
|
+
sample.close();
|
|
40384
|
+
finalSampleLet = trimmedSample;
|
|
40385
|
+
if (trimmedSample.numberOfFrames === 0) {
|
|
40386
|
+
trimmedSample.close();
|
|
40387
|
+
continue;
|
|
40388
|
+
}
|
|
40389
|
+
} else {
|
|
40390
|
+
finalSampleLet = sample;
|
|
40391
|
+
}
|
|
40392
|
+
const finalSample = __using(_stack2, finalSampleLet);
|
|
40393
|
+
finalSample.setTimestamp(finalSample.timestamp + this._timestampOffset);
|
|
40394
|
+
if (needsPadding === null) {
|
|
40395
|
+
needsPadding = finalSample.timestamp > 0 && !this.output.format.supportsTimestampedMediaData;
|
|
40396
|
+
}
|
|
40028
40397
|
if (needsPadding) {
|
|
40029
40398
|
var _stack = [];
|
|
40030
40399
|
try {
|
|
40031
|
-
const paddingLength =
|
|
40400
|
+
const paddingLength = finalSample.timestamp;
|
|
40032
40401
|
const paddingLengthSamples = Math.round(paddingLength * originalSampleRate);
|
|
40033
40402
|
const bytesPerSample = getBytesPerSample(sample.format);
|
|
40034
40403
|
const data = new Uint8Array(bytesPerSample * paddingLengthSamples * originalNumberOfChannels);
|
|
@@ -40058,28 +40427,6 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40058
40427
|
__callDispose(_stack, _error, _hasError);
|
|
40059
40428
|
}
|
|
40060
40429
|
}
|
|
40061
|
-
let startFrame = 0;
|
|
40062
|
-
let endFrame = sample.numberOfFrames;
|
|
40063
|
-
if (sample.timestamp < this._startTimestamp) {
|
|
40064
|
-
startFrame = Math.round((this._startTimestamp - sample.timestamp) * sample.sampleRate);
|
|
40065
|
-
}
|
|
40066
|
-
if (sample.timestamp + sample.duration > this._endTimestamp) {
|
|
40067
|
-
endFrame = Math.round((this._endTimestamp - sample.timestamp) * sample.sampleRate);
|
|
40068
|
-
}
|
|
40069
|
-
let finalSampleLet;
|
|
40070
|
-
if (startFrame > 0 || endFrame < sample.numberOfFrames) {
|
|
40071
|
-
const trimmedSample = sample.trim(startFrame, endFrame);
|
|
40072
|
-
sample.close();
|
|
40073
|
-
finalSampleLet = trimmedSample;
|
|
40074
|
-
if (trimmedSample.numberOfFrames === 0) {
|
|
40075
|
-
trimmedSample.close();
|
|
40076
|
-
continue;
|
|
40077
|
-
}
|
|
40078
|
-
} else {
|
|
40079
|
-
finalSampleLet = sample;
|
|
40080
|
-
}
|
|
40081
|
-
const finalSample = __using(_stack2, finalSampleLet);
|
|
40082
|
-
finalSample.setTimestamp(finalSample.timestamp - this._startTimestamp);
|
|
40083
40430
|
await this._registerAudioSample(
|
|
40084
40431
|
pump,
|
|
40085
40432
|
finalSample,
|
|
@@ -40107,11 +40454,13 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40107
40454
|
ownGroup = new OutputTrackGroup();
|
|
40108
40455
|
}
|
|
40109
40456
|
const audioTrackLanguageCode = await track.getLanguageCode();
|
|
40457
|
+
const trackName = await track.getName();
|
|
40458
|
+
const trackDisposition = await track.getDisposition();
|
|
40110
40459
|
this.output.addAudioTrack(audioSource, {
|
|
40111
40460
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
40112
40461
|
languageCode: isIso639Dash2LanguageCode(audioTrackLanguageCode) ? audioTrackLanguageCode : void 0,
|
|
40113
|
-
name:
|
|
40114
|
-
disposition:
|
|
40462
|
+
name: trackName ?? void 0,
|
|
40463
|
+
disposition: trackDisposition,
|
|
40115
40464
|
group: ownGroup ?? trackOptions.group
|
|
40116
40465
|
});
|
|
40117
40466
|
this.utilizedTracks.push(track);
|
|
@@ -40150,7 +40499,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40150
40499
|
}
|
|
40151
40500
|
/** @internal */
|
|
40152
40501
|
async _checkpoint(pump, timestamp) {
|
|
40153
|
-
while (this.
|
|
40502
|
+
while (this._state !== "canceled" && (timestamp >= this._executionUntil || this._pauseRequested)) {
|
|
40154
40503
|
pump.resolvers.resolve();
|
|
40155
40504
|
const { promise, resolve } = promiseWithResolvers();
|
|
40156
40505
|
pump.wake = resolve;
|
|
@@ -40191,14 +40540,14 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40191
40540
|
this.conversion = conversion;
|
|
40192
40541
|
}
|
|
40193
40542
|
declareTrack(trackId) {
|
|
40194
|
-
this.maxTimestamps.set(trackId,
|
|
40543
|
+
this.maxTimestamps.set(trackId, -Infinity);
|
|
40195
40544
|
}
|
|
40196
40545
|
shouldWait(trackId, timestamp) {
|
|
40197
40546
|
const currentValue = this.maxTimestamps.get(trackId);
|
|
40198
40547
|
assert(currentValue !== void 0);
|
|
40199
40548
|
this.maxTimestamps.set(trackId, Math.max(timestamp, currentValue));
|
|
40200
40549
|
const newMin = this.computeMinAndMaybeResolve();
|
|
40201
|
-
if (this.conversion.
|
|
40550
|
+
if (this.conversion._state === "canceled" || this.conversion._pauseRequested || timestamp >= this.conversion._executionUntil) {
|
|
40202
40551
|
return false;
|
|
40203
40552
|
}
|
|
40204
40553
|
return timestamp - newMin > MAX_TIMESTAMP_GAP;
|