mediabunny 1.39.2 → 1.40.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.
@@ -10470,15 +10470,18 @@ var Mediabunny = (() => {
10470
10470
  const firstPacket = await this.getFirstPacket({});
10471
10471
  this.internalTrack.info.av1CodecInfo = firstPacket && extractAv1CodecInfoFromPacket(firstPacket.data);
10472
10472
  }
10473
- return {
10473
+ const config = {
10474
10474
  codec: extractVideoCodecString(this.internalTrack.info),
10475
10475
  codedWidth: this.internalTrack.info.width,
10476
10476
  codedHeight: this.internalTrack.info.height,
10477
- displayAspectWidth: this.internalTrack.info.squarePixelWidth,
10478
- displayAspectHeight: this.internalTrack.info.squarePixelHeight,
10479
10477
  description: this.internalTrack.info.codecDescription ?? void 0,
10480
10478
  colorSpace: this.internalTrack.info.colorSpace ?? void 0
10481
10479
  };
10480
+ if (this.internalTrack.info.width !== this.internalTrack.info.squarePixelWidth || this.internalTrack.info.height !== this.internalTrack.info.squarePixelHeight) {
10481
+ config.displayAspectWidth = this.internalTrack.info.squarePixelWidth;
10482
+ config.displayAspectHeight = this.internalTrack.info.squarePixelHeight;
10483
+ }
10484
+ return config;
10482
10485
  })();
10483
10486
  }
10484
10487
  };
@@ -10639,15 +10642,12 @@ var Mediabunny = (() => {
10639
10642
  }
10640
10643
  };
