mediabunny 1.59.1 → 1.60.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.
@@ -5403,7 +5403,7 @@ var Mediabunny = (() => {
5403
5403
  return "mp3";
5404
5404
  } else if (codecString.startsWith("mp4a.40.") || codecString === "mp4a.67") {
5405
5405
  return "aac";
5406
- } else if (codecString === "opus") {
5406
+ } else if (codecString === "opus" || codecString === "Opus") {
5407
5407
  return "opus";
5408
5408
  } else if (codecString === "vorbis") {
5409
5409
  return "vorbis";
@@ -11728,21 +11728,11 @@ var Mediabunny = (() => {
11728
11728
  }
11729
11729
  }
11730
11730
  }
11731
- async getDurationFromMetadata(segment) {
11731
+ getDurationFromMetadata(segment) {
11732
11732
  if (segment.duration <= 0) {
11733
11733
  return null;
11734
11734
  }
11735
- let minTimestamp = null;
11736
- for (const track of segment.tracks) {
11737
- assert(track.trackBacking);
11738
- const firstPacket = await track.trackBacking.getFirstPacket({ metadataOnly: true });
11739
- if (firstPacket) {
11740
- minTimestamp = Math.min(minTimestamp ?? Infinity, firstPacket.timestamp);
11741
- }
11742
- }
11743
- let endTimestamp = segment.duration / segment.timestampFactor;
11744
- endTimestamp += minTimestamp ?? 0;
11745
- return endTimestamp;
11735
+ return segment.duration / segment.timestampFactor;
11746
11736
  }
11747
11737
  };
11748
11738
  var MatroskaTrackBacking = class {
@@ -32587,7 +32577,7 @@ var Mediabunny = (() => {
32587
32577
  { id: 17138 /* EBMLMaxIDLength */, data: 4 },
32588
32578
  { id: 17139 /* EBMLMaxSizeLength */, data: 8 },
32589
32579
  { id: 17026 /* DocType */, data: this.format instanceof WebMOutputFormat ? "webm" : "matroska" },
32590
- { id: 17031 /* DocTypeVersion */, data: 2 },
32580
+ { id: 17031 /* DocTypeVersion */, data: 4 },
32591
32581
  { id: 17029 /* DocTypeReadVersion */, data: 2 }
32592
32582
  ] };
32593
32583
  this.ebmlWriter.writeEBML(ebmlHeader);
@@ -32610,14 +32600,6 @@ var Mediabunny = (() => {
32610
32600
  const kaxAttachments = new Uint8Array([25, 65, 164, 105]);
32611
32601
  const kaxTags = new Uint8Array([18, 84, 195, 103]);
32612
32602
  const seekHead = { id: 290298740 /* SeekHead */, data: [
32613
- { id: 19899 /* Seek */, data: [
32614
- { id: 21419 /* SeekID */, data: kaxCues },
32615
- {
32616
- id: 21420 /* SeekPosition */,
32617
- size: 5,
32618
- data: writeOffsets ? this.ebmlWriter.offsets.get(this.cues) - this.segmentDataOffset : 0
32619
- }
32620
- ] },
32621
32603
  { id: 19899 /* Seek */, data: [
32622
32604
  { id: 21419 /* SeekID */, data: kaxInfo },
32623
32605
  {
@@ -32649,7 +32631,15 @@ var Mediabunny = (() => {
32649
32631
  size: 5,
32650
32632
  data: writeOffsets ? this.ebmlWriter.offsets.get(this.tagsElement) - this.segmentDataOffset : 0
32651
32633
  }
32652
- ] } : null
32634
+ ] } : null,
32635
+ { id: 19899 /* Seek */, data: [
32636
+ { id: 21419 /* SeekID */, data: kaxCues },
32637
+ {
32638
+ id: 21420 /* SeekPosition */,
32639
+ size: 5,
32640
+ data: writeOffsets ? this.ebmlWriter.offsets.get(this.cues) - this.segmentDataOffset : 0
32641
+ }
32642
+ ] }
32653
32643
  ] };
32654
32644
  this.seekHead = seekHead;
32655
32645
  }
@@ -32701,8 +32691,7 @@ var Mediabunny = (() => {
32701
32691
  { id: 2274716 /* Language */, data: trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE },
32702
32692
  { id: 134 /* CodecID */, data: codecId },
32703
32693
  trackData.codecPrivate ? { id: 25506 /* CodecPrivate */, data: toUint8Array(trackData.codecPrivate) } : null,
32704
- { id: 22186 /* CodecDelay */, data: 0 },
32705
- { id: 22203 /* SeekPreRoll */, data: seekPreRollNs },
32694
+ seekPreRollNs > 0 ? { id: 22203 /* SeekPreRoll */, data: seekPreRollNs } : null,
32706
32695
  trackData.track.metadata.name !== void 0 ? { id: 21358 /* Name */, data: new EBMLUnicodeString(trackData.track.metadata.name) } : null,
32707
32696
  trackData.type === "video" ? this.videoSpecificTrackInfo(trackData) : null,
32708
32697
  trackData.type === "audio" ? this.audioSpecificTrackInfo(trackData) : null,
@@ -33100,7 +33089,7 @@ var Mediabunny = (() => {
33100
33089
  height: meta.decoderConfig.codedHeight,
33101
33090
  aspectRatio,
33102
33091
  decoderConfig: meta.decoderConfig,
33103
- alphaMode: packet ? !!packet.sideData.alpha : null
33092
+ alphaMode: track.metadata.canBeTransparent || (packet ? !!packet.sideData.alpha : null)
33104
33093
  },
33105
33094
  chunkQueue: [],
33106
33095
  lastWrittenMsTimestamp: null,
@@ -33527,7 +33516,7 @@ ${cue.notes ?? ""}`;
33527
33516
  const segmentSize = this.writer.getPos() - this.segmentDataOffset;
33528
33517
  this.writer.seek(this.ebmlWriter.offsets.get(this.segment) + 4);
33529
33518
  this.ebmlWriter.writeVarInt(segmentSize, SEGMENT_SIZE_BYTES);
33530
- const duration = this.startTimestamp === Infinity ? 0 : this.endTimestamp - this.startTimestamp;
33519
+ const duration = this.startTimestamp === Infinity ? 0 : this.endTimestamp;
33531
33520
  this.segmentDuration.data = new EBMLFloat64(duration);
33532
33521
  this.writer.seek(this.ebmlWriter.offsets.get(this.segmentDuration));
33533
33522
  this.ebmlWriter.writeEBML(this.segmentDuration);
@@ -37404,6 +37393,12 @@ ${cue.notes ?? ""}`;
37404
37393
  };
37405
37394
 
37406
37395
  // src/hls/hls-muxer.ts
37396
+ var toHlsCodecString = (codecString) => {
37397
+ if (codecString === "opus") {
37398
+ return "Opus";
37399
+ }
37400
+ return codecString;
37401
+ };
37407
37402
  var HlsMuxer = class extends Muxer {
37408
37403
  constructor(output, format) {
37409
37404
  if (!(output._target instanceof PathedTarget)) {
@@ -38286,8 +38281,31 @@ ${cue.notes ?? ""}`;
38286
38281
  for (const segment of segments) {
38287
38282
  totalBits += 8 * segment.byteSize;
38288
38283
  }
38284
+ let averageBitrate = totalBits / (totalDuration || 1);
38285
+ if (segments.length === 0) {
38286
+ for (const track of playlist.tracks) {
38287
+ const trackData = this.trackDatas.find((x) => x.track === track);
38288
+ let trackPeakBitrate = track.source._nominalBitrate ?? track.metadata.bitrate ?? 0;
38289
+ averageBitrate += track.source._nominalBitrate ?? track.metadata.averageBitrate ?? 0;
38290
+ if (trackPeakBitrate === 0) {
38291
+ const mediumQuality = new Quality("medium");
38292
+ if (track.isVideoTrack()) {
38293
+ const decoderConfig = trackData?.info.decoderConfig;
38294
+ trackPeakBitrate = mediumQuality._toVideoBitrate(
38295
+ track.source._codec,
38296
+ decoderConfig?.codedWidth ?? 1920,
38297
+ // Need to assume a resolution
38298
+ decoderConfig?.codedHeight ?? 1080
38299
+ );
38300
+ } else if (track.isAudioTrack()) {
38301
+ trackPeakBitrate = mediumQuality._toAudioBitrate(track.source._codec) ?? 0;
38302
+ }
38303
+ }
38304
+ peakBitrate += trackPeakBitrate;
38305
+ }
38306
+ }
38289
38307
  playlist.peakBitrate = peakBitrate;
38290
- playlist.averageBitrate = totalBits / (totalDuration || 1);
38308
+ playlist.averageBitrate = averageBitrate;
38291
38309
  }
38292
38310
  async writePlaylist(playlist) {
38293
38311
  assert(this.output._target instanceof PathedTarget);
@@ -38346,7 +38364,7 @@ ${cue.notes ?? ""}`;
38346
38364
  for (const track of decl.playlist.tracks) {
38347
38365
  const trackData = this.trackDatas.find((x) => x.track === track);
38348
38366
  const codecString = trackData?.info.decoderConfig.codec ?? track.source._codec;
38349
- codecs.push(codecString);
38367
+ codecs.push(toHlsCodecString(codecString));
38350
38368
  }
38351
38369
  let peakDeclBitrate = 0;
38352
38370
  let maxRefAverageBitrate = 0;
@@ -38355,7 +38373,7 @@ ${cue.notes ?? ""}`;
38355
38373
  const firstTrack = firstRef.playlist.tracks[0];
38356
38374
  const trackData = this.trackDatas.find((x) => x.track === firstTrack);
38357
38375
  const codecString = trackData?.info.decoderConfig.codec ?? firstTrack.source._codec;
38358
- codecs.push(codecString);
38376
+ codecs.push(toHlsCodecString(codecString));
38359
38377
  for (const ref of decl.references) {
38360
38378
  assert(ref.playlist.peakBitrate !== null);
38361
38379
  peakDeclBitrate = Math.max(peakDeclBitrate, ref.playlist.peakBitrate);
@@ -39584,6 +39602,12 @@ ${cue.notes ?? ""}`;
39584
39602
  `Invalid video frame rate: ${metadata.frameRate}. Must be a positive number.`
39585
39603
  );
39586
39604
  }
39605
+ if (metadata.hasOnlyKeyPackets !== void 0 && typeof metadata.hasOnlyKeyPackets !== "boolean") {
39606
+ throw new TypeError("metadata.hasOnlyKeyPackets, when provided, must be a boolean.");
39607
+ }
39608
+ if (metadata.canBeTransparent !== void 0 && typeof metadata.canBeTransparent !== "boolean") {
39609
+ throw new TypeError("metadata.canBeTransparent, when provided, must be a boolean.");
39610
+ }
39587
39611
  if (metadata.decoderConfig !== void 0) {
39588
39612
  validateVideoChunkMetadata({ decoderConfig: metadata.decoderConfig }, source._codec);
39589
39613
  }
@@ -40895,6 +40919,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
40895
40919
  const trackDisposition = await track.getDisposition();
40896
40920
  const bitrate = needsTranscode ? null : await track.getBitrate();
40897
40921
  const averageBitrate = needsTranscode ? null : await track.getAverageBitrate();
40922
+ const canBeTransparent = alpha === "keep" && await track.canBeTransparent();
40898
40923
  this.output.addVideoTrack(videoSource, {
40899
40924
  frameRate: trackOptions.frameRate,
40900
40925
  // TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
@@ -40904,6 +40929,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
40904
40929
  rotation: outputTrackRotation,
40905
40930
  flip: outputTrackFlip,
40906
40931
  transformationMatrix: outputTrackMatrix ?? void 0,
40932
+ canBeTransparent,
40907
40933
  group: ownGroup ?? trackOptions.group,
40908
40934
  bitrate: bitrate ?? void 0,
40909
40935
  averageBitrate: averageBitrate ?? void 0