mediabunny 1.48.0 → 1.49.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.
Files changed (77) hide show
  1. package/dist/bundles/mediabunny.cjs +213 -86
  2. package/dist/bundles/mediabunny.min.cjs +20 -20
  3. package/dist/bundles/mediabunny.min.mjs +20 -20
  4. package/dist/bundles/mediabunny.mjs +213 -86
  5. package/dist/bundles/mediabunny.node.cjs +213 -86
  6. package/dist/mediabunny.d.ts +56 -3
  7. package/dist/modules/src/codec-data.d.ts.map +1 -1
  8. package/dist/modules/src/codec-data.js +7 -6
  9. package/dist/modules/src/codec.d.ts +1 -1
  10. package/dist/modules/src/conversion.d.ts.map +1 -1
  11. package/dist/modules/src/conversion.js +4 -3
  12. package/dist/modules/src/custom-coder.d.ts.map +1 -1
  13. package/dist/modules/src/custom-coder.js +5 -4
  14. package/dist/modules/src/flac/flac-demuxer.d.ts.map +1 -1
  15. package/dist/modules/src/flac/flac-demuxer.js +23 -1
  16. package/dist/modules/src/hls/hls-muxer.d.ts.map +1 -1
  17. package/dist/modules/src/hls/hls-muxer.js +4 -3
  18. package/dist/modules/src/id3.d.ts +0 -1
  19. package/dist/modules/src/id3.d.ts.map +1 -1
  20. package/dist/modules/src/id3.js +12 -12
  21. package/dist/modules/src/index.d.ts +1 -0
  22. package/dist/modules/src/index.d.ts.map +1 -1
  23. package/dist/modules/src/index.js +3 -1
  24. package/dist/modules/src/input-format.d.ts.map +1 -1
  25. package/dist/modules/src/input-format.js +15 -1
  26. package/dist/modules/src/input-track.d.ts.map +1 -1
  27. package/dist/modules/src/input-track.js +3 -2
  28. package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
  29. package/dist/modules/src/isobmff/isobmff-demuxer.js +18 -17
  30. package/dist/modules/src/logging.d.ts +57 -0
  31. package/dist/modules/src/logging.d.ts.map +1 -0
  32. package/dist/modules/src/logging.js +84 -0
  33. package/dist/modules/src/matroska/ebml.d.ts +4 -4
  34. package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
  35. package/dist/modules/src/matroska/matroska-demuxer.js +2 -1
  36. package/dist/modules/src/media-sink.d.ts.map +1 -1
  37. package/dist/modules/src/media-sink.js +2 -1
  38. package/dist/modules/src/media-source.d.ts.map +1 -1
  39. package/dist/modules/src/media-source.js +5 -4
  40. package/dist/modules/src/metadata.d.ts +4 -2
  41. package/dist/modules/src/metadata.d.ts.map +1 -1
  42. package/dist/modules/src/misc.d.ts +1 -1
  43. package/dist/modules/src/misc.d.ts.map +1 -1
  44. package/dist/modules/src/misc.js +5 -2
  45. package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.d.ts.map +1 -1
  46. package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.js +90 -30
  47. package/dist/modules/src/output.d.ts.map +1 -1
  48. package/dist/modules/src/output.js +5 -4
  49. package/dist/modules/src/sample.d.ts.map +1 -1
  50. package/dist/modules/src/sample.js +3 -2
  51. package/dist/modules/src/source.d.ts.map +1 -1
  52. package/dist/modules/src/source.js +4 -4
  53. package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
  54. package/dist/modules/src/wave/wave-muxer.d.ts.map +1 -1
  55. package/dist/modules/src/wave/wave-muxer.js +2 -1
  56. package/package.json +1 -1
  57. package/src/codec-data.ts +7 -6
  58. package/src/conversion.ts +4 -3
  59. package/src/custom-coder.ts +5 -4
  60. package/src/flac/flac-demuxer.ts +28 -2
  61. package/src/hls/hls-muxer.ts +4 -3
  62. package/src/id3.ts +14 -14
  63. package/src/index.ts +8 -1
  64. package/src/input-format.ts +17 -1
  65. package/src/input-track.ts +3 -2
  66. package/src/isobmff/isobmff-demuxer.ts +18 -17
  67. package/src/logging.ts +120 -0
  68. package/src/matroska/matroska-demuxer.ts +2 -1
  69. package/src/media-sink.ts +2 -1
  70. package/src/media-source.ts +5 -4
  71. package/src/metadata.ts +4 -2
  72. package/src/misc.ts +5 -2
  73. package/src/mpeg-ts/mpeg-ts-demuxer.ts +100 -31
  74. package/src/output.ts +5 -4
  75. package/src/sample.ts +3 -2
  76. package/src/source.ts +4 -4
  77. package/src/wave/wave-muxer.ts +2 -1
