@utilix-tech/sdk 0.70.0 → 0.71.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/CHANGELOG.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
4
4
 
5
+ ## 0.71.0
6
+ - Add `readMidiInfo` (midi-file-info): parse a Standard MIDI File's header and every track chunk to report format, tick division, initial tempo, time signature, and per-track event/note-on counts, plus total duration in seconds accounting for tempo changes.
7
+
5
8
  ## 0.70.0
6
9
  - Add `generateHotp`, `generateTotp` (totp-hotp-generator): generate an HOTP code (RFC 4226) for a counter value, or the current TOTP code (RFC 6238) plus seconds until rotation, from a base32-encoded shared secret, supporting SHA-1/SHA-256/SHA-512 and 6-8 digit codes.
7
10
  - Add `calculateTaxEquivalentYield` (tax-equivalent-yield-calculator): convert between a tax-free municipal bond yield and its taxable equivalent given a marginal federal (plus optional state) tax rate, in both directions.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @utilix-tech/sdk
2
2
 
3
- **691 developer utility functions for Node.js: runs locally, no API key required.**
3
+ **692 developer utility functions for Node.js: runs locally, no API key required.**
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@utilix-tech/sdk?style=flat-square&color=cb3837)](https://www.npmjs.com/package/@utilix-tech/sdk)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@utilix-tech/sdk?style=flat-square)](https://www.npmjs.com/package/@utilix-tech/sdk)
@@ -876,10 +876,10 @@ analyzeString("café"); // { length: 4, codePoints: [...], ... }
876
876
 
877
877
  ---
878
878
 
879
- ### `/media`: Image Header Parsing, EXIF, PDF Metadata & Page Dimensions, WAV, ID3, ICO, FLAC, Video & GIF Metadata
879
+ ### `/media`: Image Header Parsing, EXIF, PDF Metadata & Page Dimensions, WAV, ID3, ICO, FLAC, Video, GIF & MIDI Metadata
880
880
 
881
881
  ```ts
882
- import { readImageInfo, readExifData, readPdfMetadata, readPdfPageDimensions, readWavInfo, readId3Tags, readIcoInfo, readFlacInfo, readVideoInfo, inspectGifFrames } from "@utilix-tech/sdk/media";
882
+ import { readImageInfo, readExifData, readPdfMetadata, readPdfPageDimensions, readWavInfo, readId3Tags, readIcoInfo, readFlacInfo, readVideoInfo, inspectGifFrames, readMidiInfo } from "@utilix-tech/sdk/media";
883
883
 
884
884
  // Reads format, dimensions, bit depth, and alpha channel straight from
885
885
  // file bytes: no decoding, no canvas, no image library.
@@ -945,9 +945,17 @@ readVideoInfo(new Uint8Array(videoBytes));
945
945
  const gifBytes = await fs.promises.readFile("animation.gif");
946
946
  inspectGifFrames(new Uint8Array(gifBytes));
947
947
  // { version: "89a", width: 480, height: 270, frameCount: 24, animated: true, loopCount: 0, totalDurationMs: 2400, ... }
948
+
949
+ // Parses a Standard MIDI File's header and every track chunk to report
950
+ // format, tick division, initial tempo, time signature, and per-track
951
+ // event/note-on counts, plus total duration in seconds: no MIDI playback
952
+ // or synthesis.
953
+ const midiBytes = await fs.promises.readFile("song.mid");
954
+ readMidiInfo(new Uint8Array(midiBytes));
955
+ // { format: 1, trackCount: 2, initialTempoBpm: 120, timeSignature: { numerator: 4, denominator: 4 }, durationSeconds: 4, tracks: [...] }
948
956
  ```
949
957
 
950
- `readImageInfo` supports PNG, JPEG, GIF, WebP, and BMP. `readExifData` supports JPEG only. `readWavInfo` supports the canonical RIFF/WAVE container only. `readId3Tags` decodes ID3v2.3/2.4 and ID3v1/1.1 only (ID3v2.2 is detected but not decoded). `readIcoInfo` reads .ico icon files only and rejects .cur cursor files. `readFlacInfo` reads the native FLAC container only, not FLAC-in-Ogg. `readVideoInfo` supports MP4 (ISO BMFF) and WebM (EBML/Matroska) containers only. `inspectGifFrames` reads the GIF87a/89a block structure only; it never decodes pixel data.
958
+ `readImageInfo` supports PNG, JPEG, GIF, WebP, and BMP. `readExifData` supports JPEG only. `readWavInfo` supports the canonical RIFF/WAVE container only. `readId3Tags` decodes ID3v2.3/2.4 and ID3v1/1.1 only (ID3v2.2 is detected but not decoded). `readIcoInfo` reads .ico icon files only and rejects .cur cursor files. `readFlacInfo` reads the native FLAC container only, not FLAC-in-Ogg. `readVideoInfo` supports MP4 (ISO BMFF) and WebM (EBML/Matroska) containers only. `inspectGifFrames` reads the GIF87a/89a block structure only; it never decodes pixel data. `readMidiInfo` reads Standard MIDI Files (format 0/1/2) only.
951
959
 
952
960
  ---
953
961
 
@@ -9,6 +9,7 @@ __export(media_exports, {
9
9
  readIcoInfo: () => readIcoInfo,
10
10
  readId3Tags: () => readId3Tags,
11
11
  readImageInfo: () => readImageInfo,
12
+ readMidiInfo: () => readMidiInfo,
12
13
  readPdfMetadata: () => readPdfMetadata,
13
14
  readPdfPageDimensions: () => readPdfPageDimensions,
14
15
  readVideoInfo: () => readVideoInfo,
@@ -1306,5 +1307,135 @@ function inspectGifFrames(bytes) {
1306
1307
  hasTransparency
1307
1308
  };
1308
1309
  }
1310
+ function readU16BE(bytes, offset) {
1311
+ return bytes[offset] << 8 | bytes[offset + 1];
1312
+ }
1313
+ function readMidiVarLen(bytes, pos) {
1314
+ let value = 0;
1315
+ let i = pos;
1316
+ for (let n = 0; n < 4; n++) {
1317
+ if (i >= bytes.length) return null;
1318
+ const b = bytes[i];
1319
+ value = value << 7 | b & 127;
1320
+ i++;
1321
+ if ((b & 128) === 0) return { value, next: i };
1322
+ }
1323
+ return null;
1324
+ }
1325
+ function readMidiInfo(bytes) {
1326
+ if (bytes.length < 14) return { error: "File is too small to be a valid MIDI file" };
1327
+ if (Buffer.from(bytes.subarray(0, 4)).toString("ascii") !== "MThd") {
1328
+ return { error: 'Not a valid MIDI file (missing "MThd" header chunk)' };
1329
+ }
1330
+ const headerLength = readU32BE(bytes, 4);
1331
+ if (headerLength < 6 || 8 + headerLength > bytes.length) return { error: "Truncated or invalid MThd header chunk" };
1332
+ const format = readU16BE(bytes, 8);
1333
+ if (format !== 0 && format !== 1 && format !== 2) return { error: `Unsupported MIDI format: ${format} (expected 0, 1, or 2)` };
1334
+ const trackCount = readU16BE(bytes, 10);
1335
+ if (trackCount < 1) return { error: "MIDI file declares zero tracks" };
1336
+ const divisionRaw = readU16BE(bytes, 12);
1337
+ const division = (divisionRaw & 32768) !== 0 ? { type: "smpte", framesPerSecond: -(divisionRaw >> 8 << 24 >> 24), ticksPerFrame: divisionRaw & 255 } : { type: "ppq", ticksPerQuarterNote: divisionRaw & 32767 };
1338
+ const tracks = [];
1339
+ const tempoChanges = [];
1340
+ let timeSignature = null;
1341
+ let maxEndTick = 0;
1342
+ let offset = 8 + headerLength;
1343
+ let tracksParsed = 0;
1344
+ while (tracksParsed < trackCount && offset + 8 <= bytes.length) {
1345
+ const chunkId = Buffer.from(bytes.subarray(offset, offset + 4)).toString("ascii");
1346
+ const chunkLength = readU32BE(bytes, offset + 4);
1347
+ const dataStart = offset + 8;
1348
+ const dataEnd = Math.min(dataStart + chunkLength, bytes.length);
1349
+ if (chunkId !== "MTrk") {
1350
+ offset = dataEnd;
1351
+ continue;
1352
+ }
1353
+ let pos = dataStart;
1354
+ let runningStatus = 0;
1355
+ let absoluteTick = 0;
1356
+ let eventCount = 0;
1357
+ let noteOnCount = 0;
1358
+ let name = null;
1359
+ while (pos < dataEnd) {
1360
+ const delta = readMidiVarLen(bytes, pos);
1361
+ if (!delta) break;
1362
+ pos = delta.next;
1363
+ absoluteTick += delta.value;
1364
+ if (pos >= dataEnd) break;
1365
+ let statusByte = bytes[pos];
1366
+ if (statusByte & 128) {
1367
+ runningStatus = statusByte;
1368
+ pos++;
1369
+ }
1370
+ statusByte = runningStatus;
1371
+ eventCount++;
1372
+ if (statusByte === 255) {
1373
+ const metaType = bytes[pos];
1374
+ pos++;
1375
+ const len = readMidiVarLen(bytes, pos);
1376
+ if (!len) break;
1377
+ pos = len.next;
1378
+ const data = bytes.subarray(pos, Math.min(pos + len.value, dataEnd));
1379
+ pos += len.value;
1380
+ if (metaType === 81 && data.length >= 3) {
1381
+ tempoChanges.push({ tick: absoluteTick, usPerQuarter: data[0] << 16 | data[1] << 8 | data[2] });
1382
+ } else if (metaType === 88 && data.length >= 2) {
1383
+ if (!timeSignature) timeSignature = { numerator: data[0], denominator: 2 ** data[1] };
1384
+ } else if (metaType === 3 && name === null) {
1385
+ name = Buffer.from(data).toString("utf8").trim() || null;
1386
+ } else if (metaType === 47) {
1387
+ break;
1388
+ }
1389
+ } else if (statusByte === 240 || statusByte === 247) {
1390
+ const len = readMidiVarLen(bytes, pos);
1391
+ if (!len) break;
1392
+ pos = len.next + len.value;
1393
+ } else if (statusByte >= 128) {
1394
+ const type = statusByte & 240;
1395
+ if (type === 192 || type === 208) {
1396
+ pos += 1;
1397
+ } else {
1398
+ if (type === 144 && (bytes[pos + 1] ?? 0) > 0) noteOnCount++;
1399
+ pos += 2;
1400
+ }
1401
+ } else {
1402
+ break;
1403
+ }
1404
+ }
1405
+ tracks.push({ index: tracksParsed, name, eventCount, noteOnCount });
1406
+ maxEndTick = Math.max(maxEndTick, absoluteTick);
1407
+ offset = dataEnd;
1408
+ tracksParsed++;
1409
+ }
1410
+ if (tracks.length === 0) return { error: "No MTrk track chunks found in this MIDI file" };
1411
+ const DEFAULT_US_PER_QUARTER = 5e5;
1412
+ const initialTempoBpm = Math.round(6e7 / (tempoChanges[0]?.usPerQuarter ?? DEFAULT_US_PER_QUARTER) * 100) / 100;
1413
+ let durationSeconds = null;
1414
+ if (division.type === "smpte") {
1415
+ const ticksPerSecond = division.framesPerSecond * division.ticksPerFrame;
1416
+ durationSeconds = ticksPerSecond > 0 ? Math.round(maxEndTick / ticksPerSecond * 1e3) / 1e3 : null;
1417
+ } else {
1418
+ const sorted = [...tempoChanges].sort((a, b) => a.tick - b.tick);
1419
+ let seconds = 0;
1420
+ let prevTick = 0;
1421
+ let currentUsPerQuarter = DEFAULT_US_PER_QUARTER;
1422
+ for (const change of sorted) {
1423
+ seconds += (change.tick - prevTick) / division.ticksPerQuarterNote * (currentUsPerQuarter / 1e6);
1424
+ prevTick = change.tick;
1425
+ currentUsPerQuarter = change.usPerQuarter;
1426
+ }
1427
+ seconds += (maxEndTick - prevTick) / division.ticksPerQuarterNote * (currentUsPerQuarter / 1e6);
1428
+ durationSeconds = Math.round(seconds * 1e3) / 1e3;
1429
+ }
1430
+ return {
1431
+ format,
1432
+ trackCount: tracks.length,
1433
+ division,
1434
+ initialTempoBpm,
1435
+ timeSignature,
1436
+ durationSeconds,
1437
+ tracks
1438
+ };
1439
+ }
1309
1440
 
1310
- export { inspectGifFrames, media_exports, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readPdfMetadata, readPdfPageDimensions, readVideoInfo, readWavInfo };
1441
+ export { inspectGifFrames, media_exports, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readMidiInfo, readPdfMetadata, readPdfPageDimensions, readVideoInfo, readWavInfo };
package/dist/index.cjs CHANGED
@@ -24357,6 +24357,7 @@ __export(media_exports, {
24357
24357
  readIcoInfo: () => readIcoInfo,
24358
24358
  readId3Tags: () => readId3Tags,
24359
24359
  readImageInfo: () => readImageInfo,
24360
+ readMidiInfo: () => readMidiInfo,
24360
24361
  readPdfMetadata: () => readPdfMetadata,
24361
24362
  readPdfPageDimensions: () => readPdfPageDimensions,
24362
24363
  readVideoInfo: () => readVideoInfo,
@@ -25654,6 +25655,136 @@ function inspectGifFrames(bytes) {
25654
25655
  hasTransparency
25655
25656
  };
25656
25657
  }
25658
+ function readU16BE(bytes, offset) {
25659
+ return bytes[offset] << 8 | bytes[offset + 1];
25660
+ }
25661
+ function readMidiVarLen(bytes, pos) {
25662
+ let value = 0;
25663
+ let i = pos;
25664
+ for (let n = 0; n < 4; n++) {
25665
+ if (i >= bytes.length) return null;
25666
+ const b = bytes[i];
25667
+ value = value << 7 | b & 127;
25668
+ i++;
25669
+ if ((b & 128) === 0) return { value, next: i };
25670
+ }
25671
+ return null;
25672
+ }
25673
+ function readMidiInfo(bytes) {
25674
+ if (bytes.length < 14) return { error: "File is too small to be a valid MIDI file" };
25675
+ if (Buffer.from(bytes.subarray(0, 4)).toString("ascii") !== "MThd") {
25676
+ return { error: 'Not a valid MIDI file (missing "MThd" header chunk)' };
25677
+ }
25678
+ const headerLength = readU32BE(bytes, 4);
25679
+ if (headerLength < 6 || 8 + headerLength > bytes.length) return { error: "Truncated or invalid MThd header chunk" };
25680
+ const format = readU16BE(bytes, 8);
25681
+ if (format !== 0 && format !== 1 && format !== 2) return { error: `Unsupported MIDI format: ${format} (expected 0, 1, or 2)` };
25682
+ const trackCount = readU16BE(bytes, 10);
25683
+ if (trackCount < 1) return { error: "MIDI file declares zero tracks" };
25684
+ const divisionRaw = readU16BE(bytes, 12);
25685
+ const division = (divisionRaw & 32768) !== 0 ? { type: "smpte", framesPerSecond: -(divisionRaw >> 8 << 24 >> 24), ticksPerFrame: divisionRaw & 255 } : { type: "ppq", ticksPerQuarterNote: divisionRaw & 32767 };
25686
+ const tracks = [];
25687
+ const tempoChanges = [];
25688
+ let timeSignature = null;
25689
+ let maxEndTick = 0;
25690
+ let offset = 8 + headerLength;
25691
+ let tracksParsed = 0;
25692
+ while (tracksParsed < trackCount && offset + 8 <= bytes.length) {
25693
+ const chunkId = Buffer.from(bytes.subarray(offset, offset + 4)).toString("ascii");
25694
+ const chunkLength = readU32BE(bytes, offset + 4);
25695
+ const dataStart = offset + 8;
25696
+ const dataEnd = Math.min(dataStart + chunkLength, bytes.length);
25697
+ if (chunkId !== "MTrk") {
25698
+ offset = dataEnd;
25699
+ continue;
25700
+ }
25701
+ let pos = dataStart;
25702
+ let runningStatus = 0;
25703
+ let absoluteTick = 0;
25704
+ let eventCount = 0;
25705
+ let noteOnCount = 0;
25706
+ let name = null;
25707
+ while (pos < dataEnd) {
25708
+ const delta = readMidiVarLen(bytes, pos);
25709
+ if (!delta) break;
25710
+ pos = delta.next;
25711
+ absoluteTick += delta.value;
25712
+ if (pos >= dataEnd) break;
25713
+ let statusByte = bytes[pos];
25714
+ if (statusByte & 128) {
25715
+ runningStatus = statusByte;
25716
+ pos++;
25717
+ }
25718
+ statusByte = runningStatus;
25719
+ eventCount++;
25720
+ if (statusByte === 255) {
25721
+ const metaType = bytes[pos];
25722
+ pos++;
25723
+ const len = readMidiVarLen(bytes, pos);
25724
+ if (!len) break;
25725
+ pos = len.next;
25726
+ const data = bytes.subarray(pos, Math.min(pos + len.value, dataEnd));
25727
+ pos += len.value;
25728
+ if (metaType === 81 && data.length >= 3) {
25729
+ tempoChanges.push({ tick: absoluteTick, usPerQuarter: data[0] << 16 | data[1] << 8 | data[2] });
25730
+ } else if (metaType === 88 && data.length >= 2) {
25731
+ if (!timeSignature) timeSignature = { numerator: data[0], denominator: 2 ** data[1] };
25732
+ } else if (metaType === 3 && name === null) {
25733
+ name = Buffer.from(data).toString("utf8").trim() || null;
25734
+ } else if (metaType === 47) {
25735
+ break;
25736
+ }
25737
+ } else if (statusByte === 240 || statusByte === 247) {
25738
+ const len = readMidiVarLen(bytes, pos);
25739
+ if (!len) break;
25740
+ pos = len.next + len.value;
25741
+ } else if (statusByte >= 128) {
25742
+ const type = statusByte & 240;
25743
+ if (type === 192 || type === 208) {
25744
+ pos += 1;
25745
+ } else {
25746
+ if (type === 144 && (bytes[pos + 1] ?? 0) > 0) noteOnCount++;
25747
+ pos += 2;
25748
+ }
25749
+ } else {
25750
+ break;
25751
+ }
25752
+ }
25753
+ tracks.push({ index: tracksParsed, name, eventCount, noteOnCount });
25754
+ maxEndTick = Math.max(maxEndTick, absoluteTick);
25755
+ offset = dataEnd;
25756
+ tracksParsed++;
25757
+ }
25758
+ if (tracks.length === 0) return { error: "No MTrk track chunks found in this MIDI file" };
25759
+ const DEFAULT_US_PER_QUARTER = 5e5;
25760
+ const initialTempoBpm = Math.round(6e7 / (tempoChanges[0]?.usPerQuarter ?? DEFAULT_US_PER_QUARTER) * 100) / 100;
25761
+ let durationSeconds = null;
25762
+ if (division.type === "smpte") {
25763
+ const ticksPerSecond = division.framesPerSecond * division.ticksPerFrame;
25764
+ durationSeconds = ticksPerSecond > 0 ? Math.round(maxEndTick / ticksPerSecond * 1e3) / 1e3 : null;
25765
+ } else {
25766
+ const sorted = [...tempoChanges].sort((a, b) => a.tick - b.tick);
25767
+ let seconds = 0;
25768
+ let prevTick = 0;
25769
+ let currentUsPerQuarter = DEFAULT_US_PER_QUARTER;
25770
+ for (const change of sorted) {
25771
+ seconds += (change.tick - prevTick) / division.ticksPerQuarterNote * (currentUsPerQuarter / 1e6);
25772
+ prevTick = change.tick;
25773
+ currentUsPerQuarter = change.usPerQuarter;
25774
+ }
25775
+ seconds += (maxEndTick - prevTick) / division.ticksPerQuarterNote * (currentUsPerQuarter / 1e6);
25776
+ durationSeconds = Math.round(seconds * 1e3) / 1e3;
25777
+ }
25778
+ return {
25779
+ format,
25780
+ trackCount: tracks.length,
25781
+ division,
25782
+ initialTempoBpm,
25783
+ timeSignature,
25784
+ durationSeconds,
25785
+ tracks
25786
+ };
25787
+ }
25657
25788
 
25658
25789
  // src/index.ts
25659
25790
  var version = "0.1.0";
package/dist/index.d.cts CHANGED
@@ -13,7 +13,7 @@ export { c as color } from './color-tPwZCr9H.cjs';
13
13
  export { c as css } from './css-Cf7AMGM-.cjs';
14
14
  export { m as misc } from './misc-CA3N198T.cjs';
15
15
  export { a as ai_agent } from './ai_agent-CmrVjvYH.cjs';
16
- export { m as media } from './media-BUvwm4wU.cjs';
16
+ export { m as media } from './media-56zrIBw4.cjs';
17
17
 
18
18
  declare const version = "0.1.0";
19
19
 
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export { c as color } from './color-tPwZCr9H.js';
13
13
  export { c as css } from './css-Cf7AMGM-.js';
14
14
  export { m as misc } from './misc-CA3N198T.js';
15
15
  export { a as ai_agent } from './ai_agent-CmrVjvYH.js';
16
- export { m as media } from './media-BUvwm4wU.js';
16
+ export { m as media } from './media-56zrIBw4.js';
17
17
 
18
18
  declare const version = "0.1.0";
19
19
 
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { media_exports as media } from './chunk-226EH3ZI.js';
1
+ export { media_exports as media } from './chunk-PT4N4UBL.js';
2
2
  export { units_exports as units } from './chunk-653HDWXW.js';
3
3
  export { network_exports as network } from './chunk-ACGCCOCK.js';
4
4
  export { api_exports as api } from './chunk-4S63T7Y4.js';
@@ -224,6 +224,45 @@ interface GifInfoError {
224
224
  * any LZW-compressed pixel data.
225
225
  */
226
226
  declare function inspectGifFrames(bytes: Uint8Array): GifInfo | GifInfoError;
227
+ type MidiDivision = {
228
+ type: 'ppq';
229
+ ticksPerQuarterNote: number;
230
+ } | {
231
+ type: 'smpte';
232
+ framesPerSecond: number;
233
+ ticksPerFrame: number;
234
+ };
235
+ interface MidiTrackInfo {
236
+ index: number;
237
+ name: string | null;
238
+ eventCount: number;
239
+ noteOnCount: number;
240
+ }
241
+ interface MidiTimeSignature {
242
+ numerator: number;
243
+ denominator: number;
244
+ }
245
+ interface MidiInfo {
246
+ format: number;
247
+ trackCount: number;
248
+ division: MidiDivision;
249
+ initialTempoBpm: number;
250
+ timeSignature: MidiTimeSignature | null;
251
+ durationSeconds: number | null;
252
+ tracks: MidiTrackInfo[];
253
+ }
254
+ interface MidiInfoError {
255
+ error: string;
256
+ }
257
+ /**
258
+ * Parse a Standard MIDI File (SMF) header and every track chunk to report
259
+ * format (0/1/2), the tick division, initial tempo, time signature, a
260
+ * per-track event/note-on count, and total duration in seconds. Duration
261
+ * accounts for tempo-change meta events across the whole file when the
262
+ * division is ticks-per-quarter-note; the rarer SMPTE division uses a fixed
263
+ * frames-per-second/ticks-per-frame rate instead.
264
+ */
265
+ declare function readMidiInfo(bytes: Uint8Array): MidiInfo | MidiInfoError;
227
266
 
228
267
  type media_ExifData = ExifData;
229
268
  type media_ExifError = ExifError;
@@ -239,6 +278,11 @@ type media_Id3TagsError = Id3TagsError;
239
278
  type media_ImageFormat = ImageFormat;
240
279
  type media_ImageInfo = ImageInfo;
241
280
  type media_ImageInfoError = ImageInfoError;
281
+ type media_MidiDivision = MidiDivision;
282
+ type media_MidiInfo = MidiInfo;
283
+ type media_MidiInfoError = MidiInfoError;
284
+ type media_MidiTimeSignature = MidiTimeSignature;
285
+ type media_MidiTrackInfo = MidiTrackInfo;
242
286
  type media_PdfMetadata = PdfMetadata;
243
287
  type media_PdfMetadataError = PdfMetadataError;
244
288
  type media_PdfPageDimension = PdfPageDimension;
@@ -254,12 +298,13 @@ declare const media_readFlacInfo: typeof readFlacInfo;
254
298
  declare const media_readIcoInfo: typeof readIcoInfo;
255
299
  declare const media_readId3Tags: typeof readId3Tags;
256
300
  declare const media_readImageInfo: typeof readImageInfo;
301
+ declare const media_readMidiInfo: typeof readMidiInfo;
257
302
  declare const media_readPdfMetadata: typeof readPdfMetadata;
258
303
  declare const media_readPdfPageDimensions: typeof readPdfPageDimensions;
259
304
  declare const media_readVideoInfo: typeof readVideoInfo;
260
305
  declare const media_readWavInfo: typeof readWavInfo;
261
306
  declare namespace media {
262
- export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_FlacInfo as FlacInfo, type media_FlacInfoError as FlacInfoError, type media_GifInfo as GifInfo, type media_GifInfoError as GifInfoError, type media_IcoImageEntry as IcoImageEntry, type media_IcoInfo as IcoInfo, type media_IcoInfoError as IcoInfoError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_PdfPageDimension as PdfPageDimension, type media_PdfPageDimensionsResult as PdfPageDimensionsResult, type media_PdfPageOrientation as PdfPageOrientation, type media_VideoInfo as VideoInfo, type media_VideoInfoError as VideoInfoError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_inspectGifFrames as inspectGifFrames, media_readExifData as readExifData, media_readFlacInfo as readFlacInfo, media_readIcoInfo as readIcoInfo, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata, media_readPdfPageDimensions as readPdfPageDimensions, media_readVideoInfo as readVideoInfo, media_readWavInfo as readWavInfo };
307
+ export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_FlacInfo as FlacInfo, type media_FlacInfoError as FlacInfoError, type media_GifInfo as GifInfo, type media_GifInfoError as GifInfoError, type media_IcoImageEntry as IcoImageEntry, type media_IcoInfo as IcoInfo, type media_IcoInfoError as IcoInfoError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_MidiDivision as MidiDivision, type media_MidiInfo as MidiInfo, type media_MidiInfoError as MidiInfoError, type media_MidiTimeSignature as MidiTimeSignature, type media_MidiTrackInfo as MidiTrackInfo, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_PdfPageDimension as PdfPageDimension, type media_PdfPageDimensionsResult as PdfPageDimensionsResult, type media_PdfPageOrientation as PdfPageOrientation, type media_VideoInfo as VideoInfo, type media_VideoInfoError as VideoInfoError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_inspectGifFrames as inspectGifFrames, media_readExifData as readExifData, media_readFlacInfo as readFlacInfo, media_readIcoInfo as readIcoInfo, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readMidiInfo as readMidiInfo, media_readPdfMetadata as readPdfMetadata, media_readPdfPageDimensions as readPdfPageDimensions, media_readVideoInfo as readVideoInfo, media_readWavInfo as readWavInfo };
263
308
  }
264
309
 
265
- export { readWavInfo as A, type ExifData as E, type FlacInfo as F, type GifInfo as G, type IcoImageEntry as I, type PdfMetadata as P, type VideoInfo as V, type WavInfo as W, type ExifError as a, type FlacInfoError as b, type GifInfoError as c, type IcoInfo as d, type IcoInfoError as e, type Id3Tags as f, type Id3TagsError as g, type ImageFormat as h, type ImageInfo as i, type ImageInfoError as j, type PdfMetadataError as k, type PdfPageDimension as l, media as m, type PdfPageDimensionsResult as n, type PdfPageOrientation as o, type VideoInfoError as p, type WavInfoError as q, inspectGifFrames as r, readExifData as s, readFlacInfo as t, readIcoInfo as u, readId3Tags as v, readImageInfo as w, readPdfMetadata as x, readPdfPageDimensions as y, readVideoInfo as z };
310
+ export { readImageInfo as A, readMidiInfo as B, readPdfMetadata as C, readPdfPageDimensions as D, type ExifData as E, type FlacInfo as F, type GifInfo as G, readVideoInfo as H, type IcoImageEntry as I, readWavInfo as J, type MidiDivision as M, type PdfMetadata as P, type VideoInfo as V, type WavInfo as W, type ExifError as a, type FlacInfoError as b, type GifInfoError as c, type IcoInfo as d, type IcoInfoError as e, type Id3Tags as f, type Id3TagsError as g, type ImageFormat as h, type ImageInfo as i, type ImageInfoError as j, type MidiInfo as k, type MidiInfoError as l, media as m, type MidiTimeSignature as n, type MidiTrackInfo as o, type PdfMetadataError as p, type PdfPageDimension as q, type PdfPageDimensionsResult as r, type PdfPageOrientation as s, type VideoInfoError as t, type WavInfoError as u, inspectGifFrames as v, readExifData as w, readFlacInfo as x, readIcoInfo as y, readId3Tags as z };
@@ -224,6 +224,45 @@ interface GifInfoError {
224
224
  * any LZW-compressed pixel data.
225
225
  */
226
226
  declare function inspectGifFrames(bytes: Uint8Array): GifInfo | GifInfoError;
227
+ type MidiDivision = {
228
+ type: 'ppq';
229
+ ticksPerQuarterNote: number;
230
+ } | {
231
+ type: 'smpte';
232
+ framesPerSecond: number;
233
+ ticksPerFrame: number;
234
+ };
235
+ interface MidiTrackInfo {
236
+ index: number;
237
+ name: string | null;
238
+ eventCount: number;
239
+ noteOnCount: number;
240
+ }
241
+ interface MidiTimeSignature {
242
+ numerator: number;
243
+ denominator: number;
244
+ }
245
+ interface MidiInfo {
246
+ format: number;
247
+ trackCount: number;
248
+ division: MidiDivision;
249
+ initialTempoBpm: number;
250
+ timeSignature: MidiTimeSignature | null;
251
+ durationSeconds: number | null;
252
+ tracks: MidiTrackInfo[];
253
+ }
254
+ interface MidiInfoError {
255
+ error: string;
256
+ }
257
+ /**
258
+ * Parse a Standard MIDI File (SMF) header and every track chunk to report
259
+ * format (0/1/2), the tick division, initial tempo, time signature, a
260
+ * per-track event/note-on count, and total duration in seconds. Duration
261
+ * accounts for tempo-change meta events across the whole file when the
262
+ * division is ticks-per-quarter-note; the rarer SMPTE division uses a fixed
263
+ * frames-per-second/ticks-per-frame rate instead.
264
+ */
265
+ declare function readMidiInfo(bytes: Uint8Array): MidiInfo | MidiInfoError;
227
266
 
228
267
  type media_ExifData = ExifData;
229
268
  type media_ExifError = ExifError;
@@ -239,6 +278,11 @@ type media_Id3TagsError = Id3TagsError;
239
278
  type media_ImageFormat = ImageFormat;
240
279
  type media_ImageInfo = ImageInfo;
241
280
  type media_ImageInfoError = ImageInfoError;
281
+ type media_MidiDivision = MidiDivision;
282
+ type media_MidiInfo = MidiInfo;
283
+ type media_MidiInfoError = MidiInfoError;
284
+ type media_MidiTimeSignature = MidiTimeSignature;
285
+ type media_MidiTrackInfo = MidiTrackInfo;
242
286
  type media_PdfMetadata = PdfMetadata;
243
287
  type media_PdfMetadataError = PdfMetadataError;
244
288
  type media_PdfPageDimension = PdfPageDimension;
@@ -254,12 +298,13 @@ declare const media_readFlacInfo: typeof readFlacInfo;
254
298
  declare const media_readIcoInfo: typeof readIcoInfo;
255
299
  declare const media_readId3Tags: typeof readId3Tags;
256
300
  declare const media_readImageInfo: typeof readImageInfo;
301
+ declare const media_readMidiInfo: typeof readMidiInfo;
257
302
  declare const media_readPdfMetadata: typeof readPdfMetadata;
258
303
  declare const media_readPdfPageDimensions: typeof readPdfPageDimensions;
259
304
  declare const media_readVideoInfo: typeof readVideoInfo;
260
305
  declare const media_readWavInfo: typeof readWavInfo;
261
306
  declare namespace media {
262
- export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_FlacInfo as FlacInfo, type media_FlacInfoError as FlacInfoError, type media_GifInfo as GifInfo, type media_GifInfoError as GifInfoError, type media_IcoImageEntry as IcoImageEntry, type media_IcoInfo as IcoInfo, type media_IcoInfoError as IcoInfoError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_PdfPageDimension as PdfPageDimension, type media_PdfPageDimensionsResult as PdfPageDimensionsResult, type media_PdfPageOrientation as PdfPageOrientation, type media_VideoInfo as VideoInfo, type media_VideoInfoError as VideoInfoError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_inspectGifFrames as inspectGifFrames, media_readExifData as readExifData, media_readFlacInfo as readFlacInfo, media_readIcoInfo as readIcoInfo, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata, media_readPdfPageDimensions as readPdfPageDimensions, media_readVideoInfo as readVideoInfo, media_readWavInfo as readWavInfo };
307
+ export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_FlacInfo as FlacInfo, type media_FlacInfoError as FlacInfoError, type media_GifInfo as GifInfo, type media_GifInfoError as GifInfoError, type media_IcoImageEntry as IcoImageEntry, type media_IcoInfo as IcoInfo, type media_IcoInfoError as IcoInfoError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_MidiDivision as MidiDivision, type media_MidiInfo as MidiInfo, type media_MidiInfoError as MidiInfoError, type media_MidiTimeSignature as MidiTimeSignature, type media_MidiTrackInfo as MidiTrackInfo, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_PdfPageDimension as PdfPageDimension, type media_PdfPageDimensionsResult as PdfPageDimensionsResult, type media_PdfPageOrientation as PdfPageOrientation, type media_VideoInfo as VideoInfo, type media_VideoInfoError as VideoInfoError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_inspectGifFrames as inspectGifFrames, media_readExifData as readExifData, media_readFlacInfo as readFlacInfo, media_readIcoInfo as readIcoInfo, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readMidiInfo as readMidiInfo, media_readPdfMetadata as readPdfMetadata, media_readPdfPageDimensions as readPdfPageDimensions, media_readVideoInfo as readVideoInfo, media_readWavInfo as readWavInfo };
263
308
  }
264
309
 
265
- export { readWavInfo as A, type ExifData as E, type FlacInfo as F, type GifInfo as G, type IcoImageEntry as I, type PdfMetadata as P, type VideoInfo as V, type WavInfo as W, type ExifError as a, type FlacInfoError as b, type GifInfoError as c, type IcoInfo as d, type IcoInfoError as e, type Id3Tags as f, type Id3TagsError as g, type ImageFormat as h, type ImageInfo as i, type ImageInfoError as j, type PdfMetadataError as k, type PdfPageDimension as l, media as m, type PdfPageDimensionsResult as n, type PdfPageOrientation as o, type VideoInfoError as p, type WavInfoError as q, inspectGifFrames as r, readExifData as s, readFlacInfo as t, readIcoInfo as u, readId3Tags as v, readImageInfo as w, readPdfMetadata as x, readPdfPageDimensions as y, readVideoInfo as z };
310
+ export { readImageInfo as A, readMidiInfo as B, readPdfMetadata as C, readPdfPageDimensions as D, type ExifData as E, type FlacInfo as F, type GifInfo as G, readVideoInfo as H, type IcoImageEntry as I, readWavInfo as J, type MidiDivision as M, type PdfMetadata as P, type VideoInfo as V, type WavInfo as W, type ExifError as a, type FlacInfoError as b, type GifInfoError as c, type IcoInfo as d, type IcoInfoError as e, type Id3Tags as f, type Id3TagsError as g, type ImageFormat as h, type ImageInfo as i, type ImageInfoError as j, type MidiInfo as k, type MidiInfoError as l, media as m, type MidiTimeSignature as n, type MidiTrackInfo as o, type PdfMetadataError as p, type PdfPageDimension as q, type PdfPageDimensionsResult as r, type PdfPageOrientation as s, type VideoInfoError as t, type WavInfoError as u, inspectGifFrames as v, readExifData as w, readFlacInfo as x, readIcoInfo as y, readId3Tags as z };
@@ -1293,6 +1293,136 @@ function inspectGifFrames(bytes) {
1293
1293
  hasTransparency
1294
1294
  };
1295
1295
  }
