mediabunny 1.45.4 → 1.45.5
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 +132 -33
- package/dist/bundles/mediabunny.min.cjs +11 -11
- package/dist/bundles/mediabunny.min.mjs +11 -11
- package/dist/bundles/mediabunny.mjs +132 -33
- package/dist/bundles/mediabunny.node.cjs +132 -33
- package/dist/mediabunny.d.ts +5 -5
- package/dist/modules/src/input-track.js +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.js +12 -8
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-demuxer.js +6 -3
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts +1 -0
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.js +22 -0
- package/dist/modules/src/media-sink.d.ts.map +1 -1
- package/dist/modules/src/media-sink.js +7 -1
- 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 +1 -1
- package/dist/modules/src/reader.d.ts.map +1 -1
- package/dist/modules/src/reader.js +4 -4
- package/dist/modules/src/source.d.ts +5 -5
- package/dist/modules/src/source.d.ts.map +1 -1
- package/dist/modules/src/source.js +87 -18
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/input-track.ts +1 -1
- package/src/isobmff/isobmff-boxes.ts +12 -8
- package/src/isobmff/isobmff-demuxer.ts +7 -3
- package/src/isobmff/isobmff-muxer.ts +28 -1
- package/src/media-sink.ts +9 -0
- package/src/misc.ts +1 -1
- package/src/reader.ts +5 -4
- package/src/source.ts +112 -20
|
@@ -6353,18 +6353,21 @@ var Mediabunny = (() => {
|
|
|
6353
6353
|
}
|
|
6354
6354
|
assert(track.info?.type === "video");
|
|
6355
6355
|
const colourType = readAscii(slice, 4);
|
|
6356
|
-
if (colourType !== "nclx") {
|
|
6356
|
+
if (colourType !== "nclx" && colourType !== "nclc") {
|
|
6357
6357
|
break;
|
|
6358
6358
|
}
|
|
6359
6359
|
const colourPrimaries = readU16Be(slice);
|
|
6360
6360
|
const transferCharacteristics = readU16Be(slice);
|
|
6361
6361
|
const matrixCoefficients = readU16Be(slice);
|
|
6362
|
-
|
|
6362
|
+
let fullRange = void 0;
|
|
6363
|
+
if (colourType === "nclx") {
|
|
6364
|
+
fullRange = Boolean(readU8(slice) & 128);
|
|
6365
|
+
}
|
|
6363
6366
|
track.info.colorSpace = {
|
|
6364
6367
|
primaries: COLOR_PRIMARIES_MAP_INVERSE[colourPrimaries],
|
|
6365
6368
|
transfer: TRANSFER_CHARACTERISTICS_MAP_INVERSE[transferCharacteristics],
|
|
6366
6369
|
matrix: MATRIX_COEFFICIENTS_MAP_INVERSE[matrixCoefficients],
|
|
6367
|
-
fullRange
|
|
6370
|
+
fullRange
|
|
6368
6371
|
};
|
|
6369
6372
|
}
|
|
6370
6373
|
;
|
|
@@ -15956,8 +15959,8 @@ var Mediabunny = (() => {
|
|
|
15956
15959
|
/**
|
|
15957
15960
|
* Creates a new {@link UrlSource} backed by the resource at the specified URL.
|
|
15958
15961
|
*
|
|
15959
|
-
* When passing a `Request` instance, note that
|
|
15960
|
-
*
|
|
15962
|
+
* When passing a `Request` instance, note that its `signal` will be overridden by Mediabunny; if you want to cancel
|
|
15963
|
+
* ongoing requests, use {@link Input.dispose}.
|
|
15961
15964
|
*/
|
|
15962
15965
|
constructor(url2, options = {}) {
|
|
15963
15966
|
if (typeof url2 !== "string" && !(url2 instanceof URL) && !(typeof Request !== "undefined" && url2 instanceof Request)) {
|
|
@@ -15983,6 +15986,10 @@ var Mediabunny = (() => {
|
|
|
15983
15986
|
}
|
|
15984
15987
|
const urlString = url2 instanceof Request ? url2.url : url2 instanceof URL ? url2.href : url2;
|
|
15985
15988
|
super(urlString, (request) => new _UrlSource(request.path, this._options));
|
|
15989
|
+
/** @internal */
|
|
15990
|
+
this._offset = 0;
|
|
15991
|
+
/** @internal */
|
|
15992
|
+
this._length = null;
|
|
15986
15993
|
/**
|
|
15987
15994
|
* Note that this value being true does NOT mean the file size can't change anymore; it just signals that we have at
|
|
15988
15995
|
* least checked if we know the file size or not.
|
|
@@ -15992,6 +15999,33 @@ var Mediabunny = (() => {
|
|
|
15992
15999
|
this._url = url2;
|
|
15993
16000
|
this._options = options;
|
|
15994
16001
|
this._getRetryDelay = options.getRetryDelay ?? DEFAULT_RETRY_DELAY;
|
|
16002
|
+
this._requestInit = { ...options.requestInit };
|
|
16003
|
+
let rangeHeaderValue = null;
|
|
16004
|
+
if (options.requestInit?.headers) {
|
|
16005
|
+
const headers = { ...normalizeHeaders(options.requestInit.headers) };
|
|
16006
|
+
const rangeKey = Object.keys(headers).find((key) => key.toLowerCase() === "range");
|
|
16007
|
+
if (rangeKey !== void 0) {
|
|
16008
|
+
rangeHeaderValue = headers[rangeKey];
|
|
16009
|
+
delete headers[rangeKey];
|
|
16010
|
+
this._requestInit.headers = headers;
|
|
16011
|
+
}
|
|
16012
|
+
}
|
|
16013
|
+
if (url2 instanceof Request) {
|
|
16014
|
+
const requestRange = url2.headers.get("Range");
|
|
16015
|
+
if (requestRange !== null) {
|
|
16016
|
+
rangeHeaderValue ??= requestRange;
|
|
16017
|
+
const strippedRequest = new Request(url2);
|
|
16018
|
+
strippedRequest.headers.delete("Range");
|
|
16019
|
+
this._url = strippedRequest;
|
|
16020
|
+
}
|
|
16021
|
+
}
|
|
16022
|
+
if (rangeHeaderValue !== null) {
|
|
16023
|
+
const parsed = parseByteRangeHeader(rangeHeaderValue);
|
|
16024
|
+
if (parsed) {
|
|
16025
|
+
this._offset = parsed.offset;
|
|
16026
|
+
this._length = parsed.length;
|
|
16027
|
+
}
|
|
16028
|
+
}
|
|
15995
16029
|
const DEFAULT_PARALLELISM = 2;
|
|
15996
16030
|
this._orchestrator = new ReadOrchestrator({
|
|
15997
16031
|
maxCacheSize: options.maxCacheSize ?? 64 * 2 ** 20,
|
|
@@ -16002,11 +16036,39 @@ var Mediabunny = (() => {
|
|
|
16002
16036
|
}
|
|
16003
16037
|
/** @internal */
|
|
16004
16038
|
_getFileSize() {
|
|
16005
|
-
|
|
16039
|
+
if (!this._fileSizeDetermined) {
|
|
16040
|
+
return this._length !== null ? this._length : void 0;
|
|
16041
|
+
}
|
|
16042
|
+
const baseSize = this._orchestrator.fileSize;
|
|
16043
|
+
if (baseSize === null) {
|
|
16044
|
+
return this._length !== null ? this._length : null;
|
|
16045
|
+
}
|
|
16046
|
+
return clamp(baseSize - this._offset, 0, this._length ?? Infinity);
|
|
16006
16047
|
}
|
|
16007
16048
|
/** @internal */
|
|
16008
16049
|
_read(start, end, minReadPosition, maxReadPosition) {
|
|
16009
|
-
|
|
16050
|
+
if (this._length !== null && end > this._length) {
|
|
16051
|
+
return null;
|
|
16052
|
+
}
|
|
16053
|
+
const offset = this._offset;
|
|
16054
|
+
const result = this._orchestrator.read(
|
|
16055
|
+
offset + start,
|
|
16056
|
+
offset + end,
|
|
16057
|
+
Math.max(offset + minReadPosition, offset),
|
|
16058
|
+
offset + Math.min(maxReadPosition, this._length ?? Infinity)
|
|
16059
|
+
);
|
|
16060
|
+
const processResult = (result2) => {
|
|
16061
|
+
if (!result2) {
|
|
16062
|
+
return null;
|
|
16063
|
+
}
|
|
16064
|
+
result2.offset -= this._offset;
|
|
16065
|
+
return result2;
|
|
16066
|
+
};
|
|
16067
|
+
if (result instanceof Promise) {
|
|
16068
|
+
return result.then(processResult);
|
|
16069
|
+
} else {
|
|
16070
|
+
return processResult(result);
|
|
16071
|
+
}
|
|
16010
16072
|
}
|
|
16011
16073
|
/** @internal */
|
|
16012
16074
|
async _runWorker(worker) {
|
|
@@ -16015,7 +16077,7 @@ var Mediabunny = (() => {
|
|
|
16015
16077
|
const response = await retriedFetch(
|
|
16016
16078
|
this._options.fetchFn ?? fetch,
|
|
16017
16079
|
this._url,
|
|
16018
|
-
mergeRequestInit(this.
|
|
16080
|
+
mergeRequestInit(this._requestInit, {
|
|
16019
16081
|
headers: {
|
|
16020
16082
|
// Always sending a range request is a good way to probe if the server supports them
|
|
16021
16083
|
Range: `bytes=${worker.currentPos}-`
|
|
@@ -16124,6 +16186,22 @@ var Mediabunny = (() => {
|
|
|
16124
16186
|
this._orchestrator.dispose();
|
|
16125
16187
|
}
|
|
16126
16188
|
};
|
|
16189
|
+
var BYTE_RANGE_REGEX = /^bytes=(\d+)-(\d*)$/;
|
|
16190
|
+
var parseByteRangeHeader = (value) => {
|
|
16191
|
+
const match = BYTE_RANGE_REGEX.exec(value.trim());
|
|
16192
|
+
if (!match) {
|
|
16193
|
+
return null;
|
|
16194
|
+
}
|
|
16195
|
+
const offset = Number(match[1]);
|
|
16196
|
+
const end = match[2] === "" ? null : Number(match[2]);
|
|
16197
|
+
if (end !== null && end < offset) {
|
|
16198
|
+
return null;
|
|
16199
|
+
}
|
|
16200
|
+
return {
|
|
16201
|
+
offset,
|
|
16202
|
+
length: end !== null ? end - offset + 1 : null
|
|
16203
|
+
};
|
|
16204
|
+
};
|
|
16127
16205
|
var FilePathSource = class _FilePathSource extends PathedSource {
|
|
16128
16206
|
/** Creates a new {@link FilePathSource} backed by the file at the specified file path. */
|
|
16129
16207
|
constructor(filePath, options = {}) {
|
|
@@ -17037,20 +17115,17 @@ var Mediabunny = (() => {
|
|
|
17037
17115
|
this._offset + minReadPosition,
|
|
17038
17116
|
this._offset + maxReadPosition
|
|
17039
17117
|
);
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
if (!result2) {
|
|
17043
|
-
return null;
|
|
17044
|
-
}
|
|
17045
|
-
result2.offset -= this._offset;
|
|
17046
|
-
return result2;
|
|
17047
|
-
});
|
|
17048
|
-
} else {
|
|
17049
|
-
if (!result) {
|
|
17118
|
+
const processResult = (result2) => {
|
|
17119
|
+
if (!result2) {
|
|
17050
17120
|
return null;
|
|
17051
17121
|
}
|
|
17052
|
-
|
|
17053
|
-
return
|
|
17122
|
+
result2.offset -= this._offset;
|
|
17123
|
+
return result2;
|
|
17124
|
+
};
|
|
17125
|
+
if (result instanceof Promise) {
|
|
17126
|
+
return result.then(processResult);
|
|
17127
|
+
} else {
|
|
17128
|
+
return processResult(result);
|
|
17054
17129
|
}
|
|
17055
17130
|
}
|
|
17056
17131
|
/** @internal */
|
|
@@ -22130,6 +22205,9 @@ var Mediabunny = (() => {
|
|
|
22130
22205
|
const filteredNalUnits = [];
|
|
22131
22206
|
for (const loc of iterateAvcNalUnits(packet.data, this.decoderConfig)) {
|
|
22132
22207
|
const type = extractNalUnitTypeForAvc(packet.data[loc.offset]);
|
|
22208
|
+
if (type === 9 /* AUD */) {
|
|
22209
|
+
filteredNalUnits.length = 0;
|
|
22210
|
+
}
|
|
22133
22211
|
if (!(type >= 20 && type <= 31)) {
|
|
22134
22212
|
filteredNalUnits.push(packet.data.subarray(loc.offset, loc.offset + loc.length));
|
|
22135
22213
|
}
|
|
@@ -23816,7 +23894,7 @@ var Mediabunny = (() => {
|
|
|
23816
23894
|
/** If this method returns true, the track's samples use a high dynamic range (HDR). */
|
|
23817
23895
|
async hasHighDynamicRange() {
|
|
23818
23896
|
const colorSpace = await this._backing.getColorSpace();
|
|
23819
|
-
return colorSpace.primaries === "bt2020" || colorSpace.primaries === "smpte432" || colorSpace.transfer === "
|
|
23897
|
+
return colorSpace.primaries === "bt2020" || colorSpace.primaries === "smpte432" || colorSpace.transfer === "pq" || colorSpace.transfer === "hlg" || colorSpace.matrix === "bt2020-ncl";
|
|
23820
23898
|
}
|
|
23821
23899
|
/** Checks if this track may contain transparent samples with alpha data. */
|
|
23822
23900
|
async canBeTransparent() {
|
|
@@ -24550,13 +24628,13 @@ var Mediabunny = (() => {
|
|
|
24550
24628
|
if (chunks.length === 1 && this.fileSizeNonStrict !== null) {
|
|
24551
24629
|
return this.requestSlice(0, this.fileSizeNonStrict);
|
|
24552
24630
|
}
|
|
24553
|
-
|
|
24554
|
-
let slice = this.requestSliceRange(startOffset, 0, CHUNK_SIZE);
|
|
24631
|
+
let slice = this.requestSliceRange(currentSize, 0, CHUNK_SIZE);
|
|
24555
24632
|
if (slice instanceof Promise) slice = await slice;
|
|
24556
|
-
if (!slice) {
|
|
24633
|
+
if (!slice || slice.length === 0) {
|
|
24557
24634
|
break;
|
|
24558
24635
|
}
|
|
24559
|
-
|
|
24636
|
+
const chunk = readBytes(slice, slice.length);
|
|
24637
|
+
chunks.push(chunk);
|
|
24560
24638
|
currentSize += slice.length;
|
|
24561
24639
|
}
|
|
24562
24640
|
const joined = new Uint8Array(currentSize);
|
|
@@ -26413,12 +26491,14 @@ var Mediabunny = (() => {
|
|
|
26413
26491
|
};
|
|
26414
26492
|
var mdat = (reserveLargeSize) => ({ type: "mdat", largeSize: reserveLargeSize });
|
|
26415
26493
|
var free = (size) => ({ type: "free", size });
|
|
26416
|
-
var moov = (muxer) =>
|
|
26417
|
-
|
|
26418
|
-
|
|
26419
|
-
|
|
26420
|
-
|
|
26421
|
-
|
|
26494
|
+
var moov = (muxer) => {
|
|
26495
|
+
return box("moov", void 0, [
|
|
26496
|
+
mvhd(muxer.creationTime, muxer.trackDatas),
|
|
26497
|
+
...muxer.trackDatas.map((x) => trak(x, muxer.creationTime)),
|
|
26498
|
+
muxer.isFragmented ? mvex(muxer.trackDatas) : null,
|
|
26499
|
+
udta(muxer)
|
|
26500
|
+
]);
|
|
26501
|
+
};
|
|
26422
26502
|
var mvhd = (creationTime, trackDatas) => {
|
|
26423
26503
|
const duration = Math.max(
|
|
26424
26504
|
0,
|
|
@@ -26729,7 +26809,7 @@ var Mediabunny = (() => {
|
|
|
26729
26809
|
]);
|
|
26730
26810
|
};
|
|
26731
26811
|
var colr = (trackData) => box("colr", [
|
|
26732
|
-
ascii("nclx"),
|
|
26812
|
+
ascii(trackData.muxer.isQuickTime ? "nclc" : "nclx"),
|
|
26733
26813
|
// Colour type
|
|
26734
26814
|
u16(COLOR_PRIMARIES_MAP[trackData.info.decoderConfig.colorSpace.primaries]),
|
|
26735
26815
|
// Colour primaries
|
|
@@ -26737,7 +26817,7 @@ var Mediabunny = (() => {
|
|
|
26737
26817
|
// Transfer characteristics
|
|
26738
26818
|
u16(MATRIX_COEFFICIENTS_MAP[trackData.info.decoderConfig.colorSpace.matrix]),
|
|
26739
26819
|
// Matrix coefficients
|
|
26740
|
-
u8((trackData.info.decoderConfig.colorSpace.fullRange ? 1 : 0) << 7)
|
|
26820
|
+
trackData.muxer.isQuickTime ? [] : u8((trackData.info.decoderConfig.colorSpace.fullRange ? 1 : 0) << 7)
|
|
26741
26821
|
// Full range flag
|
|
26742
26822
|
]);
|
|
26743
26823
|
var avcC = (trackData) => trackData.info.decoderConfig && box("avcC", [
|
|
@@ -29237,6 +29317,7 @@ var Mediabunny = (() => {
|
|
|
29237
29317
|
if (this.format._options.onMoov) {
|
|
29238
29318
|
boxWriter.writer.startTrackingWrites();
|
|
29239
29319
|
}
|
|
29320
|
+
this.ensureOneEnabledTrack();
|
|
29240
29321
|
const movieBox = moov(this);
|
|
29241
29322
|
boxWriter.writeBox(movieBox);
|
|
29242
29323
|
if (this.format._options.onMoov) {
|
|
@@ -29319,6 +29400,7 @@ var Mediabunny = (() => {
|
|
|
29319
29400
|
assert(this.boxWriter);
|
|
29320
29401
|
if (this.allTracksAreKnown()) {
|
|
29321
29402
|
if (!this.mdat) {
|
|
29403
|
+
this.ensureOneEnabledTrack();
|
|
29322
29404
|
const moovBox = moov(this);
|
|
29323
29405
|
const moovSize = this.boxWriter.measureBox(moovBox);
|
|
29324
29406
|
const reservedSize = moovSize + this.computeSampleTableSizeUpperBound() + 4096;
|
|
@@ -29375,10 +29457,27 @@ var Mediabunny = (() => {
|
|
|
29375
29457
|
}
|
|
29376
29458
|
release();
|
|
29377
29459
|
}
|
|
29460
|
+
ensureOneEnabledTrack() {
|
|
29461
|
+
for (const type of ["video", "audio", "subtitle"]) {
|
|
29462
|
+
const tracks = this.trackDatas.filter((t) => t.type === type);
|
|
29463
|
+
if (tracks.length === 0) {
|
|
29464
|
+
continue;
|
|
29465
|
+
}
|
|
29466
|
+
const hasEnabled = tracks.some((t) => t.track.metadata.disposition?.default !== false);
|
|
29467
|
+
if (!hasEnabled) {
|
|
29468
|
+
const firstTrack = tracks[0];
|
|
29469
|
+
firstTrack.track.metadata.disposition = {
|
|
29470
|
+
...firstTrack.track.metadata.disposition,
|
|
29471
|
+
default: true
|
|
29472
|
+
};
|
|
29473
|
+
}
|
|
29474
|
+
}
|
|
29475
|
+
}
|
|
29378
29476
|
/** Finalizes the file, making it ready for use. Must be called after all video and audio chunks have been added. */
|
|
29379
29477
|
async finalize() {
|
|
29380
29478
|
const release = await this.mutex.acquire();
|
|
29381
29479
|
this.allTracksKnown.resolve();
|
|
29480
|
+
this.ensureOneEnabledTrack();
|
|
29382
29481
|
for (const trackData of this.trackDatas) {
|
|
29383
29482
|
trackData.closed = true;
|
|
29384
29483
|
if (trackData.type === "subtitle" && trackData.track.source._codec === "webvtt") {
|