10641
10644
  var extractRotationFromMatrix = (matrix) => {
10642
- const [m11, , , m21] = matrix;
10643
- const scaleX = Math.hypot(m11, m21);
10644
- const cosTheta = m11 / scaleX;
10645
- const sinTheta = m21 / scaleX;
10646
- const result = -Math.atan2(sinTheta, cosTheta) * (180 / Math.PI);
10647
- if (!Number.isFinite(result)) {
10645
+ const [a, b] = matrix;
10646
+ const radians = Math.atan2(b, a);
10647
+ if (!Number.isFinite(radians)) {
10648
10648
  return 0;
10649
10649
  }
10650
- return result;
10650
+ return radians * (180 / Math.PI);
10651
10651
  };
10652
10652
  var sampleTableIsEmpty = (sampleTable) => {
10653
10653
  return sampleTable.sampleSizes.length === 0;
@@ -13034,7 +13034,7 @@ var Mediabunny = (() => {
13034
13034
  if (needsPacketForAdditionalInfo) {
13035
13035
  firstPacket = await this.getFirstPacket({});
13036
13036
  }
13037
- return {
13037
+ const config = {
13038
13038
  codec: extractVideoCodecString({
13039
13039
  width: this.internalTrack.info.width,
13040
13040
  height: this.internalTrack.info.height,
@@ -13050,11 +13050,14 @@ var Mediabunny = (() => {
13050
13050
  }),
13051
13051
  codedWidth: this.internalTrack.info.width,
13052
13052
  codedHeight: this.internalTrack.info.height,
13053
- displayAspectWidth: this.internalTrack.info.squarePixelWidth,
13054
- displayAspectHeight: this.internalTrack.info.squarePixelHeight,
13055
13053
  description: this.internalTrack.info.codecDescription ?? void 0,
13056
13054
  colorSpace: this.internalTrack.info.colorSpace ?? void 0
13057
13055
  };
13056
+ if (this.internalTrack.info.width !== this.internalTrack.info.squarePixelWidth || this.internalTrack.info.height !== this.internalTrack.info.squarePixelHeight) {
13057
+ config.displayAspectWidth = this.internalTrack.info.squarePixelWidth;
13058
+ config.displayAspectHeight = this.internalTrack.info.squarePixelHeight;
13059
+ }
13060
+ return config;
13058
13061
  })();
13059
13062
  }
13060
13063
  };
@@ -15249,11 +15252,15 @@ var Mediabunny = (() => {
15249
15252
  }) {
15250
15253
  assert(this.audioInfo);
15251
15254
  const minimumHeaderLength = 6;
15252
- const maximumHeaderSize = 16;
15253
- const maximumSliceLength = this.audioInfo.maximumFrameSize + maximumHeaderSize;
15255
+ const maximumHeaderLength = 16;
15256
+ const minimumFrameLength = 10;
15257
+ const maximumFrameLength = this.audioInfo.maximumBlockSize * this.audioInfo.numberOfChannels * 4 + maximumHeaderLength + 2;
15258
+ const effectiveMinFrameSize = this.audioInfo.minimumFrameSize || minimumFrameLength;
15259
+ const effectiveMaxFrameSize = this.audioInfo.maximumFrameSize || maximumFrameLength;
15260
+ const maximumSliceLength = effectiveMaxFrameSize + maximumHeaderLength;
15254
15261
  const slice = await this.reader.requestSliceRange(
15255
15262
  startPos,
15256
- this.audioInfo.minimumFrameSize,
15263
+ maximumHeaderLength,
15257
15264
  maximumSliceLength
15258
15265
  );
15259
15266
  if (!slice) {
@@ -15266,7 +15273,7 @@ var Mediabunny = (() => {
15266
15273
  if (!frameHeader) {
15267
15274
  return null;
15268
15275
  }
15269
- slice.filePos = startPos + this.audioInfo.minimumFrameSize;
15276
+ slice.filePos = startPos + effectiveMinFrameSize;
15270
15277
  while (true) {
15271
15278
  if (slice.filePos > slice.end - minimumHeaderLength) {
15272
15279
  return {
@@ -15657,11 +15664,12 @@ var Mediabunny = (() => {
15657
15664
  while (8 * (sectionLength + BYTES_BEFORE_SECTION_LENGTH) - bitstream.pos > BITS_IN_CRC_32) {
15658
15665
  const programNumber = bitstream.readBits(16);
15659
15666
  bitstream.skipBits(3);
15667
+ const id = bitstream.readBits(13);
15660
15668
  if (programNumber !== 0) {
15661
15669
  if (programMapPid !== null) {
15662
15670
  throw new Error("Only files with a single program are supported.");
15663
15671
  } else {
15664
- programMapPid = bitstream.readBits(13);
15672
+ programMapPid = id;
15665
15673
  }
15666
15674
  }
15667
15675
  }
@@ -16623,10 +16631,12 @@ var Mediabunny = (() => {
16623
16631
  }),
16624
16632
  codedWidth: this.elementaryStream.info.width,
16625
16633
  codedHeight: this.elementaryStream.info.height,
16626
- displayAspectWidth: this.elementaryStream.info.squarePixelWidth,
16627
- displayAspectHeight: this.elementaryStream.info.squarePixelHeight,
16628
16634
  colorSpace: this.elementaryStream.info.colorSpace
16629
16635
  };
16636
+ if (this.elementaryStream.info.width !== this.elementaryStream.info.squarePixelWidth || this.elementaryStream.info.height !== this.elementaryStream.info.squarePixelHeight) {
16637
+ this.decoderConfig.displayAspectWidth = this.elementaryStream.info.squarePixelWidth;
16638
+ this.decoderConfig.displayAspectHeight = this.elementaryStream.info.squarePixelHeight;
16639
+ }
16630
16640
  }
16631
16641
  getCodec() {
16632
16642
  return this.elementaryStream.info.codec;
@@ -20055,6 +20065,9 @@ var Mediabunny = (() => {
20055
20065
  this.bitsPerSample = null;
20056
20066
  this.writer = output._writer;
20057
20067
  this.format = format;
20068
+ if (this.format._options.appendOnly) {
20069
+ this.writer.ensureMonotonicity = true;
20070
+ }
20058
20071
  }
20059
20072
  async start() {
20060
20073
  this.writer.write(FLAC_HEADER);
@@ -20124,7 +20137,9 @@ var Mediabunny = (() => {
20124
20137
  this.writer.write(header);
20125
20138
  }
20126
20139
  writeVorbisCommentAndPictureBlock() {
20127
- this.writer.seek(STREAMINFO_SIZE + FLAC_HEADER.byteLength);
20140
+ if (!this.format._options.appendOnly) {
20141
+ this.writer.seek(STREAMINFO_SIZE + FLAC_HEADER.byteLength);
20142
+ }
20128
20143
  if (metadataTagsAreEmpty(this.output._metadataTags)) {
20129
20144
  this.metadataWritten = true;
20130
20145
  return;
@@ -20173,6 +20188,28 @@ var Mediabunny = (() => {
20173
20188
  descriptionBitstream.skipBits(103 + 64);
20174
20189
  const bitsPerSample = descriptionBitstream.readBits(5) + 1;
20175
20190
  this.bitsPerSample = bitsPerSample;
20191
+ if (this.format._options.appendOnly) {
20192
+ this.writeHeader({
20193
+ // https://www.rfc-editor.org/rfc/rfc9639.html#name-streaminfo
20194
+ // Per RFC 9639, min/max block sizes can be looser than
20195
+ // actual values, so we use the full valid range (16–65535).
20196
+ // "The actual max block size MAY be smaller than what's
20197
+ // listed, and the actual min (excluding last block) MAY be
20198
+ // larger. This is because the encoder has to write these
20199
+ // fields before receiving any input audio data and cannot
20200
+ // know beforehand what block sizes it will use."
20201
+ minimumBlockSize: 16,
20202
+ maximumBlockSize: 65535,
20203
+ // https://www.rfc-editor.org/rfc/rfc9639.html#name-streaminfo
20204
+ // "A value of 0 signifies that the value is not known."
20205
+ minimumFrameSize: 0,
20206
+ maximumFrameSize: 0,
20207
+ sampleRate: this.sampleRate,
20208
+ channels: this.channels,
20209
+ bitsPerSample: this.bitsPerSample,
20210
+ totalSamples: 0
20211
+ });
20212
+ }
20176
20213
  }
20177
20214
  if (!this.metadataWritten) {
20178
20215
  this.writeVorbisCommentAndPictureBlock();
@@ -20187,8 +20224,10 @@ var Mediabunny = (() => {
20187
20224
  }
20188
20225
  readCodedNumber(slice);
20189
20226
  const blockSize = readBlockSize(slice, blockSizeOrUncommon);
20190
- this.blockSizes.push(blockSize);
20191
- this.frameSizes.push(packet.data.length);
20227
+ if (!this.format._options.appendOnly) {
20228
+ this.blockSizes.push(blockSize);
20229
+ this.frameSizes.push(packet.data.length);
20230
+ }
20192
20231
  const startPos = this.writer.getPos();
20193
20232
  this.writer.write(packet.data);
20194
20233
  if (this.format._options.onFrame) {
@@ -20204,36 +20243,38 @@ var Mediabunny = (() => {
20204
20243
  }
20205
20244
  async finalize() {
20206
20245
  const release = await this.mutex.acquire();
20207
- let minimumBlockSize = Infinity;
20208
- let maximumBlockSize = 0;
20209
- let minimumFrameSize = Infinity;
20210
- let maximumFrameSize = 0;
20211
- let totalSamples = 0;
20212
- for (let i = 0; i < this.blockSizes.length; i++) {
20213
- minimumFrameSize = Math.min(minimumFrameSize, this.frameSizes[i]);
20214
- maximumFrameSize = Math.max(maximumFrameSize, this.frameSizes[i]);
20215
- maximumBlockSize = Math.max(maximumBlockSize, this.blockSizes[i]);
20216
- totalSamples += this.blockSizes[i];
20217
- const isLastFrame = i === this.blockSizes.length - 1;
20218
- if (isLastFrame) {
20219
- continue;
20220
- }
20221
- minimumBlockSize = Math.min(minimumBlockSize, this.blockSizes[i]);
20222
- }
20223
- assert(this.sampleRate !== null);
20224
- assert(this.channels !== null);
20225
- assert(this.bitsPerSample !== null);
20226
- this.writer.seek(4);
20227
- this.writeHeader({
20228
- minimumBlockSize,
20229
- maximumBlockSize,
20230
- minimumFrameSize,
20231
- maximumFrameSize,
20232
- sampleRate: this.sampleRate,
20233
- channels: this.channels,
20234
- bitsPerSample: this.bitsPerSample,
20235
- totalSamples
20236
- });
20246
+ if (!this.format._options.appendOnly) {
20247
+ let minimumBlockSize = Infinity;
20248
+ let maximumBlockSize = 0;
20249
+ let minimumFrameSize = Infinity;
20250
+ let maximumFrameSize = 0;
20251
+ let totalSamples = 0;
20252
+ for (let i = 0; i < this.blockSizes.length; i++) {
20253
+ minimumFrameSize = Math.min(minimumFrameSize, this.frameSizes[i]);
20254
+ maximumFrameSize = Math.max(maximumFrameSize, this.frameSizes[i]);
20255
+ maximumBlockSize = Math.max(maximumBlockSize, this.blockSizes[i]);
20256
+ totalSamples += this.blockSizes[i];
20257
+ const isLastFrame = i === this.blockSizes.length - 1;
20258
+ if (isLastFrame) {
20259
+ continue;
20260
+ }
20261
+ minimumBlockSize = Math.min(minimumBlockSize, this.blockSizes[i]);
20262
+ }
20263
+ assert(this.sampleRate !== null);
20264
+ assert(this.channels !== null);
20265
+ assert(this.bitsPerSample !== null);
20266
+ this.writer.seek(4);
20267
+ this.writeHeader({
20268
+ minimumBlockSize,
20269
+ maximumBlockSize,
20270
+ minimumFrameSize,
20271
+ maximumFrameSize,
20272
+ sampleRate: this.sampleRate,
20273
+ channels: this.channels,
20274
+ bitsPerSample: this.bitsPerSample,
20275
+ totalSamples
20276
+ });
20277
+ }
20237
20278
  release();
20238
20279
  }
20239
20280
  };
@@ -26092,6 +26133,9 @@ ${cue.notes ?? ""}`;
26092
26133
  if (!options || typeof options !== "object") {
26093
26134
  throw new TypeError("options must be an object.");
26094
26135
  }
26136
+ if (options.appendOnly !== void 0 && typeof options.appendOnly !== "boolean") {
26137
+ throw new TypeError("options.appendOnly, when provided, must be a boolean.");
26138
+ }
26095
26139
  super();
26096
26140
  this._options = options;
26097
26141
  }
@@ -29193,6 +29237,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
29193
29237
  }
29194
29238
  }
29195
29239
  if (needsRerender) {
29240
+ outputTrackRotation = 0;
29196
29241
  this._trackPromises.push((async () => {
29197
29242
  await this._started;
29198
29243
  const sink = new CanvasSink(track, {
@@ -29207,7 +29252,6 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
29207
29252
  });
29208
29253
  const iterator = sink.canvases(this._startTimestamp, this._endTimestamp);
29209
29254
  const frameRate = trackOptions.frameRate;
29210
- outputTrackRotation = 0;
29211
29255
  let lastCanvas = null;
29212
29256
  let lastCanvasTimestamp = null;
29213
29257
  let lastCanvasEndTimestamp = null;