taglib-wasm 0.2.8 → 0.3.2

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/README.md CHANGED
@@ -1,32 +1,52 @@
1
1
  # taglib-wasm
2
2
 
3
- This is the Wasm version of [**TagLib**](https://taglib.org/), the most robust, de-facto standard for reading and editing metadata tags (Title, Album, Artist, etc.) in all popular audio formats. `taglib-wasm` exists because the JavaScipt/TypeScipt ecosystem had no battle-tested audio tagging library that supports reading and writing music metadata to all popular audio formats — until now!
4
-
5
- `taglib-wasm` stands on the shoulders of giants, including [TagLib](https://taglib.org/) itself, [Emscripten](https://emscripten.org/), and [Wasm](https://webassembly.org/) ([WebAssembly](https://webassembly.org/)).
6
-
7
- `taglib-wasm` aspires to be a universal solution for **JavaScript/TypeScript** platforms — Deno, Node.js, Bun, web browsers, and Cloudflare Workers. Note: This project is a baby, and you’re likely to experience some surprises at this stage of its development. I’m extremely motivated to help address them, since I’ll also be depending on this project.
3
+ This is the Wasm version of [**TagLib**](https://taglib.org/), the most robust,
4
+ de-facto standard for reading and editing metadata tags (Title, Album, Artist,
5
+ etc.) in all popular audio formats. `taglib-wasm` exists because the
6
+ JavaScipt/TypeScipt ecosystem had no battle-tested audio tagging library that
7
+ supports reading and writing music metadata to all popular audio formats until
8
+ now!
9
+
10
+ `taglib-wasm` stands on the shoulders of giants, including
11
+ [TagLib](https://taglib.org/) itself, [Emscripten](https://emscripten.org/), and
12
+ [Wasm](https://webassembly.org/) ([WebAssembly](https://webassembly.org/)).
13
+
14
+ `taglib-wasm` aspires to be a universal solution for **JavaScript/TypeScript**
15
+ platforms — Deno, Node.js, Bun, web browsers, and Cloudflare Workers. Note: This
16
+ project is a baby, and you’re likely to experience some surprises at this stage
17
+ of its development. I’m extremely motivated to help address them, since I’ll
18
+ also be depending on this project.
8
19
 
9
20
  ## 🤔 Why?
10
21
 
11
- Because there’s nothing like it. [`mp3tag.js`](https://mp3tag.js.org/) is mature and active, but only supports MP3 files and ID3 tags. TagLib was an ideal choice from a maturity and capabilities point of view, but wrappers like `node-taglib` appeared to be dormant, and I wanted to avoid making users install platform-specific dependencies whenever possible.
22
+ Because there’s nothing like it. [`mp3tag.js`](https://mp3tag.js.org/) is mature
23
+ and active, but only supports MP3 files and ID3 tags. TagLib was an ideal choice
24
+ from a maturity and capabilities point of view, but wrappers like `node-taglib`
25
+ appeared to be dormant, and I wanted to avoid making users install
26
+ platform-specific dependencies whenever possible.
12
27
 
13
28
  ## 🎯 Features
14
29
 
15
- - **✅ Universal compatibility** – Works with Deno, Node.js, Bun, web browsers, and Cloudflare Workers
30
+ - **✅ Universal compatibility** – Works with Deno, Node.js, Bun, web browsers,
31
+ and Cloudflare Workers
16
32
  - **✅ TypeScript first** – Complete type definitions and modern API
17
- - **✅ Full audio format support** – Supports all audio formats supported by TagLib
18
- - **✅ Format abstraction** – `taglib-wasm` deals with how tags are read from/written to in different file formats
33
+ - **✅ Full audio format support** – Supports all audio formats supported by
34
+ TagLib
35
+ - **✅ Format abstraction** – `taglib-wasm` deals with how tags are read
36
+ from/written to in different file formats
19
37
  - **✅ Zero dependencies** – Self-contained WASM bundle
20
38
  - **✅ Memory efficient** – In-memory processing without filesystem access
21
- - **✅ Production ready** – Growing test suite helps ensure safety and reliability
22
- - **🆕 Two API styles** – Choose between Simple (3 functions) or Core (full control) APIs
39
+ - **✅ Production ready** – Growing test suite helps ensure safety and
40
+ reliability
41
+ - **🆕 Two API styles** – Choose between Simple (3 functions) or Core (full
42
+ control) APIs
23
43
 
24
44
  ## 📦 Installation
25
45
 
26
46
  ### Deno
27
47
 
28
48
  ```typescript
29
- import { TagLib } from "jsr:@charleswiltgen/taglib-wasm";
49
+ import { TagLib } from "npm:taglib-wasm";
30
50
  ```
31
51
 
32
52
  ### Node.js
@@ -35,7 +55,19 @@ import { TagLib } from "jsr:@charleswiltgen/taglib-wasm";
35
55
  npm install taglib-wasm
36
56
  ```
37
57
 
38
- **Note:** The NPM package ships TypeScript source files. Use a TypeScript loader like [`tsx`](https://github.com/privatenumber/tsx):
58
+ The package uses TypeScript. You have two options:
59
+
60
+ #### Option 1: Use Node’s native TypeScript support
61
+
62
+ ```bash
63
+ # Node.js 22.6.0+ with experimental flag
64
+ node --experimental-strip-types your-script.ts
65
+
66
+ # Node.js 23.6.0+ (no flag needed)
67
+ node your-script.ts
68
+ ```
69
+
70
+ #### Option 2: TypeScript loader (recommended for production)
39
71
 
40
72
  ```bash
41
73
  npm install --save-dev tsx
@@ -52,16 +84,17 @@ bun add taglib-wasm
52
84
 
53
85
  ### Simple API
54
86
 
55
- Inspired by [go-taglib](https://github.com/sentriz/go-taglib)’s excellent developer experience:
87
+ This was inspired by [go-taglib](https://github.com/sentriz/go-taglib), a
88
+ similar project for Go created at about the same time.
56
89
 
57
90
  ```typescript
58
91
  import { readProperties, readTags, writeTags } from "taglib-wasm/simple";
59
92
 
60
- // Read tags - just one function call!
93
+ // Read tags
61
94
  const tags = await readTags("song.mp3");
62
95
  console.log(tags.title, tags.artist, tags.album);
63
96
 
64
- // Write tags - simple as can be
97
+ // Write tags
65
98
  await writeTags("song.mp3", {
66
99
  title: "New Title",
67
100
  artist: "New Artist",
@@ -75,16 +108,16 @@ console.log(`Duration: ${props.length}s, Bitrate: ${props.bitrate} kbps`);
75
108
 
76
109
  ### Core API
77
110
 
78
- Full control when you need it:
111
+ The Core API provides full control for more advanced applications.
79
112
 
80
113
  ```typescript
81
- import { TagLib } from "jsr:@charleswiltgen/taglib-wasm";
114
+ import { TagLib } from "taglib-wasm";
82
115
 
83
116
  // Initialize taglib-wasm
84
117
  const taglib = await TagLib.initialize();
85
118
 
86
119
  // Load audio file from buffer
87
- const audioData = await Deno.readFile("song.mp3");
120
+ const audioData = await readFile("song.mp3"); // Node.js/Bun: fs.readFile, Deno: Deno.readFile
88
121
  const file = taglib.openFile(audioData);
89
122
 
90
123
  // Read metadata
@@ -97,23 +130,90 @@ console.log(`Duration: ${props.length}s`);
97
130
  console.log(`Bitrate: ${props.bitrate} kbps`);
98
131
 
99
132
  // Write metadata
100
- file.setTitle("New Title");
101
- file.setArtist("New Artist");
102
- file.setAlbum("New Album");
133
+ const tag = file.tag();
134
+ tag.setTitle("New Title");
135
+ tag.setArtist("New Artist");
136
+ tag.setAlbum("New Album");
103
137
 
104
- console.log("Updated tags:", file.tag());
138
+ // Save changes
139
+ file.save();
105
140
 
106
- // Automatic tag mapping (format-agnostic)
107
- file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
108
- file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
109
- file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
141
+ console.log("Updated tags:", file.tag());
110
142
 
111
143
  // Clean up
112
144
  file.dispose();
113
145
  ```
114
146
 
147
+ ### Tag Constants
148
+
149
+ taglib-wasm provides type-safe tag constants with IDE autocomplete:
150
+
151
+ ```typescript
152
+ import { Tags } from "taglib-wasm";
153
+
154
+ // Use constants for better type safety and autocomplete
155
+ const properties = file.properties();
156
+
157
+ // Read properties
158
+ const title = properties[Tags.Title]?.[0];
159
+ const albumArtist = properties[Tags.AlbumArtist]?.[0];
160
+ const musicBrainzId = properties[Tags.MusicBrainzArtistId]?.[0];
161
+
162
+ // Write properties
163
+ file.setProperties({
164
+ [Tags.Title]: ["My Song"],
165
+ [Tags.AlbumArtist]: ["Various Artists"],
166
+ [Tags.Bpm]: ["128"]
167
+ });
168
+
169
+ // All constants provide IDE autocomplete
170
+ Tags.Title // → "TITLE"
171
+ Tags.Artist // → "ARTIST"
172
+ Tags.AlbumArtist // → "ALBUMARTIST"
173
+ Tags.TrackGain // → "REPLAYGAIN_TRACK_GAIN"
174
+ // ... and many more
175
+ ```
176
+
177
+ See [Tag Name Constants](docs/Tag-Name-Constants.md) for the complete list of available tags and format-specific mappings.
178
+
115
179
  ## Platform examples
116
180
 
181
+ ### Deno
182
+
183
+ ```typescript
184
+ import { TagLib } from "npm:taglib-wasm";
185
+
186
+ // Initialize taglib-wasm
187
+ const taglib = await TagLib.initialize();
188
+
189
+ // Load audio file from filesystem
190
+ const audioData = await Deno.readFile("song.mp3");
191
+ const file = taglib.openFile(audioData);
192
+
193
+ // Read metadata
194
+ const tags = file.tag();
195
+ const props = file.audioProperties();
196
+
197
+ console.log(`Title: ${tags.title}`);
198
+ console.log(`Artist: ${tags.artist}`);
199
+ console.log(`Duration: ${props.length}s`);
200
+ console.log(`Bitrate: ${props.bitrate} kbps`);
201
+
202
+ // Write metadata
203
+ const tag = file.tag();
204
+ tag.setTitle("New Title");
205
+ tag.setArtist("New Artist");
206
+ tag.setAlbum("New Album");
207
+
208
+ // Save changes
209
+ file.save();
210
+
211
+ console.log("Updated tags:", file.tag());
212
+
213
+ // Clean up
214
+ file.dispose();
215
+ ```
216
+
117
217
  ### Node.js
118
218
 
119
219
  ```typescript
@@ -137,16 +237,15 @@ console.log(`Duration: ${props.length}s`);
137
237
  console.log(`Bitrate: ${props.bitrate} kbps`);
138
238
 
139
239
  // Write metadata
140
- file.setTitle("New Title");
141
- file.setArtist("New Artist");
142
- file.setAlbum("New Album");
240
+ const tag = file.tag();
241
+ tag.setTitle("New Title");
242
+ tag.setArtist("New Artist");
243
+ tag.setAlbum("New Album");
143
244
 
144
- console.log("Updated tags:", file.tag());
245
+ // Save changes
246
+ file.save();
145
247
 
146
- // Automatic tag mapping (format-agnostic)
147
- file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
148
- file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
149
- file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
248
+ console.log("Updated tags:", file.tag());
150
249
 
151
250
  // Clean up
152
251
  file.dispose();
@@ -174,16 +273,15 @@ console.log(`Duration: ${props.length}s`);
174
273
  console.log(`Bitrate: ${props.bitrate} kbps`);
175
274
 
176
275
  // Write metadata
177
- file.setTitle("New Title");
178
- file.setArtist("New Artist");
179
- file.setAlbum("New Album");
276
+ const tag = file.tag();
277
+ tag.setTitle("New Title");
278
+ tag.setArtist("New Artist");
279
+ tag.setAlbum("New Album");
180
280
 
181
- console.log("Updated tags:", file.tag());
281
+ // Save changes
282
+ file.save();
182
283
 
183
- // Automatic tag mapping (format-agnostic)
184
- file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
185
- file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
186
- file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
284
+ console.log("Updated tags:", file.tag());
187
285
 
188
286
  // Clean up
189
287
  file.dispose();
@@ -213,16 +311,15 @@ console.log(`Duration: ${props.length}s`);
213
311
  console.log(`Bitrate: ${props.bitrate} kbps`);
214
312
 
215
313
  // Write metadata
216
- file.setTitle("New Title");
217
- file.setArtist("New Artist");
218
- file.setAlbum("New Album");
314
+ const tag = file.tag();
315
+ tag.setTitle("New Title");
316
+ tag.setArtist("New Artist");
317
+ tag.setAlbum("New Album");
219
318
 
220
- console.log("Updated tags:", file.tag());
319
+ // Save changes
320
+ file.save();
221
321
 
222
- // Automatic tag mapping (format-agnostic)
223
- file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
224
- file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
225
- file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
322
+ console.log("Updated tags:", file.tag());
226
323
 
227
324
  // Clean up
228
325
  file.dispose();
@@ -237,7 +334,8 @@ export default {
237
334
  async fetch(request: Request): Promise<Response> {
238
335
  if (request.method === "POST") {
239
336
  try {
240
- // Initialize taglib-wasm
337
+ // Initialize taglib-wasm with Workers-specific configuration
338
+ // See docs/Cloudflare-Workers.md for memory configuration details
241
339
  const taglib = await TagLib.initialize({
242
340
  memory: { initial: 8 * 1024 * 1024 }, // 8MB for Workers
243
341
  });
@@ -287,69 +385,79 @@ export default {
287
385
 
288
386
  `tag-wasm` is designed to support all formats supported by TagLib:
289
387
 
290
- - ✅ **.m4a (.mp4)** – Standard MPEG-4/AAC metadata for AAC and Apple Lossless audio
388
+ - ✅ **.m4a (.mp4)** – Standard MPEG-4/AAC metadata for AAC and Apple Lossless
389
+ audio
291
390
  - ✅ **.mp3** – ID3v2 and ID3v1 tags
292
391
  - ✅ **.flac** – Vorbis comments and audio properties
293
392
  - ✅ **.wav** – INFO chunk metadata
294
- - ✅ **Legacy formats**: Opus, APE, MPC, WavPack, TrueAudio, and more
393
+ - ✅ **Legacy formats** Opus, APE, MPC, WavPack, TrueAudio, and more
295
394
 
296
- ## 🎯 Automatic Tag Mapping
395
+ ## 🎯 Extended Metadata with PropertyMap
297
396
 
298
- `taglib-wasm` supports **automatic tag mapping** so you don’t have to worry about how the same tag is stored differently in different audio container formats.
397
+ `taglib-wasm` provides a **PropertyMap API** for accessing extended metadata
398
+ beyond the basic tags. This allows you to read and write format-specific fields
399
+ and custom metadata.
299
400
 
300
401
  ### AcoustID example
301
402
 
302
403
  ```typescript
303
- // Single API works for ALL formats (MP3, FLAC, OGG, MP4)
304
- file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
305
- file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
306
-
307
- // Automatically stores in format-specific locations:
308
- // • MP3: TXXX frames with proper descriptions
309
- // FLAC/OGG: ACOUSTID_FINGERPRINT and ACOUSTID_ID Vorbis comments
310
- // • MP4: ----:com.apple.iTunes:Acoustid... freeform atoms
404
+ import { Tags } from "taglib-wasm";
405
+
406
+ // Using PropertyMap API to set extended metadata with tag constants
407
+ file.setProperty(Tags.AcoustidFingerprint, "AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
408
+ file.setProperty(Tags.AcoustidId, "e7359e88-f1f7-41ed-b9f6-16e58e906997");
409
+
410
+ // Or using string property names
411
+ file.setProperty("ACOUSTID_FINGERPRINT", "AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
412
+
413
+ // Note: Property keys may vary by format
414
+ // Use file.properties() to see all available properties
415
+ file.save(); // Don't forget to save!
311
416
  ```
312
417
 
313
418
  ### MusicBrainz example
314
419
 
315
420
  ```typescript
316
- // Professional music database integration
317
- file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
318
- file.setMusicBrainzReleaseId("a1b2c3d4-e5f6-7890-abcd-ef1234567890");
319
- file.setMusicBrainzArtistId("12345678-90ab-cdef-1234-567890abcdef");
421
+ // MusicBrainz metadata using PropertyMap with tag constants
422
+ file.setProperty(Tags.MusicBrainzTrackId, "f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
423
+ file.setProperty(Tags.MusicBrainzAlbumId, "a1b2c3d4-e5f6-7890-abcd-ef1234567890");
424
+ file.setProperty(
425
+ Tags.MusicBrainzArtistId,
426
+ "12345678-90ab-cdef-1234-567890abcdef",
427
+ );
320
428
  ```
321
429
 
322
430
  ### Volume example
323
431
 
324
432
  ```typescript
325
- // ReplayGain support (automatic format mapping)
326
- file.setReplayGainTrackGain("-6.54 dB");
327
- file.setReplayGainTrackPeak("0.987654");
328
- file.setReplayGainAlbumGain("-8.12 dB");
329
- file.setReplayGainAlbumPeak("0.995432");
330
-
331
- // Apple Sound Check support
332
- file.setAppleSoundCheck("00000150 00000150 00000150 00000150...");
433
+ // ReplayGain volume normalization with tag constants
434
+ file.setProperty(Tags.TrackGain, "-6.54 dB");
435
+ file.setProperty(Tags.TrackPeak, "0.987654");
436
+ file.setProperty(Tags.AlbumGain, "-8.12 dB");
437
+ file.setProperty(Tags.AlbumPeak, "0.995432");
333
438
  ```
334
439
 
335
440
  ### Extended fields
336
441
 
337
442
  ```typescript
338
- // Advanced metadata fields
339
- file.setExtendedTag({
340
- albumArtist: "Various Artists",
341
- composer: "Composer Name",
342
- bpm: 120,
343
- compilation: true,
344
- discNumber: 1,
345
- totalTracks: 12,
346
- // Volume normalization
347
- replayGainTrackGain: "-6.54 dB",
348
- appleSoundCheck: "00000150...",
443
+ // Using PropertyMap to set multiple properties at once
444
+ const properties = file.properties(); // Get current properties
445
+
446
+ // Set extended metadata with tag constants
447
+ file.setProperties({
448
+ [Tags.AlbumArtist]: ["Various Artists"],
449
+ [Tags.Composer]: ["Composer Name"],
450
+ [Tags.Bpm]: ["120"],
451
+ [Tags.Compilation]: ["1"],
452
+ [Tags.DiscNumber]: ["1"],
453
+ [Tags.TrackTotal]: ["12"],
454
+ // Note: Property keys vary by format
349
455
  });
350
- ```
351
456
 
352
- **📖 See [docs/Automatic-Tag-Mapping.md](docs/Automatic-Tag-Mapping.md) for complete documentation**
457
+ // Or set individual properties
458
+ file.setProperty(Tags.AlbumArtist, "Various Artists");
459
+ file.setProperty(Tags.Composer, "Composer Name");
460
+ ```
353
461
 
354
462
  ## 🏗️ Development
355
463
 
@@ -384,8 +492,7 @@ build/
384
492
  ├── taglib.js # Generated Emscripten JavaScript
385
493
  └── taglib.wasm # Compiled WebAssembly module
386
494
 
387
- tests/ # Test files and sample audio files
388
- tests/ # Test suite
495
+ tests/ # Test suite and sample audio files
389
496
  examples/ # Usage examples for different runtimes
390
497
  ├── deno/ # Deno-specific examples
391
498
  ├── bun/ # Bun-specific examples
@@ -412,23 +519,29 @@ npm test
412
519
  # ✅ MP3 - ID3v1/v2 tag support
413
520
  # ✅ FLAC - Vorbis comments and properties
414
521
  # ✅ OGG - Vorbis comments
415
- # ✅ M4A - iTunes-compatible metadata atoms
522
+ # ✅ M4A - MPEG-4 (AAC and Apple Lossless) metadata
416
523
  ```
417
524
 
418
525
  ## 🔧 Technical Implementation
419
526
 
420
527
  ### Key architecture decisions
421
528
 
422
- 1. **Memory Management**: Uses Emscripten's `allocate()` for reliable JS↔WASM data transfer
423
- 2. **Buffer-Based Processing**: `TagLib::ByteVectorStream` enables in-memory file processing
529
+ 1. **Memory Management**: Uses Emscripten's `allocate()` for reliable JS↔WASM
530
+ data transfer
531
+ 2. **Buffer-Based Processing**: `TagLib::ByteVectorStream` enables in-memory
532
+ file processing
424
533
  3. **C++ Wrapper**: Custom C functions bridge TagLib's C++ API to WASM exports
425
- 4. **Type Safety**: Complete TypeScript definitions for all audio formats and metadata
534
+ 4. **Type Safety**: Complete TypeScript definitions for all audio formats and
535
+ metadata
426
536
 
427
537
  ### Critical implementation details
428
538
 
429
- - **ByteVectorStream**: Enables processing audio files from memory buffers without filesystem
430
- - **ID-based Object Management**: C++ objects managed via integer IDs for memory safety
431
- - **Emscripten allocate()**: Ensures proper memory synchronization between JS and WASM
539
+ - **ByteVectorStream**: Enables processing audio files from memory buffers
540
+ without filesystem
541
+ - **ID-based Object Management**: C++ objects managed via integer IDs for memory
542
+ safety
543
+ - **Emscripten allocate()**: Ensures proper memory synchronization between JS
544
+ and WASM
432
545
  - **UTF-8 String Handling**: Proper encoding for international metadata
433
546
 
434
547
  ## 📚 API Reference
@@ -449,98 +562,101 @@ class TagLib {
449
562
  class AudioFile {
450
563
  // Validation
451
564
  isValid(): boolean;
452
- format(): string;
565
+ getFormat(): string;
453
566
 
454
567
  // Properties
455
568
  audioProperties(): AudioProperties;
456
- tag(): TagData;
457
569
 
458
- // Tag Writing
459
- setTitle(title: string): void;
460
- setArtist(artist: string): void;
461
- setAlbum(album: string): void;
462
- setComment(comment: string): void;
463
- setGenre(genre: string): void;
464
- setYear(year: number): void;
465
- setTrack(track: number): void;
570
+ // Tag Access (returns Tag object with getters and setters)
571
+ tag(): Tag;
572
+
573
+ // PropertyMap API for extended metadata
574
+ properties(): PropertyMap;
575
+ setProperties(properties: PropertyMap): void;
576
+ getProperty(key: string): string | undefined;
577
+ setProperty(key: string, value: string): void;
578
+
579
+ // MP4-specific methods
580
+ isMP4(): boolean;
581
+ getMP4Item(key: string): string | undefined;
582
+ setMP4Item(key: string, value: string): void;
583
+ removeMP4Item(key: string): void;
466
584
 
467
585
  // File Operations
468
586
  save(): boolean;
587
+ getFileBuffer(): Uint8Array;
469
588
  dispose(): void;
470
-
471
- // Automatic Tag Mapping (Format-Agnostic)
472
- extendedTag(): ExtendedTag;
473
- setExtendedTag(tag: Partial<ExtendedTag>): void;
474
-
475
- // AcoustID Integration
476
- setAcoustidFingerprint(fingerprint: string): void;
477
- getAcoustidFingerprint(): string | undefined;
478
- setAcoustidId(id: string): void;
479
- getAcoustidId(): string | undefined;
480
-
481
- // MusicBrainz Integration
482
- setMusicBrainzTrackId(id: string): void;
483
- getMusicBrainzTrackId(): string | undefined;
484
-
485
- // Volume Normalization
486
- setReplayGainTrackGain(gain: string): void;
487
- getReplayGainTrackGain(): string | undefined;
488
- setReplayGainTrackPeak(peak: string): void;
489
- getReplayGainTrackPeak(): string | undefined;
490
- setReplayGainAlbumGain(gain: string): void;
491
- getReplayGainAlbumGain(): string | undefined;
492
- setReplayGainAlbumPeak(peak: string): void;
493
- getReplayGainAlbumPeak(): string | undefined;
494
- setAppleSoundCheck(iTunNORM: string): void;
495
- getAppleSoundCheck(): string | undefined;
496
589
  }
497
590
  ```
498
591
 
499
- ## 🎛️ Configuration
592
+ ### Tag interface
500
593
 
501
594
  ```typescript
502
- interface TagLibConfig {
503
- memory?: {
504
- initial?: number; // Initial memory size (default: 16MB)
505
- maximum?: number; // Maximum memory size (default: 256MB)
506
- };
507
- debug?: boolean; // Enable debug output
595
+ interface Tag {
596
+ // Basic metadata (getters)
597
+ title: string;
598
+ artist: string;
599
+ album: string;
600
+ comment: string;
601
+ genre: string;
602
+ year: number;
603
+ track: number;
604
+
605
+ // Setters
606
+ setTitle(value: string): void;
607
+ setArtist(value: string): void;
608
+ setAlbum(value: string): void;
609
+ setComment(value: string): void;
610
+ setGenre(value: string): void;
611
+ setYear(value: number): void;
612
+ setTrack(value: number): void;
508
613
  }
509
614
  ```
510
615
 
616
+ ### PropertyMap type
617
+
618
+ ```typescript
619
+ type PropertyMap = { [key: string]: string[] };
620
+ ```
621
+
622
+ ## 📖 Additional Documentation
623
+
624
+ - [**Tag Name Constants**](docs/Tag-Name-Constants.md) - Comprehensive reference for standard tag names and cross-format mapping
625
+ - [**Automatic Tag Mapping**](docs/Automatic-Tag-Mapping.md) - How taglib-wasm handles format-specific tag differences
626
+ - [**Implementation Details**](docs/Implementation.md) - Technical details about the Wasm implementation
627
+ - [**Runtime Compatibility**](docs/Runtime-Compatibility.md) - Platform-specific setup and considerations
628
+
511
629
  ## 🌐 Runtime Compatibility
512
630
 
513
- `taglib-wasm` works seamlessly across all major JavaScript runtimes:
631
+ `taglib-wasm` works across all major JavaScript runtimes:
514
632
 
515
- | Runtime | Status | Installation | Performance | TypeScript |
516
- | ----------- | ------- | --------------------------------- | ----------- | ---------- |
517
- | **Deno** | ✅ Full | `jsr:@charleswiltgen/taglib-wasm` | Excellent | Native |
518
- | **Bun** | ✅ Full | `bun add taglib-wasm` | Excellent | Native |
519
- | **Node.js** | ✅ Full | `npm install taglib-wasm` | Good | Via loader |
520
- | **Browser** | ✅ Full | CDN/bundler | Good | Via build |
633
+ | Runtime | Status | Installation | Performance | TypeScript |
634
+ | ----------- | ------- | ------------------------- | ----------- | ---------- |
635
+ | **Deno** | ✅ Full | `npm:taglib-wasm` | Excellent | Native |
636
+ | **Bun** | ✅ Full | `bun add taglib-wasm` | Excellent | Native |
637
+ | **Node.js** | ✅ Full | `npm install taglib-wasm` | Good | Native/tsx |
638
+ | **Browser** | ✅ Full | CDN/bundler | Good | Via build |
521
639
 
522
- **📖 See [docs/Runtime-Compatibility.md](docs/Runtime-Compatibility.md) for detailed runtime information**
640
+ **📖 See [docs/Runtime-Compatibility.md](docs/Runtime-Compatibility.md) for
641
+ detailed runtime information**
523
642
 
524
643
  ## 🚧 Known Limitations
525
644
 
526
- - **File Writing**: Saves only affect in-memory representation (no filesystem persistence)
527
- - **Large Files**: Memory usage scales with file size (entire file loaded into memory)
528
- - **Concurrent Access**: Not thread-safe (JavaScript single-threaded nature)
645
+ - **File Writing** Saves only affect in-memory representation (no filesystem
646
+ persistence)
647
+ - **Large Files** Memory usage scales with file size (entire file loaded into
648
+ memory)
649
+ - **Concurrent Access** – Not thread-safe (JavaScript single-threaded nature)
529
650
 
530
651
  ## 🤝 Contributing
531
652
 
532
- Contributions welcome! Areas of interest:
533
-
534
- - Additional format support (DSF, DSDIFF, etc.)
535
- - Advanced metadata implementation (PropertyMap integration)
536
- - Performance optimizations
537
- - Runtime-specific optimizations
538
- - Documentation improvements
653
+ Contributions welcome!
539
654
 
540
655
  ## 📄 License
541
656
 
542
657
  - **This project**: MIT License (see [LICENSE](LICENSE))
543
- - **TagLib library**: LGPL/MPL dual license (see [lib/taglib/COPYING.LGPL](lib/taglib/COPYING.LGPL))
658
+ - **TagLib library**: LGPL/MPL dual license (see
659
+ [lib/taglib/COPYING.LGPL](lib/taglib/COPYING.LGPL))
544
660
 
545
661
  ## 🙏 Acknowledgments
546
662