@@ -145,6 +145,8 @@ var Mediabunny = (() => {
145
145
  InputVideoTrack: () => InputVideoTrack,
146
146
  IsobmffInputFormat: () => IsobmffInputFormat,
147
147
  IsobmffOutputFormat: () => IsobmffOutputFormat2,
148
+ LogLevel: () => LogLevel,
149
+ Logging: () => Logging,
148
150
  MATROSKA: () => MATROSKA,
149
151
  MP3: () => MP3,
150
152
  MP4: () => MP4,
@@ -640,7 +642,7 @@ var Mediabunny = (() => {
640
642
  if (retryDelayInSeconds === null) {
641
643
  throw error;
642
644
  }
643
- console.error("Retrying failed fetch. Error:", error);
645
+ Logging._error("Retrying failed fetch. Error:", error);
644
646
  if (!Number.isFinite(retryDelayInSeconds) || retryDelayInSeconds < 0) {
645
647
  throw new TypeError("Retry delay must be a non-negative finite number.");
646
648
  }
@@ -1038,7 +1040,7 @@ var Mediabunny = (() => {
1038
1040
  /** @internal */
1039
1041
  this._listeners = /* @__PURE__ */ new Map();
1040
1042
  }
1041
- /** Registers a listener for the given event. */
1043
+ /** Registers a listener for the given event. Returns a function that, when called, removes the listener again. */
1042
1044
  on(event, listener, options) {
1043
1045
  if (!this._listeners.has(event)) {
1044
1046
  this._listeners.set(event, /* @__PURE__ */ new Set());
@@ -1112,6 +1114,63 @@ var Mediabunny = (() => {
1112
1114
  return value !== null && typeof value === "object" && Object.getPrototypeOf(value) === Object.prototype && Object.values(value).every((x) => typeof x === "string");
1113
1115
  };
1114
1116
 
1117
+ // src/logging.ts
1118
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
1119
+ LogLevel2[LogLevel2["Silent"] = 0] = "Silent";
1120
+ LogLevel2[LogLevel2["Errors"] = 1] = "Errors";
1121
+ LogLevel2[LogLevel2["Warnings"] = 2] = "Warnings";
1122
+ LogLevel2[LogLevel2["Info"] = 3] = "Info";
1123
+ return LogLevel2;
1124
+ })(LogLevel || {});
1125
+ var _Logging = class _Logging {
1126
+ constructor() {
1127
+ }
1128
+ /** The current log level. Defaults to {@link LogLevel.Info}. */
1129
+ static get level() {
1130
+ return _Logging._level;
1131
+ }
1132
+ static set level(value) {
1133
+ if (value !== 0 /* Silent */ && value !== 1 /* Errors */ && value !== 2 /* Warnings */ && value !== 3 /* Info */) {
1134
+ throw new TypeError("Invalid log level. Use one of the values of the LogLevel enum.");
1135
+ }
1136
+ _Logging._level = value;
1137
+ }
1138
+ /** @internal */
1139
+ static get _emitter() {
1140
+ return _Logging._emitterInstance ??= new EventEmitter();
1141
+ }
1142
+ /** Registers a listener for a log event. Returns a function that, when called, removes the listener again. */
1143
+ static on(event, listener, options) {
1144
+ return _Logging._emitter.on(event, listener, options);
1145
+ }
1146
+ /** @internal */
1147
+ static _error(...args) {
1148
+ _Logging._emitter._emit("error", args);
1149
+ if (_Logging._level >= 1 /* Errors */) {
1150
+ console.error(...args);
1151
+ }
1152
+ }
1153
+ /** @internal */
1154
+ static _warn(...args) {
1155
+ _Logging._emitter._emit("warn", args);
1156
+ if (_Logging._level >= 2 /* Warnings */) {
1157
+ console.warn(...args);
1158
+ }
1159
+ }
1160
+ /** @internal */
1161
+ static _info(...args) {
1162
+ _Logging._emitter._emit("info", args);
1163
+ if (_Logging._level >= 3 /* Info */) {
1164
+ console.info(...args);
1165
+ }
1166
+ }
1167
+ };
1168
+ /** @internal */
1169
+ _Logging._level = 3 /* Info */;
1170
+ /** @internal */
1171
+ _Logging._emitterInstance = null;
1172
+ var Logging = _Logging;
1173
+
1115
1174
  // src/metadata.ts
1116
1175
  var RichImageData = class {
1117
1176
  /** Creates a new {@link RichImageData}. */
@@ -2735,7 +2794,7 @@ var Mediabunny = (() => {
2735
2794
  sequenceParameterSetExt: hasExtendedData ? spsExtUnits : null
2736
2795
  };
2737
2796
  } catch (error) {
2738
- console.error("Error building AVC Decoder Configuration Record:", error);
2797
+ Logging._error("Error building AVC Decoder Configuration Record:", error);
2739
2798
  return null;
2740
2799
  }
2741
2800
  };
@@ -2841,7 +2900,7 @@ var Mediabunny = (() => {
2841
2900
  }
2842
2901
  return record;
2843
2902
  } catch (error) {
2844
- console.error("Error deserializing AVC Decoder Configuration Record:", error);
2903
+ Logging._error("Error deserializing AVC Decoder Configuration Record:", error);
2845
2904
  return null;
2846
2905
  }
2847
2906
  };
@@ -3070,7 +3129,7 @@ var Mediabunny = (() => {
3070
3129
  maxDecFrameBuffering
3071
3130
  };
3072
3131
  } catch (error) {
3073
- console.error("Error parsing AVC SPS:", error);
3132
+ Logging._error("Error parsing AVC SPS:", error);
3074
3133
  return null;
3075
3134
  }
3076
3135
  };
@@ -3234,7 +3293,7 @@ var Mediabunny = (() => {
3234
3293
  minSpatialSegmentationIdc
3235
3294
  };
3236
3295
  } catch (error) {
3237
- console.error("Error parsing HEVC SPS:", error);
3296
+ Logging._error("Error parsing HEVC SPS:", error);
3238
3297
  return null;
3239
3298
  }
3240
3299
  };
@@ -3345,7 +3404,7 @@ var Mediabunny = (() => {
3345
3404
  };
3346
3405
  return record;
3347
3406
  } catch (error) {
3348
- console.error("Error building HEVC Decoder Configuration Record:", error);
3407
+ Logging._error("Error building HEVC Decoder Configuration Record:", error);
3349
3408
  return null;
3350
3409
  }
3351
3410
  };
@@ -3693,7 +3752,7 @@ var Mediabunny = (() => {
3693
3752
  arrays
3694
3753
  };
3695
3754
  } catch (error) {
3696
- console.error("Error deserializing HEVC Decoder Configuration Record:", error);
3755
+ Logging._error("Error deserializing HEVC Decoder Configuration Record:", error);
3697
3756
  return null;
3698
3757
  }
3699
3758
  };
@@ -5877,7 +5936,7 @@ var Mediabunny = (() => {
5877
5936
  continue;
5878
5937
  }
5879
5938
  if (relevantEntryFound) {
5880
- console.warn(
5939
+ Logging._warn(
5881
5940
  "Unsupported edit list: multiple edits are not currently supported. Only using first edit."
5882
5941
  );
5883
5942
  break;
@@ -5887,7 +5946,7 @@ var Mediabunny = (() => {
5887
5946
  continue;
5888
5947
  }
5889
5948
  if (mediaRate !== 1) {
5890
- console.warn("Unsupported edit list entry: media rate must be 1.");
5949
+ Logging._warn("Unsupported edit list entry: media rate must be 1.");
5891
5950
  break;
5892
5951
  }
5893
5952
  track.editListPreviousSegmentDurations = previousSegmentDurations;
@@ -6026,9 +6085,9 @@ var Mediabunny = (() => {
6026
6085
  } else if (codecName === "av01") {
6027
6086
  track.info.codec = "av1";
6028
6087
  } else if (codecName === null) {
6029
- console.warn(`Unknown encrypted video codec due to missing frma box.`);
6088
+ Logging._warn(`Unknown encrypted video codec due to missing frma box.`);
6030
6089
  } else {
6031
- console.warn(`Unsupported video codec (sample entry type '${sampleBoxInfo.name}').`);
6090
+ Logging._warn(`Unsupported video codec (sample entry type '${sampleBoxInfo.name}').`);
6032
6091
  }
6033
6092
  } else {
6034
6093
  slice.skip(6 * 1 + 2);
@@ -6085,7 +6144,7 @@ var Mediabunny = (() => {
6085
6144
  } else if (sampleSize === 16) {
6086
6145
  track.info.codec = track.info.pcmLittleEndian ? "pcm-s16" : "pcm-s16be";
6087
6146
  } else {
6088
- console.warn(`Unsupported sample size ${sampleSize} for codec 'twos'.`);
6147
+ Logging._warn(`Unsupported sample size ${sampleSize} for codec 'twos'.`);
6089
6148
  track.info.codec = null;
6090
6149
  }
6091
6150
  } else if (codecName === "sowt") {
@@ -6094,7 +6153,7 @@ var Mediabunny = (() => {
6094
6153
  } else if (sampleSize === 16) {
6095
6154
  track.info.codec = "pcm-s16";
6096
6155
  } else {
6097
- console.warn(`Unsupported sample size ${sampleSize} for codec 'sowt'.`);
6156
+ Logging._warn(`Unsupported sample size ${sampleSize} for codec 'sowt'.`);
6098
6157
  track.info.codec = null;
6099
6158
  }
6100
6159
  } else if (codecName === "raw ") {
@@ -6117,7 +6176,7 @@ var Mediabunny = (() => {
6117
6176
  } else if (pcmSampleSize === 32) {
6118
6177
  track.info.codec = "pcm-s32";
6119
6178
  } else {
6120
- console.warn(`Invalid ipcm sample size ${pcmSampleSize}.`);
6179
+ Logging._warn(`Invalid ipcm sample size ${pcmSampleSize}.`);
6121
6180
  track.info.codec = null;
6122
6181
  }
6123
6182
  } else {
@@ -6128,7 +6187,7 @@ var Mediabunny = (() => {
6128
6187
  } else if (pcmSampleSize === 32) {
6129
6188
  track.info.codec = "pcm-s32be";
6130
6189
  } else {
6131
- console.warn(`Invalid ipcm sample size ${pcmSampleSize}.`);
6190
+ Logging._warn(`Invalid ipcm sample size ${pcmSampleSize}.`);
6132
6191
  track.info.codec = null;
6133
6192
  }
6134
6193
  }
@@ -6140,7 +6199,7 @@ var Mediabunny = (() => {
6140
6199
  } else if (pcmSampleSize === 64) {
6141
6200
  track.info.codec = "pcm-f64";
6142
6201
  } else {
6143
- console.warn(`Invalid fpcm sample size ${pcmSampleSize}.`);
6202
+ Logging._warn(`Invalid fpcm sample size ${pcmSampleSize}.`);
6144
6203
  track.info.codec = null;
6145
6204
  }
6146
6205
  } else {
@@ -6149,7 +6208,7 @@ var Mediabunny = (() => {
6149
6208
  } else if (pcmSampleSize === 64) {
6150
6209
  track.info.codec = "pcm-f64be";
6151
6210
  } else {
6152
- console.warn(`Invalid fpcm sample size ${pcmSampleSize}.`);
6211
+ Logging._warn(`Invalid fpcm sample size ${pcmSampleSize}.`);
6153
6212
  track.info.codec = null;
6154
6213
  }
6155
6214
  }
@@ -6182,12 +6241,12 @@ var Mediabunny = (() => {
6182
6241
  }
6183
6242
  }
6184
6243
  if (track.info.codec === null) {
6185
- console.warn("Unsupported PCM format.");
6244
+ Logging._warn("Unsupported PCM format.");
6186
6245
  }
6187
6246
  } else if (codecName === null) {
6188
- console.warn(`Unknown encrypted audio codec due to missing frma box.`);
6247
+ Logging._warn(`Unknown encrypted audio codec due to missing frma box.`);
6189
6248
  } else {
6190
- console.warn(`Unsupported audio codec (sample entry type '${sampleBoxInfo.name}').`);
6249
+ Logging._warn(`Unsupported audio codec (sample entry type '${sampleBoxInfo.name}').`);
6191
6250
  }
6192
6251
  }
6193
6252
  slice.filePos = sampleBoxStartPos + sampleBoxInfo.totalSize;
@@ -6226,7 +6285,7 @@ var Mediabunny = (() => {
6226
6285
  defaultSkipByteBlock: null
6227
6286
  };
6228
6287
  } else {
6229
- console.warn(`Unsupported encryption scheme '${schemeType}'.`);
6288
+ Logging._warn(`Unsupported encryption scheme '${schemeType}'.`);
6230
6289
  }
6231
6290
  }
6232
6291
  ;
@@ -6439,7 +6498,7 @@ var Mediabunny = (() => {
6439
6498
  } else if (objectTypeIndication === 221) {
6440
6499
  track.info.codec = "vorbis";
6441
6500
  } else {
6442
- console.warn(
6501
+ Logging._warn(
6443
6502
  `Unsupported audio codec (objectTypeIndication ${objectTypeIndication}) - discarding track.`
6444
6503
  );
6445
6504
  }
@@ -6593,7 +6652,7 @@ var Mediabunny = (() => {
6593
6652
  const bytes2 = readBytes(slice, boxInfo.contentSize);
6594
6653
  const config = parseEac3Config(bytes2);
6595
6654
  if (!config) {
6596
- console.warn("Invalid dec3 box contents, ignoring.");
6655
+ Logging._warn("Invalid dec3 box contents, ignoring.");
6597
6656
  break;
6598
6657
  }
6599
6658
  const sampleRate = getEac3SampleRate(config);
@@ -7152,7 +7211,7 @@ var Mediabunny = (() => {
7152
7211
  break;
7153
7212
  }
7154
7213
  if (entryCount > 1) {
7155
- console.warn("Multiple saio entries are not supported; using the first offset only.");
7214
+ Logging._warn("Multiple saio entries are not supported; using the first offset only.");
7156
7215
  }
7157
7216
  let offset = version === 0 ? readU32Be(slice) : Number(readU64Be(slice));
7158
7217
  if (this.currentFragment) {
@@ -9509,7 +9568,7 @@ var Mediabunny = (() => {
9509
9568
  if (this.currentTrack.decodingInstructions.some((instruction) => {
9510
9569
  return instruction.data?.type !== "decompress" || instruction.scope !== 1 /* Block */ || instruction.data.algorithm !== 3 /* HeaderStripping */;
9511
9570
  })) {
9512
- console.warn(`Track #${this.currentTrack.id} has an unsupported content encoding; dropping.`);
9571
+ Logging._warn(`Track #${this.currentTrack.id} has an unsupported content encoding; dropping.`);
9513
9572
  this.currentTrack = null;
9514
9573
  }
9515
9574
  if (this.currentTrack && this.currentTrack.id !== -1 && this.currentTrack.codecId && this.currentTrack.info) {
@@ -13024,8 +13083,26 @@ var Mediabunny = (() => {
13024
13083
  return "audio/flac";
13025
13084
  }
13026
13085
  async readMetadata() {
13027
- let currentPos = 4;
13028
13086
  return this.metadataPromise ??= (async () => {
13087
+ let currentPos = 0;
13088
+ while (true) {
13089
+ let headerSlice = this.reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
13090
+ if (headerSlice instanceof Promise) headerSlice = await headerSlice;
13091
+ if (!headerSlice) {
13092
+ this.lastSampleLoaded = true;
13093
+ return;
13094
+ }
13095
+ const id3V2Header = readId3V2Header(headerSlice);
13096
+ if (!id3V2Header) {
13097
+ break;
13098
+ }
13099
+ let contentSlice = this.reader.requestSlice(headerSlice.filePos, id3V2Header.size);
13100
+ if (contentSlice instanceof Promise) contentSlice = await contentSlice;
13101
+ assert(contentSlice);
13102
+ parseId3V2Tag(contentSlice, id3V2Header, this.metadataTags);
13103
+ currentPos = headerSlice.filePos + id3V2Header.size;
13104
+ }
13105
+ currentPos += 4;
13029
13106
  while (this.reader.fileSize === null || currentPos < this.reader.fileSize) {
13030
13107
  let sizeSlice = this.reader.requestSlice(currentPos, 4);
13031
13108
  if (sizeSlice instanceof Promise) sizeSlice = await sizeSlice;
@@ -13546,6 +13623,10 @@ var Mediabunny = (() => {
13546
13623
  currentPos += this.packetStride;
13547
13624
  continue;
13548
13625
  }
13626
+ if (hasProgramMap && !this.elementaryStreams.some((x) => x.pid === packetHeader.pid)) {
13627
+ currentPos += this.packetStride;
13628
+ continue;
13629
+ }
13549
13630
  const section = await this.readSection(
13550
13631
  currentPos,
13551
13632
  true,
@@ -13703,7 +13784,7 @@ var Mediabunny = (() => {
13703
13784
  break;
13704
13785
  default: {
13705
13786
  if (!ignoredStreamTypes.has(streamType)) {
13706
- console.warn(
13787
+ Logging._warn(
13707
13788
  `Note: MPEG-TS streams with stream_type 0x${streamType.toString(16)} are not currently supported.`
13708
13789
  );
13709
13790
  ignoredStreamTypes.add(streamType);
@@ -14845,7 +14926,10 @@ var Mediabunny = (() => {
14845
14926
  if (codec !== "avc" && codec !== "hevc") {
14846
14927
  throw new Error("Unhandled.");
14847
14928
  }
14929
+ const nalHeaderSize = codec === "avc" ? 1 : 2;
14848
14930
  let packetStartPos = null;
14931
+ let frameStartFound = false;
14932
+ let lastFirstMacroblockInSlice = 0;
14849
14933
  while (true) {
14850
14934
  let remaining = this.ensureBuffered(CHUNK_SIZE);
14851
14935
  if (remaining instanceof Promise) remaining = await remaining;
@@ -14863,7 +14947,7 @@ var Mediabunny = (() => {
14863
14947
  }
14864
14948
  i = zeroIndex;
14865
14949
  const posBeforeZero = chunkStartPos + i;
14866
- if (i + 4 >= length) {
14950
+ if (i + 3 >= length) {
14867
14951
  this.seekTo(posBeforeZero);
14868
14952
  break;
14869
14953
  }
@@ -14871,32 +14955,68 @@ var Mediabunny = (() => {
14871
14955
  const b2 = chunk[i + 2];
14872
14956
  const b3 = chunk[i + 3];
14873
14957
  let startCodeLength = 0;
14874
- let nalUnitTypeByte = null;
14875
14958
  if (b1 === 0 && b2 === 0 && b3 === 1) {
14876
14959
  startCodeLength = 4;
14877
- nalUnitTypeByte = chunk[i + 4];
14878
14960
  } else if (b1 === 0 && b2 === 1) {
14879
14961
  startCodeLength = 3;
14880
- nalUnitTypeByte = b3;
14881
14962
  }
14882
14963
  if (startCodeLength === 0) {
14883
14964
  i++;
14884
14965
  continue;
14885
14966
  }
14886
14967
  const startCodePos = posBeforeZero;
14887
- if (packetStartPos === null) {
14888
- packetStartPos = startCodePos;
14889
- i += startCodeLength;
14890
- continue;
14968
+ packetStartPos ??= startCodePos;
14969
+ const nalHeaderStart = i + startCodeLength;
14970
+ const payloadStart = nalHeaderStart + nalHeaderSize;
14971
+ const AVC_SLICE_HEADER_PEEK_SIZE = 6;
14972
+ const bytesNeeded = payloadStart + (codec === "avc" ? AVC_SLICE_HEADER_PEEK_SIZE : 1);
14973
+ if (bytesNeeded > length) {
14974
+ this.seekTo(posBeforeZero);
14975
+ break;
14891
14976
  }
14892
- if (nalUnitTypeByte !== null) {
14893
- const nalUnitType = codec === "avc" ? extractNalUnitTypeForAvc(nalUnitTypeByte) : extractNalUnitTypeForHevc(nalUnitTypeByte);
14894
- const isAud = codec === "avc" ? nalUnitType === 9 /* AUD */ : nalUnitType === 35 /* AUD_NUT */;
14895
- if (isAud) {
14896
- const packetLength = startCodePos - packetStartPos;
14897
- this.seekTo(packetStartPos);
14898
- return this.supplyPacket(packetLength, 0);
14977
+ const headerByte0 = chunk[nalHeaderStart];
14978
+ let nalUnitType;
14979
+ let isSlice;
14980
+ let isAccessUnitStart;
14981
+ if (codec === "avc") {
14982
+ nalUnitType = extractNalUnitTypeForAvc(headerByte0);
14983
+ isSlice = nalUnitType === 1 /* NON_IDR_SLICE */ || nalUnitType === 2 /* SLICE_DPA */ || nalUnitType === 5 /* IDR */;
14984
+ isAccessUnitStart = nalUnitType === 6 /* SEI */ || nalUnitType === 7 /* SPS */ || nalUnitType === 8 /* PPS */ || nalUnitType === 9 /* AUD */;
14985
+ } else {
14986
+ nalUnitType = extractNalUnitTypeForHevc(headerByte0);
14987
+ const layerId = (headerByte0 & 1) << 5 | chunk[nalHeaderStart + 1] >> 3;
14988
+ if (layerId > 0) {
14989
+ i += startCodeLength;
14990
+ continue;
14991
+ }
14992
+ isSlice = nalUnitType <= 9 /* RASL_R */ || nalUnitType >= 16 /* BLA_W_LP */ && nalUnitType <= 21;
14993
+ isAccessUnitStart = nalUnitType >= 32 /* VPS_NUT */ && nalUnitType <= 37 || nalUnitType === 39 /* PREFIX_SEI_NUT */ || nalUnitType >= 41 && nalUnitType <= 44 || nalUnitType >= 48 && nalUnitType <= 55;
14994
+ }
14995
+ let isFrameBoundary = false;
14996
+ if (isSlice) {
14997
+ let startsNewPicture;
14998
+ if (codec === "avc") {
14999
+ const headerBytes = chunk.subarray(payloadStart, payloadStart + AVC_SLICE_HEADER_PEEK_SIZE);
15000
+ const firstMacroblockInSlice = readExpGolomb(new Bitstream(headerBytes));
15001
+ startsNewPicture = !frameStartFound || firstMacroblockInSlice <= lastFirstMacroblockInSlice;
15002
+ lastFirstMacroblockInSlice = firstMacroblockInSlice;
15003
+ } else {
15004
+ startsNewPicture = chunk[payloadStart] >> 7 === 1;
14899
15005
  }
15006
+ if (startsNewPicture) {
15007
+ if (frameStartFound) {
15008
+ isFrameBoundary = true;
15009
+ } else {
15010
+ frameStartFound = true;
15011
+ }
15012
+ }
15013
+ } else if (isAccessUnitStart && frameStartFound) {
15014
+ isFrameBoundary = true;
15015
+ }
15016
+ if (isFrameBoundary) {
15017
+ const packetLength = startCodePos - packetStartPos;
15018
+ this.seekTo(packetStartPos);
15019
+ return this.supplyPacket(packetLength, 0);
14900
15020
  }
14901
15021
  i += startCodeLength;
14902
15022
  }
@@ -14904,7 +15024,7 @@ var Mediabunny = (() => {
14904
15024
  break;
14905
15025
  }
14906
15026
  }
14907
- if (packetStartPos !== null) {
15027
+ if (packetStartPos !== null && this.endPos > packetStartPos) {
14908
15028
  const packetLength = this.endPos - packetStartPos;
14909
15029
  this.seekTo(packetStartPos);
14910
15030
  return this.supplyPacket(packetLength, 0);
@@ -15983,7 +16103,7 @@ var Mediabunny = (() => {
15983
16103
  }
15984
16104
  const isOnline = typeof navigator !== "undefined" && typeof navigator.onLine === "boolean" ? navigator.onLine : true;
15985
16105
  if (isOnline && originOfSrc !== null && originOfSrc !== window.location.origin) {
15986
- console.warn(
16106
+ Logging._warn(
15987
16107
  `Request will not be retried because a CORS error was suspected due to different origins. You can modify this behavior by providing your own function for the 'getRetryDelay' option.`
15988
16108
  );
15989
16109
  return null;
@@ -16157,8 +16277,7 @@ var Mediabunny = (() => {
16157
16277
  );
16158
16278
  if (url2.origin !== "null" && !(url2.pathname.endsWith(".m3u8") || url2.pathname.endsWith(".m3u"))) {
16159
16279
  if (!warnedOrigins.has(url2.origin)) {
16160
- console.log(this._usedForHls, this._url, url2.pathname);
16161
- console.warn(
16280
+ Logging._warn(
16162
16281
  `HTTP server (origin ${url2.origin}) did not respond to a range request with 206 Partial Content, meaning the entire resource will now be downloaded. To enable efficient media file streaming across a network, please make sure your server supports range requests.`
16163
16282
  );
16164
16283
  warnedOrigins.add(url2.origin);
@@ -16196,7 +16315,7 @@ var Mediabunny = (() => {
16196
16315
  }
16197
16316
  const retryDelayInSeconds = this._getRetryDelay(1, error, this._url);
16198
16317
  if (retryDelayInSeconds !== null) {
16199
- console.error("Error while reading response stream. Attempting to resume.", error);
16318
+ Logging._error("Error while reading response stream. Attempting to resume.", error);
16200
16319
  await wait(1e3 * retryDelayInSeconds);
16201
16320
  break;
16202
16321
  } else {
@@ -18704,7 +18823,18 @@ var Mediabunny = (() => {
18704
18823
  var FlacInputFormat = class extends InputFormat {
18705
18824
  /** @internal */
18706
18825
  async _canReadInput(input) {
18707
- let slice = input._reader.requestSlice(0, 4);
18826
+ let currentPos = 0;
18827
+ while (true) {
18828
+ let slice2 = input._reader.requestSlice(currentPos, ID3_V2_HEADER_SIZE);
18829
+ if (slice2 instanceof Promise) slice2 = await slice2;
18830
+ if (!slice2) break;
18831
+ const id3V2Header = readId3V2Header(slice2);
18832
+ if (!id3V2Header) {
18833
+ break;
18834
+ }
18835
+ currentPos = slice2.filePos + id3V2Header.size;
18836
+ }
18837
+ let slice = input._reader.requestSlice(currentPos, 4);
18708
18838
  if (slice instanceof Promise) slice = await slice;
18709
18839
  if (!slice) return false;
18710
18840
  return readAscii(slice, 4) === "fLaC";
@@ -19020,7 +19150,7 @@ var Mediabunny = (() => {
19020
19150
  const now = performance.now();
19021
19151
  if (value.type === "video") {
19022
19152
  if (now - lastVideoGcErrorLog >= 1e3) {
19023
- console.error(
19153
+ Logging._error(
19024
19154
  `A VideoSample was garbage collected without first being closed. For proper resource management, make sure to call close() on all your VideoSamples as soon as you're done using them.`
19025
19155
  );
19026
19156
  lastVideoGcErrorLog = now;
@@ -19030,7 +19160,7 @@ var Mediabunny = (() => {
19030
19160
  }
19031
19161
  } else {
19032
19162
  if (now - lastAudioGcErrorLog >= 1e3) {
19033
- console.error(
19163
+ Logging._error(
19034
19164
  `An AudioSample was garbage collected without first being closed. For proper resource management, make sure to call close() on all your AudioSamples as soon as you're done using them.`
19035
19165
  );
19036
19166
  lastAudioGcErrorLog = now;
@@ -21578,7 +21708,7 @@ var Mediabunny = (() => {
21578
21708
  if (decoder.prototype instanceof CustomVideoDecoder) {
21579
21709
  const casted = decoder;
21580
21710
  if (customVideoDecoders.includes(casted)) {
21581
- console.warn("Video decoder already registered.");
21711
+ Logging._warn("Video decoder already registered.");
21582
21712
  return;
21583
21713
  }
21584
21714
  customVideoDecoders.push(casted);
@@ -21586,7 +21716,7 @@ var Mediabunny = (() => {
21586
21716
  } else if (decoder.prototype instanceof CustomAudioDecoder) {
21587
21717
  const casted = decoder;
21588
21718
  if (customAudioDecoders.includes(casted)) {
21589
- console.warn("Audio decoder already registered.");
21719
+ Logging._warn("Audio decoder already registered.");
21590
21720
  return;
21591
21721
  }
21592
21722
  customAudioDecoders.push(casted);
@@ -21599,7 +21729,7 @@ var Mediabunny = (() => {
21599
21729
  if (encoder.prototype instanceof CustomVideoEncoder) {
21600
21730
  const casted = encoder;
21601
21731
  if (customVideoEncoders.includes(casted)) {
21602
- console.warn("Video encoder already registered.");
21732
+ Logging._warn("Video encoder already registered.");
21603
21733
  return;
21604
21734
  }
21605
21735
  customVideoEncoders.push(casted);
@@ -21607,7 +21737,7 @@ var Mediabunny = (() => {
21607
21737
  } else if (encoder.prototype instanceof CustomAudioEncoder) {
21608
21738
  const casted = encoder;
21609
21739
  if (customAudioEncoders.includes(casted)) {
21610
- console.warn("Audio encoder already registered.");
21740
+ Logging._warn("Audio encoder already registered.");
21611
21741
  return;
21612
21742
  }
21613
21743
  customAudioEncoders.push(casted);
@@ -22597,7 +22727,7 @@ var Mediabunny = (() => {
22597
22727
  this.gl = null;
22598
22728
  this.canvas = null;
22599
22729
  mergerGpuUnavailable = true;
22600
- console.warn("Falling back to CPU for color/alpha merging.", error);
22730
+ Logging._warn("Falling back to CPU for color/alpha merging.", error);
22601
22731
  }
22602
22732
  }
22603
22733
  }
@@ -24137,7 +24267,7 @@ var Mediabunny = (() => {
24137
24267
  const support = await VideoDecoder.isConfigSupported(decoderConfig);
24138
24268
  return support.supported === true;
24139
24269
  } catch (error) {
24140
- console.error("Error during decodability check:", error);
24270
+ Logging._error("Error during decodability check:", error);
24141
24271
  return false;
24142
24272
  }
24143
24273
  }
@@ -24239,7 +24369,7 @@ var Mediabunny = (() => {
24239
24369
  return support.supported === true;
24240
24370
  }
24241
24371
  } catch (error) {
24242
- console.error("Error during decodability check:", error);
24372
+ Logging._error("Error during decodability check:", error);
24243
24373
  return false;
24244
24374
  }
24245
24375
  }
@@ -25280,19 +25410,20 @@ var Mediabunny = (() => {
25280
25410
  slice.filePos = startPos;
25281
25411
  return null;
25282
25412
  }
25283
- const size = decodeSynchsafe(sizeRaw);
25413
+ let size = decodeSynchsafe(sizeRaw);
25414
+ if (flags & 16 /* Footer */) {
25415
+ size += ID3_V2_HEADER_SIZE;
25416
+ }
25284
25417
  return { majorVersion, revision, flags, size };
25285
25418
  };
25286
25419
  var parseId3V2Tag = (slice, header, tags) => {
25287
25420
  if (![2, 3, 4].includes(header.majorVersion)) {
25288
- console.warn(`Unsupported ID3v2 major version: ${header.majorVersion}`);
25421
+ Logging._warn(`Unsupported ID3v2 major version: ${header.majorVersion}`);
25289
25422
  return;
25290
25423
  }
25291
- const bytes2 = readBytes(slice, header.size);
25424
+ const dataSize = header.flags & 16 /* Footer */ ? header.size - ID3_V2_HEADER_SIZE : header.size;
25425
+ const bytes2 = readBytes(slice, dataSize);
25292
25426
  const reader = new Id3V2Reader(header, bytes2);
25293
- if (header.flags & 16 /* Footer */) {
25294
- reader.removeFooter();
25295
- }
25296
25427
  if (header.flags & 128 /* Unsynchronisation */ && header.majorVersion === 3) {
25297
25428
  reader.ununsynchronizeAll();
25298
25429
  }
@@ -25323,12 +25454,12 @@ var Mediabunny = (() => {
25323
25454
  frameUnsynchronized = !!(frame.flags & 1 << 1) || !!(header.flags & 128 /* Unsynchronisation */);
25324
25455
  }
25325
25456
  if (frameEncrypted) {
25326
- console.warn(`Skipping encrypted ID3v2 frame ${frame.id}`);
25457
+ Logging._warn(`Skipping encrypted ID3v2 frame ${frame.id}`);
25327
25458
  reader.pos = frameEndPos;
25328
25459
  continue;
25329
25460
  }
25330
25461
  if (frameCompressed) {
25331
- console.warn(`Skipping compressed ID3v2 frame ${frame.id}`);
25462
+ Logging._warn(`Skipping compressed ID3v2 frame ${frame.id}`);
25332
25463
  reader.pos = frameEndPos;
25333
25464
  continue;
25334
25465
  }
@@ -25564,10 +25695,6 @@ var Mediabunny = (() => {
25564
25695
  this.bytes.set(after, before.length + newBytes.length);
25565
25696
  this.view = new DataView(this.bytes.buffer);
25566
25697
  }
25567
- removeFooter() {
25568
- this.bytes = this.bytes.subarray(0, this.bytes.length - ID3_V2_HEADER_SIZE);
25569
- this.view = new DataView(this.bytes.buffer);
25570
- }
25571
25698
  readBytes(length) {
25572
25699
  const slice = this.bytes.subarray(this.pos, this.pos + length);
25573
25700
  this.pos += length;
@@ -32023,7 +32150,7 @@ ${cue.notes ?? ""}`;
32023
32150
  const writtenTags = /* @__PURE__ */ new Set();
32024
32151
  const writeInfoTag = (tag, value) => {
32025
32152
  if (!isIso88591Compatible(value)) {
32026
- console.warn(`Didn't write tag '${tag}' because '${value}' is not ISO 8859-1-compatible.`);
32153
+ Logging._warn(`Didn't write tag '${tag}' because '${value}' is not ISO 8859-1-compatible.`);
32027
32154
  return;
32028
32155
  }
32029
32156
  const size = value.length + 1;
@@ -32987,7 +33114,7 @@ ${cue.notes ?? ""}`;
32987
33114
  this.gl = null;
32988
33115
  this.canvas = null;
32989
33116
  splitterGpuUnavailable = true;
32990
- console.warn("Falling back to CPU for color/alpha splitting.", error);
33117
+ Logging._warn("Falling back to CPU for color/alpha splitting.", error);
32991
33118
  }
32992
33119
  }
32993
33120
  }
@@ -33107,7 +33234,7 @@ ${cue.notes ?? ""}`;
33107
33234
  this.gl.shaderSource(shader, source);
33108
33235
  this.gl.compileShader(shader);
33109
33236
  if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
33110
- console.error("Shader compile error:", this.gl.getShaderInfoLog(shader));
33237
+ Logging._error("Shader compile error:", this.gl.getShaderInfoLog(shader));
33111
33238
  }
33112
33239
  return shader;
33113
33240
  }
@@ -33497,7 +33624,7 @@ ${cue.notes ?? ""}`;
33497
33624
  /** @internal */
33498
33625
  async _start() {
33499
33626
  if (!this._errorPromiseAccessed) {
33500
- console.warn(
33627
+ Logging._warn(
33501
33628
  "Make sure not to ignore the `errorPromise` field on MediaStreamVideoTrackSource, so that any internal errors get bubbled up properly."
33502
33629
  );
33503
33630
  }
@@ -34314,7 +34441,7 @@ ${cue.notes ?? ""}`;
34314
34441
  /** @internal */
34315
34442
  async _start() {
34316
34443
  if (!this._errorPromiseAccessed) {
34317
- console.warn(
34444
+ Logging._warn(
34318
34445
  "Make sure not to ignore the `errorPromise` field on MediaStreamAudioTrackSource, so that any internal errors get bubbled up properly."
34319
34446
  );
34320
34447
  }
@@ -34649,7 +34776,7 @@ ${cue.notes ?? ""}`;
34649
34776
  }
34650
34777
  if (track.type === otherTrack.type) {
34651
34778
  if (!illegalPairingDetected) {
34652
- console.warn(
34779
+ Logging._warn(
34653
34780
  `Illegal pairing of two ${track.type} tracks detected, which is not possible in HLS; treating them as unpaired.`
34654
34781
  );
34655
34782
  illegalPairingDetected = true;
@@ -34658,7 +34785,7 @@ ${cue.notes ?? ""}`;
34658
34785
  }
34659
34786
  if (track.isVideoTrack() && track.metadata.hasOnlyKeyPackets || otherTrack.isVideoTrack() && otherTrack.metadata.hasOnlyKeyPackets) {
34660
34787
  if (!keyPacketsOnlyPairingWarned) {
34661
- console.warn(
34788
+ Logging._warn(
34662
34789
  `A key-packets-only video track is pairable with another track, which is not possible in HLS; treating them as unpaired.`
34663
34790
  );
34664
34791
  keyPacketsOnlyPairingWarned = true;
@@ -35512,7 +35639,7 @@ ${cue.notes ?? ""}`;
35512
35639
  groupIdTrackCount++;
35513
35640
  masterPlaylistText += `#EXT-X-MEDIA:TYPE=${type.toUpperCase()},GROUP-ID="${decl.groupId}"`;
35514
35641
  if (name !== null && /[\n\r"]/.test(name)) {
35515
- console.warn(
35642
+ Logging._warn(
35516
35643
  "Dropping track name since it includes a line feed, carriage return, or double quote character, which are not allowed in HLS playlist attributes."
35517
35644
  );
35518
35645
  name = null;
@@ -36746,7 +36873,7 @@ ${cue.notes ?? ""}`;
36746
36873
  throw new Error("Output has been canceled.");
36747
36874
  }
36748
36875
  if (this._startPromise) {
36749
- console.warn("Output has already been started.");
36876
+ Logging._warn("Output has already been started.");
36750
36877
  return this._startPromise;
36751
36878
  }
36752
36879
  return this._startPromise = (async () => {
@@ -36777,11 +36904,11 @@ ${cue.notes ?? ""}`;
36777
36904
  */
36778
36905
  async cancel() {
36779
36906
  if (this._cancelPromise) {
36780
- console.warn("Output has already been canceled.");
36907
+ Logging._warn("Output has already been canceled.");
36781
36908
  return this._cancelPromise;
36782
36909
  } else if (this.state === "finalizing" || this.state === "finalized") {
36783
36910
  if (this.state === "finalized") {
36784
- console.warn("Output has already been finalized.");
36911
+ Logging._warn("Output has already been finalized.");
36785
36912
  }
36786
36913
  return;
36787
36914
  }
@@ -36810,7 +36937,7 @@ ${cue.notes ?? ""}`;
36810
36937
  throw new Error("Cannot finalize after canceling.");
36811
36938
  }
36812
36939
  if (this._finalizePromise) {
36813
- console.warn("Output has already been finalized.");
36940
+ Logging._warn("Output has already been finalized.");
36814
36941
  return this._finalizePromise;
36815
36942
  }
36816
36943
  return this._finalizePromise = (async () => {
@@ -37258,7 +37385,7 @@ ${cue.notes ?? ""}`;
37258
37385
  warnElements.push(this._getInvalidityExplanation().join(""));
37259
37386
  }
37260
37387
  if (warnElements.length > 0) {
37261
- console.warn(...warnElements);
37388
+ Logging._warn(...warnElements);
37262
37389
  }
37263
37390
  }
37264
37391
  }
@@ -37391,7 +37518,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
37391
37518
  return;
37392
37519
  }
37393
37520
  if (this._canceled) {
37394
- console.warn("Conversion already canceled.");
37521
+ Logging._warn("Conversion already canceled.");
37395
37522
  return;
37396
37523
  }
37397
37524
  this._canceled = true;
@@ -37522,7 +37649,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
37522
37649
  firstSample.close();
37523
37650
  await tempOutput.finalize();
37524
37651
  } catch (error) {
37525
- console.info("Error when probing encoder support. Falling back to rerender path.", error);
37652
+ Logging._info("Error when probing encoder support. Falling back to rerender path.", error);
37526
37653
  needsRerender = true;
37527
37654
  void tempOutput.cancel();
37528
37655
  }
@@ -37854,7 +37981,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
37854
37981
  // src/index.ts
37855
37982
  var MEDIABUNNY_LOADED_SYMBOL = Symbol.for("mediabunny loaded");
37856
37983
  if (globalThis[MEDIABUNNY_LOADED_SYMBOL]) {
37857
- console.error(
37984
+ Logging._error(
37858
37985
  "[WARNING]\nMediabunny was loaded twice. This will likely cause Mediabunny not to work correctly. Check if multiple dependencies are importing different versions of Mediabunny, or if something is being bundled incorrectly."
37859
37986
  );
37860
37987
  }