mediabunny 1.55.6 → 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 +535 -180
- package/dist/bundles/mediabunny.min.cjs +12 -12
- package/dist/bundles/mediabunny.min.mjs +12 -12
- package/dist/bundles/mediabunny.mjs +535 -180
- package/dist/bundles/mediabunny.node.cjs +535 -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-sink.d.ts.map +1 -1
- package/dist/modules/src/media-sink.js +12 -0
- 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-sink.ts +12 -0
- 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
|
/**
|
|
@@ -23736,11 +23793,15 @@ var Mediabunny = (() => {
|
|
|
23736
23793
|
async next() {
|
|
23737
23794
|
while (true) {
|
|
23738
23795
|
if (track.input._disposed) {
|
|
23796
|
+
terminated = true;
|
|
23797
|
+
ended = true;
|
|
23739
23798
|
closeSamples();
|
|
23740
23799
|
throw new InputDisposedError();
|
|
23741
23800
|
} else if (terminated) {
|
|
23742
23801
|
return { value: void 0, done: true };
|
|
23743
23802
|
} else if (hasOutOfBandError) {
|
|
23803
|
+
terminated = true;
|
|
23804
|
+
ended = true;
|
|
23744
23805
|
closeSamples();
|
|
23745
23806
|
throw outOfBandError;
|
|
23746
23807
|
} else if (sampleQueue.length > 0) {
|
|
@@ -23904,11 +23965,13 @@ var Mediabunny = (() => {
|
|
|
23904
23965
|
async next() {
|
|
23905
23966
|
while (true) {
|
|
23906
23967
|
if (track.input._disposed) {
|
|
23968
|
+
terminated = true;
|
|
23907
23969
|
closeSamples();
|
|
23908
23970
|
throw new InputDisposedError();
|
|
23909
23971
|
} else if (terminated) {
|
|
23910
23972
|
return { value: void 0, done: true };
|
|
23911
23973
|
} else if (hasOutOfBandError) {
|
|
23974
|
+
terminated = true;
|
|
23912
23975
|
closeSamples();
|
|
23913
23976
|
throw outOfBandError;
|
|
23914
23977
|
} else if (sampleQueue.length > 0) {
|
|
@@ -27880,9 +27943,6 @@ var Mediabunny = (() => {
|
|
|
27880
27943
|
onTrackClose(track) {
|
|
27881
27944
|
}
|
|
27882
27945
|
validateTimestamp(track, timestampInSeconds, isKeyPacket) {
|
|
27883
|
-
if (timestampInSeconds < 0) {
|
|
27884
|
-
throw new Error(`Timestamps must be non-negative (got ${timestampInSeconds}s).`);
|
|
27885
|
-
}
|
|
27886
27946
|
let timestampInfo = this.trackTimestampInfo.get(track);
|
|
27887
27947
|
if (!timestampInfo) {
|
|
27888
27948
|
if (!isKeyPacket) {
|
|
@@ -28558,7 +28618,8 @@ var Mediabunny = (() => {
|
|
|
28558
28618
|
ascii("dash")
|
|
28559
28619
|
]);
|
|
28560
28620
|
var sidx = (muxer, referencedSize) => {
|
|
28561
|
-
|
|
28621
|
+
const earliestPresentationTime = Math.max(0, muxer.minWrittenTimestamp);
|
|
28622
|
+
let duration = Math.max(0, muxer.maxWrittenEndTimestamp - earliestPresentationTime);
|
|
28562
28623
|
if (!Number.isFinite(duration)) {
|
|
28563
28624
|
duration = 0;
|
|
28564
28625
|
}
|
|
@@ -28567,7 +28628,7 @@ var Mediabunny = (() => {
|
|
|
28567
28628
|
// Reference ID
|
|
28568
28629
|
u32(GLOBAL_TIMESCALE),
|
|
28569
28630
|
// Timescale
|
|
28570
|
-
u64(intoTimescale(
|
|
28631
|
+
u64(intoTimescale(earliestPresentationTime, GLOBAL_TIMESCALE)),
|
|
28571
28632
|
// Earliest presentation time
|
|
28572
28633
|
u64(0),
|
|
28573
28634
|
// First offset
|
|
@@ -28596,7 +28657,13 @@ var Mediabunny = (() => {
|
|
|
28596
28657
|
var mvhd = (creationTime, trackDatas) => {
|
|
28597
28658
|
const duration = Math.max(
|
|
28598
28659
|
0,
|
|
28599
|
-
...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
|
+
))
|
|
28600
28667
|
);
|
|
28601
28668
|
const nextTrackId = Math.max(0, ...trackDatas.map((x) => x.track.id)) + 1;
|
|
28602
28669
|
const needsU64 = !isU32(creationTime) || !isU32(duration);
|
|
@@ -28646,10 +28713,10 @@ var Mediabunny = (() => {
|
|
|
28646
28713
|
};
|
|
28647
28714
|
var trak = (trackData, creationTime) => {
|
|
28648
28715
|
const trackMetadata = getTrackMetadata(trackData);
|
|
28649
|
-
const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset
|
|
28716
|
+
const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset !== 0;
|
|
28650
28717
|
return box("trak", void 0, [
|
|
28651
28718
|
tkhd(trackData, creationTime),
|
|
28652
|
-
needsEditList ? edts(trackData
|
|
28719
|
+
needsEditList ? edts(trackData) : null,
|
|
28653
28720
|
mdia(trackData, creationTime),
|
|
28654
28721
|
trackMetadata.name !== void 0 ? box("udta", void 0, [
|
|
28655
28722
|
box("name", [
|
|
@@ -28660,7 +28727,10 @@ var Mediabunny = (() => {
|
|
|
28660
28727
|
]);
|
|
28661
28728
|
};
|
|
28662
28729
|
var tkhd = (trackData, creationTime) => {
|
|
28663
|
-
const durationInGlobalTimescale =
|
|
28730
|
+
const durationInGlobalTimescale = Math.max(
|
|
28731
|
+
0,
|
|
28732
|
+
intoTimescale(presentationSpan(trackData), GLOBAL_TIMESCALE) + intoTimescale(trackData.startTimestampOffset ?? 0, GLOBAL_TIMESCALE)
|
|
28733
|
+
);
|
|
28664
28734
|
const needsU64 = !isU32(creationTime) || !isU32(durationInGlobalTimescale);
|
|
28665
28735
|
const u32OrU64 = needsU64 ? u64 : u32;
|
|
28666
28736
|
let matrix;
|
|
@@ -28704,32 +28774,58 @@ var Mediabunny = (() => {
|
|
|
28704
28774
|
// Track height
|
|
28705
28775
|
]);
|
|
28706
28776
|
};
|
|
28707
|
-
var edts = (trackData
|
|
28708
|
-
const
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
|
|
28715
|
-
|
|
28716
|
-
|
|
28717
|
-
|
|
28718
|
-
|
|
28719
|
-
|
|
28720
|
-
|
|
28721
|
-
|
|
28722
|
-
|
|
28723
|
-
|
|
28724
|
-
|
|
28725
|
-
|
|
28726
|
-
|
|
28727
|
-
|
|
28728
|
-
|
|
28729
|
-
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
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
|
+
}
|
|
28733
28829
|
};
|
|
28734
28830
|
var mdia = (trackData, creationTime) => box("mdia", void 0, [
|
|
28735
28831
|
mdhd(trackData, creationTime),
|
|
@@ -31038,7 +31134,7 @@ var Mediabunny = (() => {
|
|
|
31038
31134
|
currentChunk: null,
|
|
31039
31135
|
compactlyCodedChunkTable: [],
|
|
31040
31136
|
closed: false,
|
|
31041
|
-
lastCueEndTimestamp:
|
|
31137
|
+
lastCueEndTimestamp: null,
|
|
31042
31138
|
cueQueue: [],
|
|
31043
31139
|
nextSourceId: 0,
|
|
31044
31140
|
cueToSourceId: /* @__PURE__ */ new WeakMap()
|
|
@@ -31170,6 +31266,7 @@ var Mediabunny = (() => {
|
|
|
31170
31266
|
}
|
|
31171
31267
|
async processWebVTTCues(trackData, until) {
|
|
31172
31268
|
while (trackData.cueQueue.length > 0) {
|
|
31269
|
+
trackData.lastCueEndTimestamp ??= Math.min(0, trackData.cueQueue[0].timestamp);
|
|
31173
31270
|
const timestamps = /* @__PURE__ */ new Set([]);
|
|
31174
31271
|
for (const cue of trackData.cueQueue) {
|
|
31175
31272
|
assert(cue.timestamp <= until);
|
|
@@ -31253,9 +31350,8 @@ var Mediabunny = (() => {
|
|
|
31253
31350
|
return;
|
|
31254
31351
|
}
|
|
31255
31352
|
if (trackData.type === "audio" && trackData.info.requiresPcmTransformation) {
|
|
31256
|
-
|
|
31257
|
-
|
|
31258
|
-
}
|
|
31353
|
+
assert(!this.isFragmented);
|
|
31354
|
+
trackData.startTimestampOffset ??= trackData.timestampProcessingQueue[0].timestamp;
|
|
31259
31355
|
let totalDuration = 0;
|
|
31260
31356
|
for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {
|
|
31261
31357
|
const sample = trackData.timestampProcessingQueue[i];
|
|
@@ -31275,7 +31371,9 @@ var Mediabunny = (() => {
|
|
|
31275
31371
|
return;
|
|
31276
31372
|
}
|
|
31277
31373
|
const sortedTimestamps = trackData.timestampProcessingQueue.map((x) => x.timestamp).sort((a, b) => a - b);
|
|
31278
|
-
if (
|
|
31374
|
+
if (this.isFragmented) {
|
|
31375
|
+
trackData.startTimestampOffset ??= Math.min(sortedTimestamps[0], 0);
|
|
31376
|
+
} else {
|
|
31279
31377
|
trackData.startTimestampOffset ??= sortedTimestamps[0];
|
|
31280
31378
|
}
|
|
31281
31379
|
for (let i = 0; i < trackData.timestampProcessingQueue.length; i++) {
|
|
@@ -31526,11 +31624,16 @@ var Mediabunny = (() => {
|
|
|
31526
31624
|
let fragmentStartTimestamp = Infinity;
|
|
31527
31625
|
for (let i = 0; i < tracksInFragment.length; i++) {
|
|
31528
31626
|
const trackData = tracksInFragment[i];
|
|
31627
|
+
assert(trackData.currentChunk);
|
|
31628
|
+
assert(trackData.startTimestampOffset !== null);
|
|
31529
31629
|
trackData.currentChunk.offset = currentPos;
|
|
31530
31630
|
trackData.currentChunk.moofOffset = moofOffset;
|
|
31531
31631
|
trackData.currentChunk.trafIndex = i;
|
|
31632
|
+
trackData.currentChunk.startTimestamp -= trackData.startTimestampOffset;
|
|
31532
31633
|
for (const sample of trackData.currentChunk.samples) {
|
|
31533
31634
|
currentPos += sample.size;
|
|
31635
|
+
sample.timestamp -= trackData.startTimestampOffset;
|
|
31636
|
+
sample.decodeTimestamp -= trackData.startTimestampOffset;
|
|
31534
31637
|
}
|
|
31535
31638
|
fragmentStartTimestamp = Math.min(fragmentStartTimestamp, trackData.currentChunk.startTimestamp);
|
|
31536
31639
|
}
|
|
@@ -31832,6 +31935,7 @@ var Mediabunny = (() => {
|
|
|
31832
31935
|
this.trackDatasInCurrentCluster = /* @__PURE__ */ new Map();
|
|
31833
31936
|
this.startTimestamp = Infinity;
|
|
31834
31937
|
this.endTimestamp = -Infinity;
|
|
31938
|
+
this.warnedAboutTooNegativeTimestamp = false;
|
|
31835
31939
|
this.format = format;
|
|
31836
31940
|
}
|
|
31837
31941
|
async start() {
|
|
@@ -32629,6 +32733,13 @@ ${cue.notes ?? ""}`;
|
|
|
32629
32733
|
}
|
|
32630
32734
|
const relativeTimestamp = msTimestamp - this.currentClusterStartMsTimestamp;
|
|
32631
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
|
+
}
|
|
32632
32743
|
return;
|
|
32633
32744
|
}
|
|
32634
32745
|
const prelude = new Uint8Array(4);
|
|
@@ -32677,6 +32788,7 @@ ${cue.notes ?? ""}`;
|
|
|
32677
32788
|
}
|
|
32678
32789
|
/** Creates a new Cluster element to contain media chunks. */
|
|
32679
32790
|
createNewCluster(msTimestamp) {
|
|
32791
|
+
msTimestamp = Math.max(0, msTimestamp);
|
|
32680
32792
|
if (this.currentCluster) {
|
|
32681
32793
|
this.finalizeCurrentCluster();
|
|
32682
32794
|
}
|
|
@@ -32721,7 +32833,8 @@ ${cue.notes ?? ""}`;
|
|
|
32721
32833
|
for (const [msTimestamp, trackDatas] of groupedAndSortedByTimestamp) {
|
|
32722
32834
|
assert(this.cues);
|
|
32723
32835
|
this.cues.data.push({ id: 187 /* CuePoint */, data: [
|
|
32724
|
-
{ id: 179 /* CueTime */, data: msTimestamp },
|
|
32836
|
+
{ id: 179 /* CueTime */, data: Math.max(0, msTimestamp) },
|
|
32837
|
+
// CueTime is unsigned
|
|
32725
32838
|
// Create CueTrackPositions for each track that starts at this timestamp
|
|
32726
32839
|
...trackDatas.map((trackData) => {
|
|
32727
32840
|
return { id: 183 /* CueTrackPositions */, data: [
|
|
@@ -33780,24 +33893,26 @@ ${cue.notes ?? ""}`;
|
|
|
33780
33893
|
pesView.setUint8(6, 132);
|
|
33781
33894
|
pesView.setUint8(7, includeDts ? 192 : 128);
|
|
33782
33895
|
pesView.setUint8(8, headerDataLength);
|
|
33783
|
-
const
|
|
33896
|
+
const unwrappedPts = Math.round(queuedPacket.presentationTimestamp * TIMESCALE);
|
|
33897
|
+
const pts = modEuclid(unwrappedPts, TIMESTAMP_MODULUS);
|
|
33784
33898
|
ptsDtsBitstream.pos = 0;
|
|
33785
33899
|
ptsDtsBitstream.writeBits(4, includeDts ? 3 : 2);
|
|
33786
|
-
ptsDtsBitstream.writeBits(3, pts
|
|
33900
|
+
ptsDtsBitstream.writeBits(3, Math.floor(pts / 2 ** 30));
|
|
33787
33901
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33788
|
-
ptsDtsBitstream.writeBits(15, pts
|
|
33902
|
+
ptsDtsBitstream.writeBits(15, Math.floor(pts / 2 ** 15) % 2 ** 15);
|
|
33789
33903
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33790
|
-
ptsDtsBitstream.writeBits(15, pts
|
|
33904
|
+
ptsDtsBitstream.writeBits(15, pts % 2 ** 15);
|
|
33791
33905
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33792
33906
|
if (includeDts) {
|
|
33793
33907
|
assert(queuedPacket.decodeTimestamp !== null);
|
|
33794
|
-
const
|
|
33908
|
+
const unwrappedDts = Math.round(queuedPacket.decodeTimestamp * TIMESCALE);
|
|
33909
|
+
const dts = modEuclid(unwrappedDts, TIMESTAMP_MODULUS);
|
|
33795
33910
|
ptsDtsBitstream.writeBits(4, 1);
|
|
33796
|
-
ptsDtsBitstream.writeBits(3, dts
|
|
33911
|
+
ptsDtsBitstream.writeBits(3, Math.floor(dts / 2 ** 30));
|
|
33797
33912
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33798
|
-
ptsDtsBitstream.writeBits(15, dts
|
|
33913
|
+
ptsDtsBitstream.writeBits(15, Math.floor(dts / 2 ** 15) % 2 ** 15);
|
|
33799
33914
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33800
|
-
ptsDtsBitstream.writeBits(15, dts
|
|
33915
|
+
ptsDtsBitstream.writeBits(15, dts % 2 ** 15);
|
|
33801
33916
|
ptsDtsBitstream.writeBits(1, 1);
|
|
33802
33917
|
}
|
|
33803
33918
|
const totalLength = pesHeaderBuffer.length + queuedPacket.data.length;
|
|
@@ -35384,8 +35499,8 @@ ${cue.notes ?? ""}`;
|
|
|
35384
35499
|
* to respect writer and encoder backpressure.
|
|
35385
35500
|
*/
|
|
35386
35501
|
add(timestamp, duration = 0, encodeOptions) {
|
|
35387
|
-
if (!Number.isFinite(timestamp)
|
|
35388
|
-
throw new TypeError("timestamp must be a
|
|
35502
|
+
if (!Number.isFinite(timestamp)) {
|
|
35503
|
+
throw new TypeError("timestamp must be a finite number.");
|
|
35389
35504
|
}
|
|
35390
35505
|
if (!Number.isFinite(duration) || duration < 0) {
|
|
35391
35506
|
throw new TypeError("duration must be a non-negative number.");
|
|
@@ -36230,19 +36345,24 @@ ${cue.notes ?? ""}`;
|
|
|
36230
36345
|
var AudioBufferSource = class extends AudioSource {
|
|
36231
36346
|
/**
|
|
36232
36347
|
* Creates a new {@link AudioBufferSource} whose `AudioBuffer` instances are encoded according to the specified
|
|
36233
|
-
* {@link AudioEncodingConfig}.
|
|
36348
|
+
* {@link AudioEncodingConfig} and {@link AudioBufferSourceOptions}.
|
|
36234
36349
|
*/
|
|
36235
|
-
constructor(encodingConfig) {
|
|
36350
|
+
constructor(encodingConfig, options = {}) {
|
|
36236
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
|
+
}
|
|
36237
36358
|
super(encodingConfig.codec);
|
|
36238
|
-
/** @internal */
|
|
36239
|
-
this._accumulatedTime = 0;
|
|
36240
36359
|
this._encoder = new AudioEncoderWrapper(this, encodingConfig);
|
|
36360
|
+
this._accumulatedTime = options.startTimestamp ?? 0;
|
|
36241
36361
|
}
|
|
36242
36362
|
/**
|
|
36243
|
-
* Converts an AudioBuffer to audio samples, encodes them and adds them to the output. The first AudioBuffer will
|
|
36244
|
-
* be played at timestamp 0, and
|
|
36245
|
-
*
|
|
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.
|
|
36246
36366
|
*
|
|
36247
36367
|
* @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise
|
|
36248
36368
|
* to respect writer and encoder backpressure.
|
|
@@ -37824,6 +37944,9 @@ ${cue.notes ?? ""}`;
|
|
|
37824
37944
|
get supportsTimestampedMediaData() {
|
|
37825
37945
|
return true;
|
|
37826
37946
|
}
|
|
37947
|
+
get negativeTimestampSupport() {
|
|
37948
|
+
return "full";
|
|
37949
|
+
}
|
|
37827
37950
|
/** @internal */
|
|
37828
37951
|
_createMuxer(output) {
|
|
37829
37952
|
return new IsobmffMuxer2(output, this);
|
|
@@ -37998,6 +38121,9 @@ ${cue.notes ?? ""}`;
|
|
|
37998
38121
|
get supportsTimestampedMediaData() {
|
|
37999
38122
|
return true;
|
|
38000
38123
|
}
|
|
38124
|
+
get negativeTimestampSupport() {
|
|
38125
|
+
return "prefer-non-negative";
|
|
38126
|
+
}
|
|
38001
38127
|
};
|
|
38002
38128
|
var WebMOutputFormat = class extends MkvOutputFormat2 {
|
|
38003
38129
|
/** Creates a new {@link WebMOutputFormat} configured with the specified `options`. */
|
|
@@ -38075,6 +38201,9 @@ ${cue.notes ?? ""}`;
|
|
|
38075
38201
|
get supportsTimestampedMediaData() {
|
|
38076
38202
|
return false;
|
|
38077
38203
|
}
|
|
38204
|
+
get negativeTimestampSupport() {
|
|
38205
|
+
return null;
|
|
38206
|
+
}
|
|
38078
38207
|
};
|
|
38079
38208
|
var WavOutputFormat = class extends OutputFormat {
|
|
38080
38209
|
/** Creates a new {@link WavOutputFormat} configured with the specified `options`. */
|
|
@@ -38129,6 +38258,9 @@ ${cue.notes ?? ""}`;
|
|
|
38129
38258
|
get supportsTimestampedMediaData() {
|
|
38130
38259
|
return false;
|
|
38131
38260
|
}
|
|
38261
|
+
get negativeTimestampSupport() {
|
|
38262
|
+
return null;
|
|
38263
|
+
}
|
|
38132
38264
|
};
|
|
38133
38265
|
var OggOutputFormat = class extends OutputFormat {
|
|
38134
38266
|
/** Creates a new {@link OggOutputFormat} configured with the specified `options`. */
|
|
@@ -38179,6 +38311,9 @@ ${cue.notes ?? ""}`;
|
|
|
38179
38311
|
get supportsTimestampedMediaData() {
|
|
38180
38312
|
return false;
|
|
38181
38313
|
}
|
|
38314
|
+
get negativeTimestampSupport() {
|
|
38315
|
+
return null;
|
|
38316
|
+
}
|
|
38182
38317
|
};
|
|
38183
38318
|
var AdtsOutputFormat = class extends OutputFormat {
|
|
38184
38319
|
/** Creates a new {@link AdtsOutputFormat} configured with the specified `options`. */
|
|
@@ -38223,6 +38358,9 @@ ${cue.notes ?? ""}`;
|
|
|
38223
38358
|
get supportsTimestampedMediaData() {
|
|
38224
38359
|
return false;
|
|
38225
38360
|
}
|
|
38361
|
+
get negativeTimestampSupport() {
|
|
38362
|
+
return null;
|
|
38363
|
+
}
|
|
38226
38364
|
};
|
|
38227
38365
|
var FlacOutputFormat = class extends OutputFormat {
|
|
38228
38366
|
/** Creates a new {@link FlacOutputFormat} configured with the specified `options`. */
|
|
@@ -38267,6 +38405,9 @@ ${cue.notes ?? ""}`;
|
|
|
38267
38405
|
get supportsTimestampedMediaData() {
|
|
38268
38406
|
return false;
|
|
38269
38407
|
}
|
|
38408
|
+
get negativeTimestampSupport() {
|
|
38409
|
+
return null;
|
|
38410
|
+
}
|
|
38270
38411
|
};
|
|
38271
38412
|
var MpegTsOutputFormat = class extends OutputFormat {
|
|
38272
38413
|
/** Creates a new {@link MpegTsOutputFormat} configured with the specified `options`. */
|
|
@@ -38317,6 +38458,9 @@ ${cue.notes ?? ""}`;
|
|
|
38317
38458
|
get supportsTimestampedMediaData() {
|
|
38318
38459
|
return true;
|
|
38319
38460
|
}
|
|
38461
|
+
get negativeTimestampSupport() {
|
|
38462
|
+
return "prefer-non-negative";
|
|
38463
|
+
}
|
|
38320
38464
|
};
|
|
38321
38465
|
var HlsOutputFormat = class extends OutputFormat {
|
|
38322
38466
|
/** Creates a new {@link HlsOutputFormat} configured with the specified `options`. */
|
|
@@ -38410,6 +38554,19 @@ ${cue.notes ?? ""}`;
|
|
|
38410
38554
|
get supportsTimestampedMediaData() {
|
|
38411
38555
|
return true;
|
|
38412
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
|
+
}
|
|
38413
38570
|
/** @internal */
|
|
38414
38571
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
38415
38572
|
_codecUnsupportedHint(codec) {
|
|
@@ -39148,15 +39305,16 @@ ${cue.notes ?? ""}`;
|
|
|
39148
39305
|
var Conversion = class _Conversion {
|
|
39149
39306
|
/** Creates a new Conversion instance (duh). */
|
|
39150
39307
|
constructor(options) {
|
|
39151
|
-
/**
|
|
39152
|
-
|
|
39153
|
-
|
|
39154
|
-
|
|
39155
|
-
|
|
39156
|
-
|
|
39157
|
-
|
|
39158
|
-
|
|
39159
|
-
|
|
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();
|
|
39160
39318
|
/** @internal */
|
|
39161
39319
|
this._nextOutputTrackId = 0;
|
|
39162
39320
|
/** @internal */
|
|
@@ -39227,6 +39385,22 @@ ${cue.notes ?? ""}`;
|
|
|
39227
39385
|
if (options.composable !== void 0 && typeof options.composable !== "boolean") {
|
|
39228
39386
|
throw new TypeError("options.composable, when provided, must be a boolean.");
|
|
39229
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
|
+
}
|
|
39230
39404
|
const composable = options.composable ?? false;
|
|
39231
39405
|
if (!composable) {
|
|
39232
39406
|
if (options.output.tracks.length > 0 || Object.keys(options.output._metadataTags).length > 0 || options.output.state !== "pending") {
|
|
@@ -39268,8 +39442,8 @@ ${cue.notes ?? ""}`;
|
|
|
39268
39442
|
if (options.trim?.start !== void 0 && !Number.isFinite(options.trim.start)) {
|
|
39269
39443
|
throw new TypeError("options.trim.start, when provided, must be a finite number.");
|
|
39270
39444
|
}
|
|
39271
|
-
if (options.trim?.end !== void 0 && !
|
|
39272
|
-
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.");
|
|
39273
39447
|
}
|
|
39274
39448
|
if (options.trim?.start !== void 0 && options.trim.end !== void 0 && options.trim.start >= options.trim.end) {
|
|
39275
39449
|
throw new TypeError("options.trim.start must be less than options.trim.end.");
|
|
@@ -39284,10 +39458,24 @@ ${cue.notes ?? ""}`;
|
|
|
39284
39458
|
throw new TypeError("options.showWarnings, when provided, must be a boolean.");
|
|
39285
39459
|
}
|
|
39286
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";
|
|
39287
39464
|
this._composable = composable;
|
|
39288
39465
|
this.input = options.input;
|
|
39289
39466
|
this.output = options.output;
|
|
39290
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
|
+
}
|
|
39291
39479
|
/** Initializes a new conversion process without starting the conversion. */
|
|
39292
39480
|
static async init(options) {
|
|
39293
39481
|
const conversion = new _Conversion(options);
|
|
@@ -39394,6 +39582,7 @@ ${cue.notes ?? ""}`;
|
|
|
39394
39582
|
);
|
|
39395
39583
|
}
|
|
39396
39584
|
this._endTimestamp = Math.max(this._options.trim?.end ?? Infinity, this._startTimestamp);
|
|
39585
|
+
this._timestampOffset = -this._startTimestamp;
|
|
39397
39586
|
for (let i = 0; i < filteredTracks.length; i++) {
|
|
39398
39587
|
const track = filteredTracks[i];
|
|
39399
39588
|
const options = filteredTrackOptions[i];
|
|
@@ -39572,13 +39761,13 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39572
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("")
|
|
39573
39762
|
);
|
|
39574
39763
|
}
|
|
39575
|
-
if (this.
|
|
39764
|
+
if (this._state === "executing") {
|
|
39576
39765
|
throw new Error("Cannot call execute() while a previous call to execute() is still running.");
|
|
39577
39766
|
}
|
|
39578
|
-
if (this.
|
|
39767
|
+
if (this._state === "canceled") {
|
|
39579
39768
|
throw new ConversionCanceledError();
|
|
39580
39769
|
}
|
|
39581
|
-
if (this.
|
|
39770
|
+
if (this._state === "done") {
|
|
39582
39771
|
return;
|
|
39583
39772
|
}
|
|
39584
39773
|
if (this._composable && this.output.state === "pending") {
|
|
@@ -39586,11 +39775,11 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39586
39775
|
"A composable conversion requires the output to be started. Call start() on the output before executing the conversion."
|
|
39587
39776
|
);
|
|
39588
39777
|
}
|
|
39589
|
-
this.
|
|
39778
|
+
this._state = "executing";
|
|
39590
39779
|
this._executionUntil = options.until ?? Infinity;
|
|
39591
39780
|
this._pauseRequested = options.pauseSignal?.aborted ?? false;
|
|
39592
39781
|
const onPause = () => {
|
|
39593
|
-
if (this.
|
|
39782
|
+
if (this._state !== "executing") {
|
|
39594
39783
|
return;
|
|
39595
39784
|
}
|
|
39596
39785
|
this._pauseRequested = true;
|
|
@@ -39640,18 +39829,18 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39640
39829
|
try {
|
|
39641
39830
|
await Promise.all(this._trackPumps.map((x) => x.resolvers.promise));
|
|
39642
39831
|
} catch (error) {
|
|
39643
|
-
if (this.
|
|
39832
|
+
if (this._state !== "canceled") {
|
|
39644
39833
|
void this.cancel();
|
|
39645
39834
|
}
|
|
39646
39835
|
throw error;
|
|
39647
39836
|
} finally {
|
|
39648
39837
|
options.pauseSignal?.removeEventListener("abort", onPause);
|
|
39649
39838
|
}
|
|
39650
|
-
if (this.
|
|
39839
|
+
if (this._state === "canceled") {
|
|
39651
39840
|
throw new ConversionCanceledError();
|
|
39652
39841
|
}
|
|
39653
39842
|
const isDone = this._trackPumps.every((x) => x.done);
|
|
39654
|
-
this.
|
|
39843
|
+
this._state = isDone ? "done" : "idle";
|
|
39655
39844
|
if (isDone) {
|
|
39656
39845
|
if (!this._composable) {
|
|
39657
39846
|
await this.output.finalize();
|
|
@@ -39667,14 +39856,14 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39667
39856
|
* Does nothing if the conversion is already complete.
|
|
39668
39857
|
*/
|
|
39669
39858
|
async cancel() {
|
|
39670
|
-
if (this.
|
|
39859
|
+
if (this._state === "done") {
|
|
39671
39860
|
return;
|
|
39672
39861
|
}
|
|
39673
|
-
if (this.
|
|
39862
|
+
if (this._state === "canceled") {
|
|
39674
39863
|
Logging._warn("Conversion already canceled.");
|
|
39675
39864
|
return;
|
|
39676
39865
|
}
|
|
39677
|
-
this.
|
|
39866
|
+
this._state = "canceled";
|
|
39678
39867
|
for (const pump of this._trackPumps) {
|
|
39679
39868
|
pump.wake?.();
|
|
39680
39869
|
}
|
|
@@ -39720,10 +39909,63 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39720
39909
|
width = ceilToMultipleOfTwo(trackOptions.width);
|
|
39721
39910
|
height = ceilToMultipleOfTwo(trackOptions.height);
|
|
39722
39911
|
}
|
|
39723
|
-
const firstTimestamp = await track.getFirstTimestamp();
|
|
39724
39912
|
let videoCodecs = this.output.format.getSupportedVideoCodecs();
|
|
39725
|
-
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;
|
|
39726
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
|
+
}
|
|
39727
39969
|
if (!needsTranscode) {
|
|
39728
39970
|
const source = new EncodedVideoPacketSource(sourceCodec);
|
|
39729
39971
|
videoSource = source;
|
|
@@ -39731,18 +39973,51 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39731
39973
|
const sink = new EncodedPacketSink(track);
|
|
39732
39974
|
const decoderConfig = await track.getDecoderConfig();
|
|
39733
39975
|
const meta = { decoderConfig: decoderConfig ?? void 0 };
|
|
39734
|
-
for await (const packet of sink.packets(
|
|
39735
|
-
|
|
39976
|
+
if (copyStartPacket) for await (const packet of sink.packets(
|
|
39977
|
+
copyStartPacket,
|
|
39978
|
+
void 0,
|
|
39979
|
+
{ verifyKeyPackets: true }
|
|
39980
|
+
)) {
|
|
39981
|
+
if (this._state === "canceled") {
|
|
39736
39982
|
break;
|
|
39737
39983
|
}
|
|
39738
39984
|
if (packet.timestamp >= this._endTimestamp) {
|
|
39739
|
-
|
|
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
|
+
}
|
|
39740
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;
|
|
39741
40016
|
const modifiedPacket = packet.clone({
|
|
39742
|
-
timestamp:
|
|
40017
|
+
timestamp: packetStartTimestamp,
|
|
40018
|
+
duration: packetEndTimestamp - packetStartTimestamp,
|
|
39743
40019
|
sideData: alpha === "discard" ? {} : packet.sideData
|
|
39744
40020
|
});
|
|
39745
|
-
assert(modifiedPacket.timestamp >= 0);
|
|
39746
40021
|
this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
|
|
39747
40022
|
await source.add(modifiedPacket, meta);
|
|
39748
40023
|
if (this._synchronizer.shouldWait(outputTrackId, modifiedPacket.timestamp)) {
|
|
@@ -39803,7 +40078,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39803
40078
|
tempOutput.addVideoTrack(tempSource);
|
|
39804
40079
|
await tempOutput.start();
|
|
39805
40080
|
const sink = new VideoSampleSink(track);
|
|
39806
|
-
const firstSample = __using(_stack, await sink.getSample(
|
|
40081
|
+
const firstSample = __using(_stack, await sink.getSample(await track.getFirstTimestamp()));
|
|
39807
40082
|
if (firstSample) {
|
|
39808
40083
|
try {
|
|
39809
40084
|
await tempSource.add(firstSample);
|
|
@@ -39854,11 +40129,16 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39854
40129
|
var _stack2 = [];
|
|
39855
40130
|
try {
|
|
39856
40131
|
const sample = __using(_stack2, _sample);
|
|
39857
|
-
if (this.
|
|
40132
|
+
if (this._state === "canceled") {
|
|
39858
40133
|
break;
|
|
39859
40134
|
}
|
|
39860
|
-
const
|
|
39861
|
-
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);
|
|
39862
40142
|
this._reportProgress(outputTrackId, sample.timestamp + sample.duration);
|
|
39863
40143
|
await source.add(sample);
|
|
39864
40144
|
sample.close();
|
|
@@ -39883,12 +40163,14 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39883
40163
|
ownGroup = new OutputTrackGroup();
|
|
39884
40164
|
}
|
|
39885
40165
|
const videoTrackLanguageCode = await track.getLanguageCode();
|
|
40166
|
+
const trackName = await track.getName();
|
|
40167
|
+
const trackDisposition = await track.getDisposition();
|
|
39886
40168
|
this.output.addVideoTrack(videoSource, {
|
|
39887
40169
|
frameRate: trackOptions.frameRate,
|
|
39888
40170
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
39889
40171
|
languageCode: isIso639Dash2LanguageCode(videoTrackLanguageCode) ? videoTrackLanguageCode : void 0,
|
|
39890
|
-
name:
|
|
39891
|
-
disposition:
|
|
40172
|
+
name: trackName ?? void 0,
|
|
40173
|
+
disposition: trackDisposition,
|
|
39892
40174
|
rotation: outputTrackRotation,
|
|
39893
40175
|
group: ownGroup ?? trackOptions.group
|
|
39894
40176
|
});
|
|
@@ -39910,30 +40192,93 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39910
40192
|
let audioSource;
|
|
39911
40193
|
const originalNumberOfChannels = await track.getNumberOfChannels();
|
|
39912
40194
|
const originalSampleRate = await track.getSampleRate();
|
|
39913
|
-
const firstTimestamp = await track.getFirstTimestamp();
|
|
39914
40195
|
let numberOfChannels = trackOptions.numberOfChannels ?? originalNumberOfChannels;
|
|
39915
40196
|
let sampleRate = trackOptions.sampleRate ?? originalSampleRate;
|
|
39916
|
-
const needsTrimming = firstTimestamp < this._startTimestamp;
|
|
39917
|
-
let needsPadding = firstTimestamp > this._startTimestamp && !this.output.format.supportsTimestampedMediaData;
|
|
39918
40197
|
let audioCodecs = this.output.format.getSupportedAudioCodecs();
|
|
39919
|
-
|
|
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) {
|
|
39920
40262
|
const source = new EncodedAudioPacketSource(sourceCodec);
|
|
39921
40263
|
audioSource = source;
|
|
39922
40264
|
this._registerTrackPump(async (pump) => {
|
|
39923
40265
|
const sink = new EncodedPacketSink(track);
|
|
39924
40266
|
const decoderConfig = await track.getDecoderConfig();
|
|
39925
40267
|
const meta = { decoderConfig: decoderConfig ?? void 0 };
|
|
39926
|
-
for await (const packet of sink.packets()) {
|
|
39927
|
-
if (this.
|
|
40268
|
+
if (copyStartPacket) for await (const packet of sink.packets(copyStartPacket)) {
|
|
40269
|
+
if (this._state === "canceled") {
|
|
39928
40270
|
break;
|
|
39929
40271
|
}
|
|
39930
40272
|
if (packet.timestamp >= this._endTimestamp) {
|
|
39931
40273
|
break;
|
|
39932
40274
|
}
|
|
40275
|
+
if (this._copyBoundaryPolicy === "shrink" && packet.timestamp + packet.duration > this._endTimestamp) {
|
|
40276
|
+
break;
|
|
40277
|
+
}
|
|
39933
40278
|
const modifiedPacket = packet.clone({
|
|
39934
|
-
timestamp: packet.timestamp
|
|
40279
|
+
timestamp: packet.timestamp + this._timestampOffset,
|
|
40280
|
+
duration: packet.duration
|
|
39935
40281
|
});
|
|
39936
|
-
assert(modifiedPacket.timestamp >= 0);
|
|
39937
40282
|
this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
|
|
39938
40283
|
await source.add(modifiedPacket, meta);
|
|
39939
40284
|
if (this._synchronizer.shouldWait(outputTrackId, modifiedPacket.timestamp)) {
|
|
@@ -40009,6 +40354,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40009
40354
|
const source = new AudioSampleSource(encodingConfig);
|
|
40010
40355
|
audioSource = source;
|
|
40011
40356
|
this._registerTrackPump(async (pump) => {
|
|
40357
|
+
let needsPadding = null;
|
|
40012
40358
|
const sink = new AudioSampleSink(track);
|
|
40013
40359
|
for await (var _sample of sink.samples(this._startTimestamp, this._endTimestamp)) {
|
|
40014
40360
|
var _stack3 = [];
|
|
@@ -40016,13 +40362,42 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40016
40362
|
const sample = __using(_stack3, _sample);
|
|
40017
40363
|
var _stack2 = [];
|
|
40018
40364
|
try {
|
|
40019
|
-
if (this.
|
|
40365
|
+
if (this._state === "canceled") {
|
|
40020
40366
|
break;
|
|
40021
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
|
+
}
|
|
40022
40397
|
if (needsPadding) {
|
|
40023
40398
|
var _stack = [];
|
|
40024
40399
|
try {
|
|
40025
|
-
const paddingLength =
|
|
40400
|
+
const paddingLength = finalSample.timestamp;
|
|
40026
40401
|
const paddingLengthSamples = Math.round(paddingLength * originalSampleRate);
|
|
40027
40402
|
const bytesPerSample = getBytesPerSample(sample.format);
|
|
40028
40403
|
const data = new Uint8Array(bytesPerSample * paddingLengthSamples * originalNumberOfChannels);
|
|
@@ -40052,28 +40427,6 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40052
40427
|
__callDispose(_stack, _error, _hasError);
|
|
40053
40428
|
}
|
|
40054
40429
|
}
|
|
40055
|
-
let startFrame = 0;
|
|
40056
|
-
let endFrame = sample.numberOfFrames;
|
|
40057
|
-
if (sample.timestamp < this._startTimestamp) {
|
|
40058
|
-
startFrame = Math.round((this._startTimestamp - sample.timestamp) * sample.sampleRate);
|
|
40059
|
-
}
|
|
40060
|
-
if (sample.timestamp + sample.duration > this._endTimestamp) {
|
|
40061
|
-
endFrame = Math.round((this._endTimestamp - sample.timestamp) * sample.sampleRate);
|
|
40062
|
-
}
|
|
40063
|
-
let finalSampleLet;
|
|
40064
|
-
if (startFrame > 0 || endFrame < sample.numberOfFrames) {
|
|
40065
|
-
const trimmedSample = sample.trim(startFrame, endFrame);
|
|
40066
|
-
sample.close();
|
|
40067
|
-
finalSampleLet = trimmedSample;
|
|
40068
|
-
if (trimmedSample.numberOfFrames === 0) {
|
|
40069
|
-
trimmedSample.close();
|
|
40070
|
-
continue;
|
|
40071
|
-
}
|
|
40072
|
-
} else {
|
|
40073
|
-
finalSampleLet = sample;
|
|
40074
|
-
}
|
|
40075
|
-
const finalSample = __using(_stack2, finalSampleLet);
|
|
40076
|
-
finalSample.setTimestamp(finalSample.timestamp - this._startTimestamp);
|
|
40077
40430
|
await this._registerAudioSample(
|
|
40078
40431
|
pump,
|
|
40079
40432
|
finalSample,
|
|
@@ -40101,11 +40454,13 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40101
40454
|
ownGroup = new OutputTrackGroup();
|
|
40102
40455
|
}
|
|
40103
40456
|
const audioTrackLanguageCode = await track.getLanguageCode();
|
|
40457
|
+
const trackName = await track.getName();
|
|
40458
|
+
const trackDisposition = await track.getDisposition();
|
|
40104
40459
|
this.output.addAudioTrack(audioSource, {
|
|
40105
40460
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
40106
40461
|
languageCode: isIso639Dash2LanguageCode(audioTrackLanguageCode) ? audioTrackLanguageCode : void 0,
|
|
40107
|
-
name:
|
|
40108
|
-
disposition:
|
|
40462
|
+
name: trackName ?? void 0,
|
|
40463
|
+
disposition: trackDisposition,
|
|
40109
40464
|
group: ownGroup ?? trackOptions.group
|
|
40110
40465
|
});
|
|
40111
40466
|
this.utilizedTracks.push(track);
|
|
@@ -40144,7 +40499,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40144
40499
|
}
|
|
40145
40500
|
/** @internal */
|
|
40146
40501
|
async _checkpoint(pump, timestamp) {
|
|
40147
|
-
while (this.
|
|
40502
|
+
while (this._state !== "canceled" && (timestamp >= this._executionUntil || this._pauseRequested)) {
|
|
40148
40503
|
pump.resolvers.resolve();
|
|
40149
40504
|
const { promise, resolve } = promiseWithResolvers();
|
|
40150
40505
|
pump.wake = resolve;
|
|
@@ -40185,14 +40540,14 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40185
40540
|
this.conversion = conversion;
|
|
40186
40541
|
}
|
|
40187
40542
|
declareTrack(trackId) {
|
|
40188
|
-
this.maxTimestamps.set(trackId,
|
|
40543
|
+
this.maxTimestamps.set(trackId, -Infinity);
|
|
40189
40544
|
}
|
|
40190
40545
|
shouldWait(trackId, timestamp) {
|
|
40191
40546
|
const currentValue = this.maxTimestamps.get(trackId);
|
|
40192
40547
|
assert(currentValue !== void 0);
|
|
40193
40548
|
this.maxTimestamps.set(trackId, Math.max(timestamp, currentValue));
|
|
40194
40549
|
const newMin = this.computeMinAndMaybeResolve();
|
|
40195
|
-
if (this.conversion.
|
|
40550
|
+
if (this.conversion._state === "canceled" || this.conversion._pauseRequested || timestamp >= this.conversion._executionUntil) {
|
|
40196
40551
|
return false;
|
|
40197
40552
|
}
|
|
40198
40553
|
return timestamp - newMin > MAX_TIMESTAMP_GAP;
|