taglib-wasm 0.2.7 → 0.3.1
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 +155 -149
- package/build/taglib.js +4 -10
- package/build/taglib.wasm +0 -0
- package/index.ts +17 -3
- package/package.json +9 -9
- package/src/mod.ts +14 -3
- package/src/simple.ts +21 -25
- package/src/taglib.ts +179 -496
- package/src/types.ts +6 -3
- package/src/wasm-workers.ts +9 -1
- package/src/wasm.ts +105 -244
- package/src/workers.ts +50 -29
- package/src/enhanced-api.ts +0 -296
- package/src/simple-jsr.ts +0 -201
- package/src/taglib-embind.ts +0 -231
- package/src/taglib-jsr.ts +0 -544
- package/src/wasm-embind.ts +0 -55
- package/src/wasm-jsr.ts +0 -280
package/README.md
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
# taglib-wasm
|
|
2
2
|
|
|
3
|
-
[TagLib](https://taglib.org/)
|
|
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
4
|
|
|
5
|
-
`taglib-wasm`
|
|
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
6
|
|
|
7
|
-
|
|
8
|
-
> This project is a baby, and you’re likely to experience some surprises at this stage of its development. I’m extremely moditivated to help address them, though.
|
|
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.
|
|
9
8
|
|
|
10
|
-
## Why?
|
|
9
|
+
## 🤔 Why?
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
[`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.
|
|
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.
|
|
15
12
|
|
|
16
13
|
## 🎯 Features
|
|
17
14
|
|
|
@@ -29,7 +26,7 @@ In the process of building a utility to improve the metadata of my music collect
|
|
|
29
26
|
### Deno
|
|
30
27
|
|
|
31
28
|
```typescript
|
|
32
|
-
import { TagLib } from "
|
|
29
|
+
import { TagLib } from "npm:taglib-wasm";
|
|
33
30
|
```
|
|
34
31
|
|
|
35
32
|
### Node.js
|
|
@@ -38,6 +35,13 @@ import { TagLib } from "jsr:@charleswiltgen/taglib-wasm";
|
|
|
38
35
|
npm install taglib-wasm
|
|
39
36
|
```
|
|
40
37
|
|
|
38
|
+
**Note:** The NPM package ships TypeScript source files. Use a TypeScript loader like [`tsx`](https://github.com/privatenumber/tsx):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install --save-dev tsx
|
|
42
|
+
npx tsx your-script.ts
|
|
43
|
+
```
|
|
44
|
+
|
|
41
45
|
### Bun
|
|
42
46
|
|
|
43
47
|
```bash
|
|
@@ -74,13 +78,13 @@ console.log(`Duration: ${props.length}s, Bitrate: ${props.bitrate} kbps`);
|
|
|
74
78
|
Full control when you need it:
|
|
75
79
|
|
|
76
80
|
```typescript
|
|
77
|
-
import { TagLib } from "
|
|
81
|
+
import { TagLib } from "taglib-wasm";
|
|
78
82
|
|
|
79
83
|
// Initialize taglib-wasm
|
|
80
84
|
const taglib = await TagLib.initialize();
|
|
81
85
|
|
|
82
86
|
// Load audio file from buffer
|
|
83
|
-
const audioData = await
|
|
87
|
+
const audioData = await readFile("song.mp3"); // Node.js/Bun: fs.readFile, Deno: Deno.readFile
|
|
84
88
|
const file = taglib.openFile(audioData);
|
|
85
89
|
|
|
86
90
|
// Read metadata
|
|
@@ -93,16 +97,15 @@ console.log(`Duration: ${props.length}s`);
|
|
|
93
97
|
console.log(`Bitrate: ${props.bitrate} kbps`);
|
|
94
98
|
|
|
95
99
|
// Write metadata
|
|
96
|
-
file.
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
const tag = file.tag();
|
|
101
|
+
tag.setTitle("New Title");
|
|
102
|
+
tag.setArtist("New Artist");
|
|
103
|
+
tag.setAlbum("New Album");
|
|
99
104
|
|
|
100
|
-
|
|
105
|
+
// Save changes
|
|
106
|
+
file.save();
|
|
101
107
|
|
|
102
|
-
|
|
103
|
-
file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
|
|
104
|
-
file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
105
|
-
file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
|
|
108
|
+
console.log("Updated tags:", file.tag());
|
|
106
109
|
|
|
107
110
|
// Clean up
|
|
108
111
|
file.dispose();
|
|
@@ -110,16 +113,17 @@ file.dispose();
|
|
|
110
113
|
|
|
111
114
|
## Platform examples
|
|
112
115
|
|
|
113
|
-
###
|
|
116
|
+
### Node.js
|
|
114
117
|
|
|
115
118
|
```typescript
|
|
116
|
-
import { TagLib } from "
|
|
119
|
+
import { TagLib } from "taglib-wasm";
|
|
120
|
+
import { readFile } from "fs/promises";
|
|
117
121
|
|
|
118
122
|
// Initialize taglib-wasm
|
|
119
123
|
const taglib = await TagLib.initialize();
|
|
120
124
|
|
|
121
125
|
// Load audio file from filesystem
|
|
122
|
-
const audioData = await
|
|
126
|
+
const audioData = await readFile("song.mp3");
|
|
123
127
|
const file = taglib.openFile(audioData);
|
|
124
128
|
|
|
125
129
|
// Read metadata
|
|
@@ -132,33 +136,31 @@ console.log(`Duration: ${props.length}s`);
|
|
|
132
136
|
console.log(`Bitrate: ${props.bitrate} kbps`);
|
|
133
137
|
|
|
134
138
|
// Write metadata
|
|
135
|
-
file.
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
const tag = file.tag();
|
|
140
|
+
tag.setTitle("New Title");
|
|
141
|
+
tag.setArtist("New Artist");
|
|
142
|
+
tag.setAlbum("New Album");
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
// Save changes
|
|
145
|
+
file.save();
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
|
|
143
|
-
file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
144
|
-
file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
|
|
147
|
+
console.log("Updated tags:", file.tag());
|
|
145
148
|
|
|
146
149
|
// Clean up
|
|
147
150
|
file.dispose();
|
|
148
151
|
```
|
|
149
152
|
|
|
150
|
-
###
|
|
153
|
+
### Bun
|
|
151
154
|
|
|
152
155
|
```typescript
|
|
153
156
|
import { TagLib } from "taglib-wasm";
|
|
154
|
-
import { readFile } from "fs/promises";
|
|
155
157
|
|
|
156
158
|
// Initialize taglib-wasm
|
|
157
159
|
const taglib = await TagLib.initialize();
|
|
158
160
|
|
|
159
|
-
// Load
|
|
160
|
-
const audioData = await
|
|
161
|
-
const file = taglib.openFile(audioData);
|
|
161
|
+
// Load from file system (Bun's native file API)
|
|
162
|
+
const audioData = await Bun.file("song.mp3").arrayBuffer();
|
|
163
|
+
const file = taglib.openFile(new Uint8Array(audioData));
|
|
162
164
|
|
|
163
165
|
// Read metadata
|
|
164
166
|
const tags = file.tag();
|
|
@@ -170,22 +172,21 @@ console.log(`Duration: ${props.length}s`);
|
|
|
170
172
|
console.log(`Bitrate: ${props.bitrate} kbps`);
|
|
171
173
|
|
|
172
174
|
// Write metadata
|
|
173
|
-
file.
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
const tag = file.tag();
|
|
176
|
+
tag.setTitle("New Title");
|
|
177
|
+
tag.setArtist("New Artist");
|
|
178
|
+
tag.setAlbum("New Album");
|
|
176
179
|
|
|
177
|
-
|
|
180
|
+
// Save changes
|
|
181
|
+
file.save();
|
|
178
182
|
|
|
179
|
-
|
|
180
|
-
file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
|
|
181
|
-
file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
182
|
-
file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
|
|
183
|
+
console.log("Updated tags:", file.tag());
|
|
183
184
|
|
|
184
185
|
// Clean up
|
|
185
186
|
file.dispose();
|
|
186
187
|
```
|
|
187
188
|
|
|
188
|
-
###
|
|
189
|
+
### Browser
|
|
189
190
|
|
|
190
191
|
```typescript
|
|
191
192
|
import { TagLib } from "taglib-wasm";
|
|
@@ -193,9 +194,11 @@ import { TagLib } from "taglib-wasm";
|
|
|
193
194
|
// Initialize taglib-wasm
|
|
194
195
|
const taglib = await TagLib.initialize();
|
|
195
196
|
|
|
196
|
-
// Load from file
|
|
197
|
-
const
|
|
198
|
-
const
|
|
197
|
+
// Load from file input or fetch
|
|
198
|
+
const fileInput = document.querySelector('input[type="file"]');
|
|
199
|
+
const audioFile = fileInput.files[0];
|
|
200
|
+
const audioData = new Uint8Array(await audioFile.arrayBuffer());
|
|
201
|
+
const file = taglib.openFile(audioData);
|
|
199
202
|
|
|
200
203
|
// Read metadata
|
|
201
204
|
const tags = file.tag();
|
|
@@ -207,33 +210,30 @@ console.log(`Duration: ${props.length}s`);
|
|
|
207
210
|
console.log(`Bitrate: ${props.bitrate} kbps`);
|
|
208
211
|
|
|
209
212
|
// Write metadata
|
|
210
|
-
file.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
+
const tag = file.tag();
|
|
214
|
+
tag.setTitle("New Title");
|
|
215
|
+
tag.setArtist("New Artist");
|
|
216
|
+
tag.setAlbum("New Album");
|
|
213
217
|
|
|
214
|
-
|
|
218
|
+
// Save changes
|
|
219
|
+
file.save();
|
|
215
220
|
|
|
216
|
-
|
|
217
|
-
file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
|
|
218
|
-
file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
219
|
-
file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
|
|
221
|
+
console.log("Updated tags:", file.tag());
|
|
220
222
|
|
|
221
223
|
// Clean up
|
|
222
224
|
file.dispose();
|
|
223
225
|
```
|
|
224
226
|
|
|
225
|
-
###
|
|
227
|
+
### Deno
|
|
226
228
|
|
|
227
229
|
```typescript
|
|
228
|
-
import { TagLib } from "taglib-wasm";
|
|
230
|
+
import { TagLib } from "npm:taglib-wasm";
|
|
229
231
|
|
|
230
232
|
// Initialize taglib-wasm
|
|
231
233
|
const taglib = await TagLib.initialize();
|
|
232
234
|
|
|
233
|
-
// Load
|
|
234
|
-
const
|
|
235
|
-
const audioFile = fileInput.files[0];
|
|
236
|
-
const audioData = new Uint8Array(await audioFile.arrayBuffer());
|
|
235
|
+
// Load audio file from filesystem
|
|
236
|
+
const audioData = await Deno.readFile("song.mp3");
|
|
237
237
|
const file = taglib.openFile(audioData);
|
|
238
238
|
|
|
239
239
|
// Read metadata
|
|
@@ -246,16 +246,15 @@ console.log(`Duration: ${props.length}s`);
|
|
|
246
246
|
console.log(`Bitrate: ${props.bitrate} kbps`);
|
|
247
247
|
|
|
248
248
|
// Write metadata
|
|
249
|
-
file.
|
|
250
|
-
|
|
251
|
-
|
|
249
|
+
const tag = file.tag();
|
|
250
|
+
tag.setTitle("New Title");
|
|
251
|
+
tag.setArtist("New Artist");
|
|
252
|
+
tag.setAlbum("New Album");
|
|
252
253
|
|
|
253
|
-
|
|
254
|
+
// Save changes
|
|
255
|
+
file.save();
|
|
254
256
|
|
|
255
|
-
|
|
256
|
-
file.setAcoustidFingerprint("AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
|
|
257
|
-
file.setAcoustidId("e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
258
|
-
file.setMusicBrainzTrackId("f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
|
|
257
|
+
console.log("Updated tags:", file.tag());
|
|
259
258
|
|
|
260
259
|
// Clean up
|
|
261
260
|
file.dispose();
|
|
@@ -318,72 +317,70 @@ export default {
|
|
|
318
317
|
|
|
319
318
|
## 📋 Supported Formats
|
|
320
319
|
|
|
321
|
-
|
|
320
|
+
`tag-wasm` is designed to support all formats supported by TagLib:
|
|
322
321
|
|
|
323
|
-
- ✅ **
|
|
324
|
-
- ✅ **
|
|
325
|
-
- ✅ **
|
|
326
|
-
- ✅ **
|
|
327
|
-
- ✅ **
|
|
328
|
-
- 🔄 **Additional formats**: Opus, APE, MPC, WavPack, TrueAudio, and more
|
|
322
|
+
- ✅ **.m4a (.mp4)** – Standard MPEG-4/AAC metadata for AAC and Apple Lossless audio
|
|
323
|
+
- ✅ **.mp3** – ID3v2 and ID3v1 tags
|
|
324
|
+
- ✅ **.flac** – Vorbis comments and audio properties
|
|
325
|
+
- ✅ **.wav** – INFO chunk metadata
|
|
326
|
+
- ✅ **Legacy formats**: Opus, APE, MPC, WavPack, TrueAudio, and more
|
|
329
327
|
|
|
330
|
-
## 🎯
|
|
328
|
+
## 🎯 Extended Metadata with PropertyMap
|
|
331
329
|
|
|
332
|
-
`taglib-wasm`
|
|
330
|
+
`taglib-wasm` provides a **PropertyMap API** for accessing extended metadata beyond the basic tags. This allows you to read and write format-specific fields and custom metadata.
|
|
333
331
|
|
|
334
332
|
### AcoustID example
|
|
335
333
|
|
|
336
334
|
```typescript
|
|
337
|
-
//
|
|
338
|
-
file.
|
|
339
|
-
file.
|
|
340
|
-
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
// • MP4: ----:com.apple.iTunes:Acoustid... freeform atoms
|
|
335
|
+
// Using PropertyMap API to set extended metadata
|
|
336
|
+
file.setProperty("ACOUSTID_FINGERPRINT", "AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
|
|
337
|
+
file.setProperty("ACOUSTID_ID", "e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
338
|
+
|
|
339
|
+
// Note: Property keys may vary by format
|
|
340
|
+
// Use file.properties() to see all available properties
|
|
341
|
+
file.save(); // Don't forget to save!
|
|
345
342
|
```
|
|
346
343
|
|
|
347
344
|
### MusicBrainz example
|
|
348
345
|
|
|
349
346
|
```typescript
|
|
350
|
-
//
|
|
351
|
-
file.
|
|
352
|
-
file.
|
|
353
|
-
file.
|
|
347
|
+
// MusicBrainz metadata using PropertyMap
|
|
348
|
+
file.setProperty("MUSICBRAINZ_TRACKID", "f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab");
|
|
349
|
+
file.setProperty("MUSICBRAINZ_ALBUMID", "a1b2c3d4-e5f6-7890-abcd-ef1234567890");
|
|
350
|
+
file.setProperty("MUSICBRAINZ_ARTISTID", "12345678-90ab-cdef-1234-567890abcdef");
|
|
354
351
|
```
|
|
355
352
|
|
|
356
353
|
### Volume example
|
|
357
354
|
|
|
358
355
|
```typescript
|
|
359
|
-
// ReplayGain
|
|
360
|
-
file.
|
|
361
|
-
file.
|
|
362
|
-
file.
|
|
363
|
-
file.
|
|
364
|
-
|
|
365
|
-
// Apple Sound Check support
|
|
366
|
-
file.setAppleSoundCheck("00000150 00000150 00000150 00000150...");
|
|
356
|
+
// ReplayGain volume normalization
|
|
357
|
+
file.setProperty("REPLAYGAIN_TRACK_GAIN", "-6.54 dB");
|
|
358
|
+
file.setProperty("REPLAYGAIN_TRACK_PEAK", "0.987654");
|
|
359
|
+
file.setProperty("REPLAYGAIN_ALBUM_GAIN", "-8.12 dB");
|
|
360
|
+
file.setProperty("REPLAYGAIN_ALBUM_PEAK", "0.995432");
|
|
367
361
|
```
|
|
368
362
|
|
|
369
363
|
### Extended fields
|
|
370
364
|
|
|
371
365
|
```typescript
|
|
372
|
-
//
|
|
373
|
-
file.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
366
|
+
// Using PropertyMap to set multiple properties at once
|
|
367
|
+
const properties = file.properties(); // Get current properties
|
|
368
|
+
|
|
369
|
+
// Set extended metadata
|
|
370
|
+
file.setProperties({
|
|
371
|
+
ALBUMARTIST: ["Various Artists"],
|
|
372
|
+
COMPOSER: ["Composer Name"],
|
|
373
|
+
BPM: ["120"],
|
|
374
|
+
COMPILATION: ["1"],
|
|
375
|
+
DISCNUMBER: ["1"],
|
|
376
|
+
TRACKTOTAL: ["12"],
|
|
377
|
+
// Note: Property keys vary by format
|
|
383
378
|
});
|
|
384
|
-
```
|
|
385
379
|
|
|
386
|
-
|
|
380
|
+
// Or set individual properties
|
|
381
|
+
file.setProperty("ALBUMARTIST", "Various Artists");
|
|
382
|
+
file.setProperty("COMPOSER", "Composer Name");
|
|
383
|
+
```
|
|
387
384
|
|
|
388
385
|
## 🏗️ Development
|
|
389
386
|
|
|
@@ -418,8 +415,7 @@ build/
|
|
|
418
415
|
├── taglib.js # Generated Emscripten JavaScript
|
|
419
416
|
└── taglib.wasm # Compiled WebAssembly module
|
|
420
417
|
|
|
421
|
-
tests/ # Test
|
|
422
|
-
tests/ # Test suite
|
|
418
|
+
tests/ # Test suite and sample audio files
|
|
423
419
|
examples/ # Usage examples for different runtimes
|
|
424
420
|
├── deno/ # Deno-specific examples
|
|
425
421
|
├── bun/ # Bun-specific examples
|
|
@@ -483,53 +479,63 @@ class TagLib {
|
|
|
483
479
|
class AudioFile {
|
|
484
480
|
// Validation
|
|
485
481
|
isValid(): boolean;
|
|
486
|
-
|
|
482
|
+
getFormat(): string;
|
|
487
483
|
|
|
488
484
|
// Properties
|
|
489
485
|
audioProperties(): AudioProperties;
|
|
490
|
-
tag(): TagData;
|
|
491
486
|
|
|
492
|
-
// Tag
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
487
|
+
// Tag Access (returns Tag object with getters and setters)
|
|
488
|
+
tag(): Tag;
|
|
489
|
+
|
|
490
|
+
// PropertyMap API for extended metadata
|
|
491
|
+
properties(): PropertyMap;
|
|
492
|
+
setProperties(properties: PropertyMap): void;
|
|
493
|
+
getProperty(key: string): string | undefined;
|
|
494
|
+
setProperty(key: string, value: string): void;
|
|
495
|
+
|
|
496
|
+
// MP4-specific methods
|
|
497
|
+
isMP4(): boolean;
|
|
498
|
+
getMP4Item(key: string): string | undefined;
|
|
499
|
+
setMP4Item(key: string, value: string): void;
|
|
500
|
+
removeMP4Item(key: string): void;
|
|
500
501
|
|
|
501
502
|
// File Operations
|
|
502
503
|
save(): boolean;
|
|
504
|
+
getFileBuffer(): Uint8Array;
|
|
503
505
|
dispose(): void;
|
|
506
|
+
}
|
|
507
|
+
```
|
|
504
508
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
//
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
setReplayGainAlbumPeak(peak: string): void;
|
|
527
|
-
getReplayGainAlbumPeak(): string | undefined;
|
|
528
|
-
setAppleSoundCheck(iTunNORM: string): void;
|
|
529
|
-
getAppleSoundCheck(): string | undefined;
|
|
509
|
+
### Tag interface
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
interface Tag {
|
|
513
|
+
// Basic metadata (getters)
|
|
514
|
+
title: string;
|
|
515
|
+
artist: string;
|
|
516
|
+
album: string;
|
|
517
|
+
comment: string;
|
|
518
|
+
genre: string;
|
|
519
|
+
year: number;
|
|
520
|
+
track: number;
|
|
521
|
+
|
|
522
|
+
// Setters
|
|
523
|
+
setTitle(value: string): void;
|
|
524
|
+
setArtist(value: string): void;
|
|
525
|
+
setAlbum(value: string): void;
|
|
526
|
+
setComment(value: string): void;
|
|
527
|
+
setGenre(value: string): void;
|
|
528
|
+
setYear(value: number): void;
|
|
529
|
+
setTrack(value: number): void;
|
|
530
530
|
}
|
|
531
531
|
```
|
|
532
532
|
|
|
533
|
+
### PropertyMap type
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
type PropertyMap = { [key: string]: string[] };
|
|
537
|
+
```
|
|
538
|
+
|
|
533
539
|
## 🎛️ Configuration
|
|
534
540
|
|
|
535
541
|
```typescript
|
|
@@ -548,7 +554,7 @@ interface TagLibConfig {
|
|
|
548
554
|
|
|
549
555
|
| Runtime | Status | Installation | Performance | TypeScript |
|
|
550
556
|
| ----------- | ------- | --------------------------------- | ----------- | ---------- |
|
|
551
|
-
| **Deno** | ✅ Full | `
|
|
557
|
+
| **Deno** | ✅ Full | `npm:taglib-wasm` | Excellent | Native |
|
|
552
558
|
| **Bun** | ✅ Full | `bun add taglib-wasm` | Excellent | Native |
|
|
553
559
|
| **Node.js** | ✅ Full | `npm install taglib-wasm` | Good | Via loader |
|
|
554
560
|
| **Browser** | ✅ Full | CDN/bundler | Good | Via build |
|