1296
+ function readU16BE(bytes, offset) {
1297
+ return bytes[offset] << 8 | bytes[offset + 1];
1298
+ }
1299
+ function readMidiVarLen(bytes, pos) {
1300
+ let value = 0;
1301
+ let i = pos;
1302
+ for (let n = 0; n < 4; n++) {
1303
+ if (i >= bytes.length) return null;
1304
+ const b = bytes[i];
1305
+ value = value << 7 | b & 127;
1306
+ i++;
1307
+ if ((b & 128) === 0) return { value, next: i };
1308
+ }
1309
+ return null;
1310
+ }
1311
+ function readMidiInfo(bytes) {
1312
+ if (bytes.length < 14) return { error: "File is too small to be a valid MIDI file" };
1313
+ if (Buffer.from(bytes.subarray(0, 4)).toString("ascii") !== "MThd") {
1314
+ return { error: 'Not a valid MIDI file (missing "MThd" header chunk)' };
1315
+ }
1316
+ const headerLength = readU32BE(bytes, 4);
1317
+ if (headerLength < 6 || 8 + headerLength > bytes.length) return { error: "Truncated or invalid MThd header chunk" };
1318
+ const format = readU16BE(bytes, 8);
1319
+ if (format !== 0 && format !== 1 && format !== 2) return { error: `Unsupported MIDI format: ${format} (expected 0, 1, or 2)` };
1320
+ const trackCount = readU16BE(bytes, 10);
1321
+ if (trackCount < 1) return { error: "MIDI file declares zero tracks" };
1322
+ const divisionRaw = readU16BE(bytes, 12);
1323
+ const division = (divisionRaw & 32768) !== 0 ? { type: "smpte", framesPerSecond: -(divisionRaw >> 8 << 24 >> 24), ticksPerFrame: divisionRaw & 255 } : { type: "ppq", ticksPerQuarterNote: divisionRaw & 32767 };
1324
+ const tracks = [];
1325
+ const tempoChanges = [];
1326
+ let timeSignature = null;
1327
+ let maxEndTick = 0;
1328
+ let offset = 8 + headerLength;
1329
+ let tracksParsed = 0;
1330
+ while (tracksParsed < trackCount && offset + 8 <= bytes.length) {
1331
+ const chunkId = Buffer.from(bytes.subarray(offset, offset + 4)).toString("ascii");
1332
+ const chunkLength = readU32BE(bytes, offset + 4);
1333
+ const dataStart = offset + 8;
1334
+ const dataEnd = Math.min(dataStart + chunkLength, bytes.length);
1335
+ if (chunkId !== "MTrk") {
1336
+ offset = dataEnd;
1337
+ continue;
1338
+ }
1339
+ let pos = dataStart;
1340
+ let runningStatus = 0;
1341
+ let absoluteTick = 0;
1342
+ let eventCount = 0;
1343
+ let noteOnCount = 0;
1344
+ let name = null;
1345
+ while (pos < dataEnd) {
1346
+ const delta = readMidiVarLen(bytes, pos);
1347
+ if (!delta) break;
1348
+ pos = delta.next;
1349
+ absoluteTick += delta.value;
1350
+ if (pos >= dataEnd) break;
1351
+ let statusByte = bytes[pos];
1352
+ if (statusByte & 128) {
1353
+ runningStatus = statusByte;
1354
+ pos++;
1355
+ }
1356
+ statusByte = runningStatus;
1357
+ eventCount++;
1358
+ if (statusByte === 255) {
1359
+ const metaType = bytes[pos];
1360
+ pos++;
1361
+ const len = readMidiVarLen(bytes, pos);
1362
+ if (!len) break;
1363
+ pos = len.next;
1364
+ const data = bytes.subarray(pos, Math.min(pos + len.value, dataEnd));
1365
+ pos += len.value;
1366
+ if (metaType === 81 && data.length >= 3) {
1367
+ tempoChanges.push({ tick: absoluteTick, usPerQuarter: data[0] << 16 | data[1] << 8 | data[2] });
1368
+ } else if (metaType === 88 && data.length >= 2) {
1369
+ if (!timeSignature) timeSignature = { numerator: data[0], denominator: 2 ** data[1] };
1370
+ } else if (metaType === 3 && name === null) {
1371
+ name = Buffer.from(data).toString("utf8").trim() || null;
1372
+ } else if (metaType === 47) {
1373
+ break;
1374
+ }
1375
+ } else if (statusByte === 240 || statusByte === 247) {
1376
+ const len = readMidiVarLen(bytes, pos);
1377
+ if (!len) break;
1378
+ pos = len.next + len.value;
1379
+ } else if (statusByte >= 128) {
1380
+ const type = statusByte & 240;
1381
+ if (type === 192 || type === 208) {
1382
+ pos += 1;
1383
+ } else {
1384
+ if (type === 144 && (bytes[pos + 1] ?? 0) > 0) noteOnCount++;
1385
+ pos += 2;
1386
+ }
1387
+ } else {
1388
+ break;
1389
+ }
1390
+ }
1391
+ tracks.push({ index: tracksParsed, name, eventCount, noteOnCount });
1392
+ maxEndTick = Math.max(maxEndTick, absoluteTick);
1393
+ offset = dataEnd;
1394
+ tracksParsed++;
1395
+ }
1396
+ if (tracks.length === 0) return { error: "No MTrk track chunks found in this MIDI file" };
1397
+ const DEFAULT_US_PER_QUARTER = 5e5;
1398
+ const initialTempoBpm = Math.round(6e7 / (tempoChanges[0]?.usPerQuarter ?? DEFAULT_US_PER_QUARTER) * 100) / 100;
1399
+ let durationSeconds = null;
1400
+ if (division.type === "smpte") {
1401
+ const ticksPerSecond = division.framesPerSecond * division.ticksPerFrame;
1402
+ durationSeconds = ticksPerSecond > 0 ? Math.round(maxEndTick / ticksPerSecond * 1e3) / 1e3 : null;
1403
+ } else {
1404
+ const sorted = [...tempoChanges].sort((a, b) => a.tick - b.tick);
1405
+ let seconds = 0;
1406
+ let prevTick = 0;
1407
+ let currentUsPerQuarter = DEFAULT_US_PER_QUARTER;
1408
+ for (const change of sorted) {
1409
+ seconds += (change.tick - prevTick) / division.ticksPerQuarterNote * (currentUsPerQuarter / 1e6);
1410
+ prevTick = change.tick;
1411
+ currentUsPerQuarter = change.usPerQuarter;
1412
+ }
1413
+ seconds += (maxEndTick - prevTick) / division.ticksPerQuarterNote * (currentUsPerQuarter / 1e6);
1414
+ durationSeconds = Math.round(seconds * 1e3) / 1e3;
1415
+ }
1416
+ return {
1417
+ format,
1418
+ trackCount: tracks.length,
1419
+ division,
1420
+ initialTempoBpm,
1421
+ timeSignature,
1422
+ durationSeconds,
1423
+ tracks
1424
+ };
1425
+ }
1296
1426
 
