mediabunny 1.45.4 → 1.46.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 +164 -42
- package/dist/bundles/mediabunny.min.cjs +11 -11
- package/dist/bundles/mediabunny.min.mjs +11 -11
- package/dist/bundles/mediabunny.mjs +164 -42
- package/dist/bundles/mediabunny.node.cjs +164 -42
- package/dist/mediabunny.d.ts +20 -5
- package/dist/modules/src/index.d.ts +1 -1
- package/dist/modules/src/index.d.ts.map +1 -1
- 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/media-source.d.ts.map +1 -1
- package/dist/modules/src/media-source.js +9 -7
- package/dist/modules/src/misc.d.ts +10 -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/sample.d.ts +7 -1
- package/dist/modules/src/sample.d.ts.map +1 -1
- package/dist/modules/src/sample.js +27 -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/index.ts +1 -0
- 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/media-source.ts +10 -7
- package/src/misc.ts +10 -1
- package/src/reader.ts +5 -4
- package/src/sample.ts +43 -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 */
|
|
@@ -18993,7 +19068,7 @@ var Mediabunny = (() => {
|
|
|
18993
19068
|
"init.displayWidth and init.displayHeight must be either both provided or both omitted."
|
|
18994
19069
|
);
|
|
18995
19070
|
}
|
|
18996
|
-
this._data = toUint8Array(data).slice();
|
|
19071
|
+
this._data = init._doNotCopy ? toUint8Array(data) : toUint8Array(data).slice();
|
|
18997
19072
|
this._layout = init.layout ?? createDefaultPlaneLayout(init.format, init.codedWidth, init.codedHeight);
|
|
18998
19073
|
this.format = init.format;
|
|
18999
19074
|
this.rotation = init.rotation ?? 0;
|
|
@@ -19103,7 +19178,11 @@ var Mediabunny = (() => {
|
|
|
19103
19178
|
// Firefox has VideoFrame glitches with opaque canvases
|
|
19104
19179
|
willReadFrequently: true
|
|
19105
19180
|
});
|
|
19106
|
-
|
|
19181
|
+
if (!context) {
|
|
19182
|
+
throw new Error(
|
|
19183
|
+
"OffscreenCanvas must have support for the '2d' context in order to create a VideoSample from this data."
|
|
19184
|
+
);
|
|
19185
|
+
}
|
|
19107
19186
|
context.drawImage(data, 0, 0);
|
|
19108
19187
|
this._data = canvas;
|
|
19109
19188
|
this._layout = null;
|
|
@@ -19168,6 +19247,7 @@ var Mediabunny = (() => {
|
|
|
19168
19247
|
"Invalid data type: Must be a BufferSource, CanvasImageSource, or VideoSampleResource."
|
|
19169
19248
|
);
|
|
19170
19249
|
}
|
|
19250
|
+
this.encodeOptions = init?.encodeOptions ?? {};
|
|
19171
19251
|
this.pixelAspectRatio = simplifyRational({
|
|
19172
19252
|
num: this.squarePixelWidth * this.codedHeight,
|
|
19173
19253
|
den: this.squarePixelHeight * this.codedWidth
|
|
@@ -19215,13 +19295,15 @@ var Mediabunny = (() => {
|
|
|
19215
19295
|
return new _VideoSample(this._data, {
|
|
19216
19296
|
timestamp: this.timestamp,
|
|
19217
19297
|
duration: this.duration,
|
|
19218
|
-
rotation: this.rotation
|
|
19298
|
+
rotation: this.rotation,
|
|
19299
|
+
encodeOptions: this.encodeOptions
|
|
19219
19300
|
});
|
|
19220
19301
|
} else if (isVideoFrame(this._data)) {
|
|
19221
19302
|
return new _VideoSample(this._data.clone(), {
|
|
19222
19303
|
timestamp: this.timestamp,
|
|
19223
19304
|
duration: this.duration,
|
|
19224
|
-
rotation: this.rotation
|
|
19305
|
+
rotation: this.rotation,
|
|
19306
|
+
encodeOptions: this.encodeOptions
|
|
19225
19307
|
});
|
|
19226
19308
|
} else if (this._data instanceof Uint8Array) {
|
|
19227
19309
|
assert(this._layout);
|
|
@@ -19236,7 +19318,10 @@ var Mediabunny = (() => {
|
|
|
19236
19318
|
rotation: this.rotation,
|
|
19237
19319
|
visibleRect: this.visibleRect,
|
|
19238
19320
|
displayWidth: this.displayWidth,
|
|
19239
|
-
displayHeight: this.displayHeight
|
|
19321
|
+
displayHeight: this.displayHeight,
|
|
19322
|
+
encodeOptions: this.encodeOptions,
|
|
19323
|
+
// It's already been copied, if we copy it again we make the clone unnecessarily expensive
|
|
19324
|
+
_doNotCopy: true
|
|
19240
19325
|
});
|
|
19241
19326
|
} else {
|
|
19242
19327
|
return new _VideoSample(this._data, {
|
|
@@ -19249,7 +19334,8 @@ var Mediabunny = (() => {
|
|
|
19249
19334
|
rotation: this.rotation,
|
|
19250
19335
|
visibleRect: this.visibleRect,
|
|
19251
19336
|
displayWidth: this.displayWidth,
|
|
19252
|
-
displayHeight: this.displayHeight
|
|
19337
|
+
displayHeight: this.displayHeight,
|
|
19338
|
+
encodeOptions: this.encodeOptions
|
|
19253
19339
|
});
|
|
19254
19340
|
}
|
|
19255
19341
|
}
|
|
@@ -19811,7 +19897,11 @@ var Mediabunny = (() => {
|
|
|
19811
19897
|
const context = canvas.getContext("2d", {
|
|
19812
19898
|
alpha: true
|
|
19813
19899
|
});
|
|
19814
|
-
|
|
19900
|
+
if (!context) {
|
|
19901
|
+
throw new Error(
|
|
19902
|
+
"The '2d' canvas context is required to transform VideoSamples. Register a custom transformer using registerVideoSampleTransformer to work around this limitation."
|
|
19903
|
+
);
|
|
19904
|
+
}
|
|
19815
19905
|
if (description.alpha === "discard") {
|
|
19816
19906
|
context.fillStyle = "black";
|
|
19817
19907
|
context.fillRect(0, 0, description.width, description.height);
|
|
@@ -19851,6 +19941,13 @@ var Mediabunny = (() => {
|
|
|
19851
19941
|
}
|
|
19852
19942
|
this.duration = newDuration;
|
|
19853
19943
|
}
|
|
19944
|
+
/** Sets the encode options used when this sample is passed to an encoder. */
|
|
19945
|
+
setEncodeOptions(newEncodeOptions) {
|
|
19946
|
+
if (!newEncodeOptions || typeof newEncodeOptions !== "object") {
|
|
19947
|
+
throw new TypeError("newEncodeOptions must be an object.");
|
|
19948
|
+
}
|
|
19949
|
+
this.encodeOptions = newEncodeOptions;
|
|
19950
|
+
}
|
|
19854
19951
|
/** Calls `.close()`. */
|
|
19855
19952
|
[Symbol.dispose]() {
|
|
19856
19953
|
this.close();
|
|
@@ -22130,6 +22227,9 @@ var Mediabunny = (() => {
|
|
|
22130
22227
|
const filteredNalUnits = [];
|
|
22131
22228
|
for (const loc of iterateAvcNalUnits(packet.data, this.decoderConfig)) {
|
|
22132
22229
|
const type = extractNalUnitTypeForAvc(packet.data[loc.offset]);
|
|
22230
|
+
if (type === 9 /* AUD */) {
|
|
22231
|
+
filteredNalUnits.length = 0;
|
|
22232
|
+
}
|
|
22133
22233
|
if (!(type >= 20 && type <= 31)) {
|
|
22134
22234
|
filteredNalUnits.push(packet.data.subarray(loc.offset, loc.offset + loc.length));
|
|
22135
22235
|
}
|
|
@@ -23816,7 +23916,7 @@ var Mediabunny = (() => {
|
|
|
23816
23916
|
/** If this method returns true, the track's samples use a high dynamic range (HDR). */
|
|
23817
23917
|
async hasHighDynamicRange() {
|
|
23818
23918
|
const colorSpace = await this._backing.getColorSpace();
|
|
23819
|
-
return colorSpace.primaries === "bt2020" || colorSpace.primaries === "smpte432" || colorSpace.transfer === "
|
|
23919
|
+
return colorSpace.primaries === "bt2020" || colorSpace.primaries === "smpte432" || colorSpace.transfer === "pq" || colorSpace.transfer === "hlg" || colorSpace.matrix === "bt2020-ncl";
|
|
23820
23920
|
}
|
|
23821
23921
|
/** Checks if this track may contain transparent samples with alpha data. */
|
|
23822
23922
|
async canBeTransparent() {
|
|
@@ -24550,13 +24650,13 @@ var Mediabunny = (() => {
|
|
|
24550
24650
|
if (chunks.length === 1 && this.fileSizeNonStrict !== null) {
|
|
24551
24651
|
return this.requestSlice(0, this.fileSizeNonStrict);
|
|
24552
24652
|
}
|
|
24553
|
-
|
|
24554
|
-
let slice = this.requestSliceRange(startOffset, 0, CHUNK_SIZE);
|
|
24653
|
+
let slice = this.requestSliceRange(currentSize, 0, CHUNK_SIZE);
|
|
24555
24654
|
if (slice instanceof Promise) slice = await slice;
|
|
24556
|
-
if (!slice) {
|
|
24655
|
+
if (!slice || slice.length === 0) {
|
|
24557
24656
|
break;
|
|
24558
24657
|
}
|
|
24559
|
-
|
|
24658
|
+
const chunk = readBytes(slice, slice.length);
|
|
24659
|
+
chunks.push(chunk);
|
|
24560
24660
|
currentSize += slice.length;
|
|
24561
24661
|
}
|
|
24562
24662
|
const joined = new Uint8Array(currentSize);
|
|
@@ -26413,12 +26513,14 @@ var Mediabunny = (() => {
|
|
|
26413
26513
|
};
|
|
26414
26514
|
var mdat = (reserveLargeSize) => ({ type: "mdat", largeSize: reserveLargeSize });
|
|
26415
26515
|
var free = (size) => ({ type: "free", size });
|
|
26416
|
-
var moov = (muxer) =>
|
|
26417
|
-
|
|
26418
|
-
|
|
26419
|
-
|
|
26420
|
-
|
|
26421
|
-
|
|
26516
|
+
var moov = (muxer) => {
|
|
26517
|
+
return box("moov", void 0, [
|
|
26518
|
+
mvhd(muxer.creationTime, muxer.trackDatas),
|
|
26519
|
+
...muxer.trackDatas.map((x) => trak(x, muxer.creationTime)),
|
|
26520
|
+
muxer.isFragmented ? mvex(muxer.trackDatas) : null,
|
|
26521
|
+
udta(muxer)
|
|
26522
|
+
]);
|
|
26523
|
+
};
|
|
26422
26524
|
var mvhd = (creationTime, trackDatas) => {
|
|
26423
26525
|
const duration = Math.max(
|
|
26424
26526
|
0,
|
|
@@ -26729,7 +26831,7 @@ var Mediabunny = (() => {
|
|
|
26729
26831
|
]);
|
|
26730
26832
|
};
|
|
26731
26833
|
var colr = (trackData) => box("colr", [
|
|
26732
|
-
ascii("nclx"),
|
|
26834
|
+
ascii(trackData.muxer.isQuickTime ? "nclc" : "nclx"),
|
|
26733
26835
|
// Colour type
|
|
26734
26836
|
u16(COLOR_PRIMARIES_MAP[trackData.info.decoderConfig.colorSpace.primaries]),
|
|
26735
26837
|
// Colour primaries
|
|
@@ -26737,7 +26839,7 @@ var Mediabunny = (() => {
|
|
|
26737
26839
|
// Transfer characteristics
|
|
26738
26840
|
u16(MATRIX_COEFFICIENTS_MAP[trackData.info.decoderConfig.colorSpace.matrix]),
|
|
26739
26841
|
// Matrix coefficients
|
|
26740
|
-
u8((trackData.info.decoderConfig.colorSpace.fullRange ? 1 : 0) << 7)
|
|
26842
|
+
trackData.muxer.isQuickTime ? [] : u8((trackData.info.decoderConfig.colorSpace.fullRange ? 1 : 0) << 7)
|
|
26741
26843
|
// Full range flag
|
|
26742
26844
|
]);
|
|
26743
26845
|
var avcC = (trackData) => trackData.info.decoderConfig && box("avcC", [
|
|
@@ -29237,6 +29339,7 @@ var Mediabunny = (() => {
|
|
|
29237
29339
|
if (this.format._options.onMoov) {
|
|
29238
29340
|
boxWriter.writer.startTrackingWrites();
|
|
29239
29341
|
}
|
|
29342
|
+
this.ensureOneEnabledTrack();
|
|
29240
29343
|
const movieBox = moov(this);
|
|
29241
29344
|
boxWriter.writeBox(movieBox);
|
|
29242
29345
|
if (this.format._options.onMoov) {
|
|
@@ -29319,6 +29422,7 @@ var Mediabunny = (() => {
|
|
|
29319
29422
|
assert(this.boxWriter);
|
|
29320
29423
|
if (this.allTracksAreKnown()) {
|
|
29321
29424
|
if (!this.mdat) {
|
|
29425
|
+
this.ensureOneEnabledTrack();
|
|
29322
29426
|
const moovBox = moov(this);
|
|
29323
29427
|
const moovSize = this.boxWriter.measureBox(moovBox);
|
|
29324
29428
|
const reservedSize = moovSize + this.computeSampleTableSizeUpperBound() + 4096;
|
|
@@ -29375,10 +29479,27 @@ var Mediabunny = (() => {
|
|
|
29375
29479
|
}
|
|
29376
29480
|
release();
|
|
29377
29481
|
}
|
|
29482
|
+
ensureOneEnabledTrack() {
|
|
29483
|
+
for (const type of ["video", "audio", "subtitle"]) {
|
|
29484
|
+
const tracks = this.trackDatas.filter((t) => t.type === type);
|
|
29485
|
+
if (tracks.length === 0) {
|
|
29486
|
+
continue;
|
|
29487
|
+
}
|
|
29488
|
+
const hasEnabled = tracks.some((t) => t.track.metadata.disposition?.default !== false);
|
|
29489
|
+
if (!hasEnabled) {
|
|
29490
|
+
const firstTrack = tracks[0];
|
|
29491
|
+
firstTrack.track.metadata.disposition = {
|
|
29492
|
+
...firstTrack.track.metadata.disposition,
|
|
29493
|
+
default: true
|
|
29494
|
+
};
|
|
29495
|
+
}
|
|
29496
|
+
}
|
|
29497
|
+
}
|
|
29378
29498
|
/** Finalizes the file, making it ready for use. Must be called after all video and audio chunks have been added. */
|
|
29379
29499
|
async finalize() {
|
|
29380
29500
|
const release = await this.mutex.acquire();
|
|
29381
29501
|
this.allTracksKnown.resolve();
|
|
29502
|
+
this.ensureOneEnabledTrack();
|
|
29382
29503
|
for (const trackData of this.trackDatas) {
|
|
29383
29504
|
trackData.closed = true;
|
|
29384
29505
|
if (trackData.type === "subtitle" && trackData.track.source._codec === "webvtt") {
|
|
@@ -32331,9 +32452,10 @@ ${cue.notes ?? ""}`;
|
|
|
32331
32452
|
assert(this.encoderInitialized);
|
|
32332
32453
|
const keyFrameInterval = this.encodingConfig.keyFrameInterval ?? 2;
|
|
32333
32454
|
const multipleOfKeyFrameInterval = Math.floor(sampleToEncode.timestamp / keyFrameInterval);
|
|
32455
|
+
const mergedEncodeOptions = { ...sampleToEncode.encodeOptions, ...encodeOptions };
|
|
32334
32456
|
const finalEncodeOptions = {
|
|
32335
|
-
...
|
|
32336
|
-
keyFrame:
|
|
32457
|
+
...mergedEncodeOptions,
|
|
32458
|
+
keyFrame: mergedEncodeOptions.keyFrame !== void 0 ? mergedEncodeOptions.keyFrame : keyFrameInterval === 0 || multipleOfKeyFrameInterval !== this.lastMultipleOfKeyFrameInterval
|
|
32337
32459
|
};
|
|
32338
32460
|
this.lastMultipleOfKeyFrameInterval = multipleOfKeyFrameInterval;
|
|
32339
32461
|
if (this.customEncoder) {
|