1297
1427
  exports.inspectGifFrames = inspectGifFrames;
1298
1428
  exports.readExifData = readExifData;
@@ -1300,6 +1430,7 @@ exports.readFlacInfo = readFlacInfo;
1300
1430
  exports.readIcoInfo = readIcoInfo;
1301
1431
  exports.readId3Tags = readId3Tags;
1302
1432
  exports.readImageInfo = readImageInfo;
1433
+ exports.readMidiInfo = readMidiInfo;
1303
1434
  exports.readPdfMetadata = readPdfMetadata;
1304
1435
  exports.readPdfPageDimensions = readPdfPageDimensions;
1305
1436
  exports.readVideoInfo = readVideoInfo;
@@ -1 +1 @@
1
- export { E as ExifData, a as ExifError, F as FlacInfo, b as FlacInfoError, G as GifInfo, c as GifInfoError, I as IcoImageEntry, d as IcoInfo, e as IcoInfoError, f as Id3Tags, g as Id3TagsError, h as ImageFormat, i as ImageInfo, j as ImageInfoError, P as PdfMetadata, k as PdfMetadataError, l as PdfPageDimension, n as PdfPageDimensionsResult, o as PdfPageOrientation, V as VideoInfo, p as VideoInfoError, W as WavInfo, q as WavInfoError, r as inspectGifFrames, s as readExifData, t as readFlacInfo, u as readIcoInfo, v as readId3Tags, w as readImageInfo, x as readPdfMetadata, y as readPdfPageDimensions, z as readVideoInfo, A as readWavInfo } from '../media-BUvwm4wU.cjs';
1
+ export { E as ExifData, a as ExifError, F as FlacInfo, b as FlacInfoError, G as GifInfo, c as GifInfoError, I as IcoImageEntry, d as IcoInfo, e as IcoInfoError, f as Id3Tags, g as Id3TagsError, h as ImageFormat, i as ImageInfo, j as ImageInfoError, M as MidiDivision, k as MidiInfo, l as MidiInfoError, n as MidiTimeSignature, o as MidiTrackInfo, P as PdfMetadata, p as PdfMetadataError, q as PdfPageDimension, r as PdfPageDimensionsResult, s as PdfPageOrientation, V as VideoInfo, t as VideoInfoError, W as WavInfo, u as WavInfoError, v as inspectGifFrames, w as readExifData, x as readFlacInfo, y as readIcoInfo, z as readId3Tags, A as readImageInfo, B as readMidiInfo, C as readPdfMetadata, D as readPdfPageDimensions, H as readVideoInfo, J as readWavInfo } from '../media-56zrIBw4.cjs';
@@ -1 +1 @@
1
- export { E as ExifData, a as ExifError, F as FlacInfo, b as FlacInfoError, G as GifInfo, c as GifInfoError, I as IcoImageEntry, d as IcoInfo, e as IcoInfoError, f as Id3Tags, g as Id3TagsError, h as ImageFormat, i as ImageInfo, j as ImageInfoError, P as PdfMetadata, k as PdfMetadataError, l as PdfPageDimension, n as PdfPageDimensionsResult, o as PdfPageOrientation, V as VideoInfo, p as VideoInfoError, W as WavInfo, q as WavInfoError, r as inspectGifFrames, s as readExifData, t as readFlacInfo, u as readIcoInfo, v as readId3Tags, w as readImageInfo, x as readPdfMetadata, y as readPdfPageDimensions, z as readVideoInfo, A as readWavInfo } from '../media-BUvwm4wU.js';
1
+ export { E as ExifData, a as ExifError, F as FlacInfo, b as FlacInfoError, G as GifInfo, c as GifInfoError, I as IcoImageEntry, d as IcoInfo, e as IcoInfoError, f as Id3Tags, g as Id3TagsError, h as ImageFormat, i as ImageInfo, j as ImageInfoError, M as MidiDivision, k as MidiInfo, l as MidiInfoError, n as MidiTimeSignature, o as MidiTrackInfo, P as PdfMetadata, p as PdfMetadataError, q as PdfPageDimension, r as PdfPageDimensionsResult, s as PdfPageOrientation, V as VideoInfo, t as VideoInfoError, W as WavInfo, u as WavInfoError, v as inspectGifFrames, w as readExifData, x as readFlacInfo, y as readIcoInfo, z as readId3Tags, A as readImageInfo, B as readMidiInfo, C as readPdfMetadata, D as readPdfPageDimensions, H as readVideoInfo, J as readWavInfo } from '../media-56zrIBw4.js';
@@ -1,2 +1,2 @@
1
- export { inspectGifFrames, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readPdfMetadata, readPdfPageDimensions, readVideoInfo, readWavInfo } from '../chunk-226EH3ZI.js';
1
+ export { inspectGifFrames, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readMidiInfo, readPdfMetadata, readPdfPageDimensions, readVideoInfo, readWavInfo } from '../chunk-PT4N4UBL.js';
2
2
  import '../chunk-MLKGABMK.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilix-tech/sdk",
3
- "version": "0.70.0",
3
+ "version": "0.71.0",
4
4
  "description": "154+ developer utility tools for Node.js: JSON, encoding, hashing, color, CSS, network and more. Runs locally, no API key required.",
5
5
  "author": "Utilix <hello@utilix.tech>",
6
6
  "license": "MIT",