taglib-wasm 0.3.1 → 0.3.3
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 +190 -97
- package/build/taglib.js +2401 -8
- package/index.ts +96 -4
- package/package.json +4 -1
- package/src/constants.ts +227 -0
- package/src/mod.ts +6 -6
- package/src/simple.ts +105 -70
- package/src/taglib.ts +246 -70
- package/src/types.ts +166 -17
- package/src/wasm-workers.ts +8 -8
- package/src/wasm.ts +21 -12
- package/src/workers.ts +111 -31
package/README.md
CHANGED
|
@@ -1,25 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# TagLib-Wasm
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> TagLib for TypeScript platforms: Deno, Node.js, Bun, browsers, and Cloudflare
|
|
4
|
+
> Workers
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
This is the Wasm version of [**TagLib**](https://taglib.org/), the most robust,
|
|
7
|
+
de-facto standard for reading and editing metadata tags (Title, Album, Artist,
|
|
8
|
+
etc.) in all popular audio formats. `taglib-wasm` exists because the
|
|
9
|
+
JavaScipt/TypeScipt ecosystem had no battle-tested audio tagging library that
|
|
10
|
+
supports reading and writing music metadata to all popular audio formats — until
|
|
11
|
+
now!
|
|
6
12
|
|
|
7
|
-
`taglib-wasm`
|
|
13
|
+
`taglib-wasm` stands on the shoulders of giants, including
|
|
14
|
+
[TagLib](https://taglib.org/) itself, [Emscripten](https://emscripten.org/), and
|
|
15
|
+
[Wasm](https://webassembly.org/) ([WebAssembly](https://webassembly.org/)).
|
|
16
|
+
|
|
17
|
+
`taglib-wasm` aspires to be a universal solution for **JavaScript/TypeScript**
|
|
18
|
+
platforms — Deno, Node.js, Bun, web browsers, and Cloudflare Workers. Note: This
|
|
19
|
+
project is a baby, and you’re likely to experience some surprises at this stage
|
|
20
|
+
of its development. I’m extremely motivated to help address them, since I’ll
|
|
21
|
+
also be depending on this project.
|
|
8
22
|
|
|
9
23
|
## 🤔 Why?
|
|
10
24
|
|
|
11
|
-
Because there’s nothing like it. [`mp3tag.js`](https://mp3tag.js.org/) is mature
|
|
25
|
+
Because there’s nothing like it. [`mp3tag.js`](https://mp3tag.js.org/) is mature
|
|
26
|
+
and active, but only supports MP3 files and ID3 tags. TagLib was an ideal choice
|
|
27
|
+
from a maturity and capabilities point of view, but wrappers like `node-taglib`
|
|
28
|
+
appeared to be dormant, and I wanted to avoid making users install
|
|
29
|
+
platform-specific dependencies whenever possible.
|
|
12
30
|
|
|
13
31
|
## 🎯 Features
|
|
14
32
|
|
|
15
|
-
- **✅ Universal compatibility** – Works with Deno, Node.js, Bun, web browsers,
|
|
33
|
+
- **✅ Universal compatibility** – Works with Deno, Node.js, Bun, web browsers,
|
|
34
|
+
and Cloudflare Workers
|
|
16
35
|
- **✅ TypeScript first** – Complete type definitions and modern API
|
|
17
|
-
- **✅ Full audio format support** – Supports all audio formats supported by
|
|
18
|
-
|
|
19
|
-
- **✅
|
|
36
|
+
- **✅ Full audio format support** – Supports all audio formats supported by
|
|
37
|
+
TagLib
|
|
38
|
+
- **✅ Format abstraction** – `taglib-wasm` deals with how tags are read
|
|
39
|
+
from/written to in different file formats
|
|
40
|
+
- **✅ Zero dependencies** – Self-contained Wasm bundle
|
|
20
41
|
- **✅ Memory efficient** – In-memory processing without filesystem access
|
|
21
|
-
- **✅ Production ready** – Growing test suite helps ensure safety and
|
|
22
|
-
|
|
42
|
+
- **✅ Production ready** – Growing test suite helps ensure safety and
|
|
43
|
+
reliability
|
|
44
|
+
- **🆕 Two API styles** – Choose between Simple (3 functions) or Core (full
|
|
45
|
+
control) APIs
|
|
23
46
|
|
|
24
47
|
## 📦 Installation
|
|
25
48
|
|
|
@@ -35,7 +58,19 @@ import { TagLib } from "npm:taglib-wasm";
|
|
|
35
58
|
npm install taglib-wasm
|
|
36
59
|
```
|
|
37
60
|
|
|
38
|
-
|
|
61
|
+
The package uses TypeScript. You have two options:
|
|
62
|
+
|
|
63
|
+
#### Option 1: Use Node’s native TypeScript support
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Node.js 22.6.0+ with experimental flag
|
|
67
|
+
node --experimental-strip-types your-script.ts
|
|
68
|
+
|
|
69
|
+
# Node.js 23.6.0+ (no flag needed)
|
|
70
|
+
node your-script.ts
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### Option 2: TypeScript loader (recommended for production)
|
|
39
74
|
|
|
40
75
|
```bash
|
|
41
76
|
npm install --save-dev tsx
|
|
@@ -52,16 +87,17 @@ bun add taglib-wasm
|
|
|
52
87
|
|
|
53
88
|
### Simple API
|
|
54
89
|
|
|
55
|
-
|
|
90
|
+
This was inspired by [go-taglib](https://github.com/sentriz/go-taglib), a
|
|
91
|
+
similar project for Go created at about the same time.
|
|
56
92
|
|
|
57
93
|
```typescript
|
|
58
94
|
import { readProperties, readTags, writeTags } from "taglib-wasm/simple";
|
|
59
95
|
|
|
60
|
-
// Read tags
|
|
96
|
+
// Read tags
|
|
61
97
|
const tags = await readTags("song.mp3");
|
|
62
98
|
console.log(tags.title, tags.artist, tags.album);
|
|
63
99
|
|
|
64
|
-
// Write tags
|
|
100
|
+
// Write tags
|
|
65
101
|
await writeTags("song.mp3", {
|
|
66
102
|
title: "New Title",
|
|
67
103
|
artist: "New Artist",
|
|
@@ -75,7 +111,7 @@ console.log(`Duration: ${props.length}s, Bitrate: ${props.bitrate} kbps`);
|
|
|
75
111
|
|
|
76
112
|
### Core API
|
|
77
113
|
|
|
78
|
-
|
|
114
|
+
The Core API provides full control for more advanced applications.
|
|
79
115
|
|
|
80
116
|
```typescript
|
|
81
117
|
import { TagLib } from "taglib-wasm";
|
|
@@ -111,19 +147,51 @@ console.log("Updated tags:", file.tag());
|
|
|
111
147
|
file.dispose();
|
|
112
148
|
```
|
|
113
149
|
|
|
150
|
+
### Tag Constants
|
|
151
|
+
|
|
152
|
+
taglib-wasm provides type-safe tag constants with IDE autocomplete:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { Tags } from "taglib-wasm";
|
|
156
|
+
|
|
157
|
+
// Use constants for better type safety and autocomplete
|
|
158
|
+
const properties = file.properties();
|
|
159
|
+
|
|
160
|
+
// Read properties
|
|
161
|
+
const title = properties[Tags.Title]?.[0];
|
|
162
|
+
const albumArtist = properties[Tags.AlbumArtist]?.[0];
|
|
163
|
+
const musicBrainzId = properties[Tags.MusicBrainzArtistId]?.[0];
|
|
164
|
+
|
|
165
|
+
// Write properties
|
|
166
|
+
file.setProperties({
|
|
167
|
+
[Tags.Title]: ["My Song"],
|
|
168
|
+
[Tags.AlbumArtist]: ["Various Artists"],
|
|
169
|
+
[Tags.Bpm]: ["128"],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// All constants provide IDE autocomplete
|
|
173
|
+
Tags.Title; // → "TITLE"
|
|
174
|
+
Tags.Artist; // → "ARTIST"
|
|
175
|
+
Tags.AlbumArtist; // → "ALBUMARTIST"
|
|
176
|
+
Tags.TrackGain; // → "REPLAYGAIN_TRACK_GAIN"
|
|
177
|
+
// ... and many more
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
See [Tag Name Constants](docs/Tag-Name-Constants.md) for the complete list of
|
|
181
|
+
available tags and format-specific mappings.
|
|
182
|
+
|
|
114
183
|
## Platform examples
|
|
115
184
|
|
|
116
|
-
###
|
|
185
|
+
### Deno
|
|
117
186
|
|
|
118
187
|
```typescript
|
|
119
|
-
import { TagLib } from "taglib-wasm";
|
|
120
|
-
import { readFile } from "fs/promises";
|
|
188
|
+
import { TagLib } from "npm:taglib-wasm";
|
|
121
189
|
|
|
122
190
|
// Initialize taglib-wasm
|
|
123
191
|
const taglib = await TagLib.initialize();
|
|
124
192
|
|
|
125
193
|
// Load audio file from filesystem
|
|
126
|
-
const audioData = await readFile("song.mp3");
|
|
194
|
+
const audioData = await Deno.readFile("song.mp3");
|
|
127
195
|
const file = taglib.openFile(audioData);
|
|
128
196
|
|
|
129
197
|
// Read metadata
|
|
@@ -150,17 +218,18 @@ console.log("Updated tags:", file.tag());
|
|
|
150
218
|
file.dispose();
|
|
151
219
|
```
|
|
152
220
|
|
|
153
|
-
###
|
|
221
|
+
### Node.js
|
|
154
222
|
|
|
155
223
|
```typescript
|
|
156
224
|
import { TagLib } from "taglib-wasm";
|
|
225
|
+
import { readFile } from "fs/promises";
|
|
157
226
|
|
|
158
227
|
// Initialize taglib-wasm
|
|
159
228
|
const taglib = await TagLib.initialize();
|
|
160
229
|
|
|
161
|
-
// Load
|
|
162
|
-
const audioData = await
|
|
163
|
-
const file = taglib.openFile(
|
|
230
|
+
// Load audio file from filesystem
|
|
231
|
+
const audioData = await readFile("song.mp3");
|
|
232
|
+
const file = taglib.openFile(audioData);
|
|
164
233
|
|
|
165
234
|
// Read metadata
|
|
166
235
|
const tags = file.tag();
|
|
@@ -186,7 +255,7 @@ console.log("Updated tags:", file.tag());
|
|
|
186
255
|
file.dispose();
|
|
187
256
|
```
|
|
188
257
|
|
|
189
|
-
###
|
|
258
|
+
### Bun
|
|
190
259
|
|
|
191
260
|
```typescript
|
|
192
261
|
import { TagLib } from "taglib-wasm";
|
|
@@ -194,11 +263,9 @@ import { TagLib } from "taglib-wasm";
|
|
|
194
263
|
// Initialize taglib-wasm
|
|
195
264
|
const taglib = await TagLib.initialize();
|
|
196
265
|
|
|
197
|
-
// Load from file
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
const audioData = new Uint8Array(await audioFile.arrayBuffer());
|
|
201
|
-
const file = taglib.openFile(audioData);
|
|
266
|
+
// Load from file system (Bun's native file API)
|
|
267
|
+
const audioData = await Bun.file("song.mp3").arrayBuffer();
|
|
268
|
+
const file = taglib.openFile(new Uint8Array(audioData));
|
|
202
269
|
|
|
203
270
|
// Read metadata
|
|
204
271
|
const tags = file.tag();
|
|
@@ -224,16 +291,18 @@ console.log("Updated tags:", file.tag());
|
|
|
224
291
|
file.dispose();
|
|
225
292
|
```
|
|
226
293
|
|
|
227
|
-
###
|
|
294
|
+
### Browser
|
|
228
295
|
|
|
229
296
|
```typescript
|
|
230
|
-
import { TagLib } from "
|
|
297
|
+
import { TagLib } from "taglib-wasm";
|
|
231
298
|
|
|
232
299
|
// Initialize taglib-wasm
|
|
233
300
|
const taglib = await TagLib.initialize();
|
|
234
301
|
|
|
235
|
-
// Load
|
|
236
|
-
const
|
|
302
|
+
// Load from file input or fetch
|
|
303
|
+
const fileInput = document.querySelector('input[type="file"]');
|
|
304
|
+
const audioFile = fileInput.files[0];
|
|
305
|
+
const audioData = new Uint8Array(await audioFile.arrayBuffer());
|
|
237
306
|
const file = taglib.openFile(audioData);
|
|
238
307
|
|
|
239
308
|
// Read metadata
|
|
@@ -269,7 +338,8 @@ export default {
|
|
|
269
338
|
async fetch(request: Request): Promise<Response> {
|
|
270
339
|
if (request.method === "POST") {
|
|
271
340
|
try {
|
|
272
|
-
// Initialize taglib-wasm
|
|
341
|
+
// Initialize taglib-wasm with Workers-specific configuration
|
|
342
|
+
// See docs/Cloudflare-Workers.md for memory configuration details
|
|
273
343
|
const taglib = await TagLib.initialize({
|
|
274
344
|
memory: { initial: 8 * 1024 * 1024 }, // 8MB for Workers
|
|
275
345
|
});
|
|
@@ -319,22 +389,33 @@ export default {
|
|
|
319
389
|
|
|
320
390
|
`tag-wasm` is designed to support all formats supported by TagLib:
|
|
321
391
|
|
|
322
|
-
- ✅ **.m4a (.mp4)** – Standard MPEG-4/AAC metadata for AAC and Apple Lossless
|
|
392
|
+
- ✅ **.m4a (.mp4)** – Standard MPEG-4/AAC metadata for AAC and Apple Lossless
|
|
393
|
+
audio
|
|
323
394
|
- ✅ **.mp3** – ID3v2 and ID3v1 tags
|
|
324
395
|
- ✅ **.flac** – Vorbis comments and audio properties
|
|
325
396
|
- ✅ **.wav** – INFO chunk metadata
|
|
326
|
-
- ✅ **Legacy formats
|
|
397
|
+
- ✅ **Legacy formats** – Opus, APE, MPC, WavPack, TrueAudio, and more
|
|
327
398
|
|
|
328
399
|
## 🎯 Extended Metadata with PropertyMap
|
|
329
400
|
|
|
330
|
-
`taglib-wasm` provides a **PropertyMap API** for accessing extended metadata
|
|
401
|
+
`taglib-wasm` provides a **PropertyMap API** for accessing extended metadata
|
|
402
|
+
beyond the basic tags. This allows you to read and write format-specific fields
|
|
403
|
+
and custom metadata.
|
|
331
404
|
|
|
332
405
|
### AcoustID example
|
|
333
406
|
|
|
334
407
|
```typescript
|
|
335
|
-
|
|
408
|
+
import { Tags } from "taglib-wasm";
|
|
409
|
+
|
|
410
|
+
// Using PropertyMap API to set extended metadata with tag constants
|
|
411
|
+
file.setProperty(
|
|
412
|
+
Tags.AcoustidFingerprint,
|
|
413
|
+
"AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...",
|
|
414
|
+
);
|
|
415
|
+
file.setProperty(Tags.AcoustidId, "e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
416
|
+
|
|
417
|
+
// Or using string property names
|
|
336
418
|
file.setProperty("ACOUSTID_FINGERPRINT", "AQADtMmybfGO8NCNEESLnzHyXNOHeHnG...");
|
|
337
|
-
file.setProperty("ACOUSTID_ID", "e7359e88-f1f7-41ed-b9f6-16e58e906997");
|
|
338
419
|
|
|
339
420
|
// Note: Property keys may vary by format
|
|
340
421
|
// Use file.properties() to see all available properties
|
|
@@ -344,20 +425,29 @@ file.save(); // Don't forget to save!
|
|
|
344
425
|
### MusicBrainz example
|
|
345
426
|
|
|
346
427
|
```typescript
|
|
347
|
-
// MusicBrainz metadata using PropertyMap
|
|
348
|
-
file.setProperty(
|
|
349
|
-
|
|
350
|
-
|
|
428
|
+
// MusicBrainz metadata using PropertyMap with tag constants
|
|
429
|
+
file.setProperty(
|
|
430
|
+
Tags.MusicBrainzTrackId,
|
|
431
|
+
"f4d1b6b8-8c1e-4d9a-9f2a-1234567890ab",
|
|
432
|
+
);
|
|
433
|
+
file.setProperty(
|
|
434
|
+
Tags.MusicBrainzAlbumId,
|
|
435
|
+
"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
|
436
|
+
);
|
|
437
|
+
file.setProperty(
|
|
438
|
+
Tags.MusicBrainzArtistId,
|
|
439
|
+
"12345678-90ab-cdef-1234-567890abcdef",
|
|
440
|
+
);
|
|
351
441
|
```
|
|
352
442
|
|
|
353
443
|
### Volume example
|
|
354
444
|
|
|
355
445
|
```typescript
|
|
356
|
-
// ReplayGain volume normalization
|
|
357
|
-
file.setProperty(
|
|
358
|
-
file.setProperty(
|
|
359
|
-
file.setProperty(
|
|
360
|
-
file.setProperty(
|
|
446
|
+
// ReplayGain volume normalization with tag constants
|
|
447
|
+
file.setProperty(Tags.TrackGain, "-6.54 dB");
|
|
448
|
+
file.setProperty(Tags.TrackPeak, "0.987654");
|
|
449
|
+
file.setProperty(Tags.AlbumGain, "-8.12 dB");
|
|
450
|
+
file.setProperty(Tags.AlbumPeak, "0.995432");
|
|
361
451
|
```
|
|
362
452
|
|
|
363
453
|
### Extended fields
|
|
@@ -366,20 +456,20 @@ file.setProperty("REPLAYGAIN_ALBUM_PEAK", "0.995432");
|
|
|
366
456
|
// Using PropertyMap to set multiple properties at once
|
|
367
457
|
const properties = file.properties(); // Get current properties
|
|
368
458
|
|
|
369
|
-
// Set extended metadata
|
|
459
|
+
// Set extended metadata with tag constants
|
|
370
460
|
file.setProperties({
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
461
|
+
[Tags.AlbumArtist]: ["Various Artists"],
|
|
462
|
+
[Tags.Composer]: ["Composer Name"],
|
|
463
|
+
[Tags.Bpm]: ["120"],
|
|
464
|
+
[Tags.Compilation]: ["1"],
|
|
465
|
+
[Tags.DiscNumber]: ["1"],
|
|
466
|
+
[Tags.TrackTotal]: ["12"],
|
|
377
467
|
// Note: Property keys vary by format
|
|
378
468
|
});
|
|
379
469
|
|
|
380
470
|
// Or set individual properties
|
|
381
|
-
file.setProperty(
|
|
382
|
-
file.setProperty(
|
|
471
|
+
file.setProperty(Tags.AlbumArtist, "Various Artists");
|
|
472
|
+
file.setProperty(Tags.Composer, "Composer Name");
|
|
383
473
|
```
|
|
384
474
|
|
|
385
475
|
## 🏗️ Development
|
|
@@ -394,7 +484,7 @@ file.setProperty("COMPOSER", "Composer Name");
|
|
|
394
484
|
git clone <repository>
|
|
395
485
|
cd taglib-wasm
|
|
396
486
|
|
|
397
|
-
# Build
|
|
487
|
+
# Build Wasm module
|
|
398
488
|
deno task build:wasm
|
|
399
489
|
|
|
400
490
|
# Run tests
|
|
@@ -408,7 +498,7 @@ src/
|
|
|
408
498
|
├── mod.ts # Main module exports
|
|
409
499
|
├── taglib.ts # Core TagLib and AudioFile classes
|
|
410
500
|
├── types.ts # TypeScript type definitions
|
|
411
|
-
└── wasm.ts #
|
|
501
|
+
└── wasm.ts # Wasm module interface and utilities
|
|
412
502
|
|
|
413
503
|
build/
|
|
414
504
|
├── build-wasm.sh # Complete build script with C++ wrapper
|
|
@@ -442,23 +532,29 @@ npm test
|
|
|
442
532
|
# ✅ MP3 - ID3v1/v2 tag support
|
|
443
533
|
# ✅ FLAC - Vorbis comments and properties
|
|
444
534
|
# ✅ OGG - Vorbis comments
|
|
445
|
-
# ✅ M4A -
|
|
535
|
+
# ✅ M4A - MPEG-4 (AAC and Apple Lossless) metadata
|
|
446
536
|
```
|
|
447
537
|
|
|
448
538
|
## 🔧 Technical Implementation
|
|
449
539
|
|
|
450
540
|
### Key architecture decisions
|
|
451
541
|
|
|
452
|
-
1. **Memory Management**: Uses Emscripten's `allocate()` for reliable JS↔
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
542
|
+
1. **Memory Management**: Uses Emscripten's `allocate()` for reliable JS↔Wasm
|
|
543
|
+
data transfer
|
|
544
|
+
2. **Buffer-Based Processing**: `TagLib::ByteVectorStream` enables in-memory
|
|
545
|
+
file processing
|
|
546
|
+
3. **C++ Wrapper**: Custom C functions bridge TagLib's C++ API to Wasm exports
|
|
547
|
+
4. **Type Safety**: Complete TypeScript definitions for all audio formats and
|
|
548
|
+
metadata
|
|
456
549
|
|
|
457
550
|
### Critical implementation details
|
|
458
551
|
|
|
459
|
-
- **ByteVectorStream**: Enables processing audio files from memory buffers
|
|
460
|
-
|
|
461
|
-
- **
|
|
552
|
+
- **ByteVectorStream**: Enables processing audio files from memory buffers
|
|
553
|
+
without filesystem
|
|
554
|
+
- **ID-based Object Management**: C++ objects managed via integer IDs for memory
|
|
555
|
+
safety
|
|
556
|
+
- **Emscripten allocate()**: Ensures proper memory synchronization between JS
|
|
557
|
+
and Wasm
|
|
462
558
|
- **UTF-8 String Handling**: Proper encoding for international metadata
|
|
463
559
|
|
|
464
560
|
## 📚 API Reference
|
|
@@ -536,51 +632,48 @@ interface Tag {
|
|
|
536
632
|
type PropertyMap = { [key: string]: string[] };
|
|
537
633
|
```
|
|
538
634
|
|
|
539
|
-
##
|
|
635
|
+
## 📖 Additional Documentation
|
|
540
636
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
```
|
|
637
|
+
- [**Tag Name Constants**](docs/Tag-Name-Constants.md) - Comprehensive reference
|
|
638
|
+
for standard tag names and cross-format mapping
|
|
639
|
+
- [**Automatic Tag Mapping**](docs/Automatic-Tag-Mapping.md) - How taglib-wasm
|
|
640
|
+
handles format-specific tag differences
|
|
641
|
+
- [**Implementation Details**](docs/Implementation.md) - Technical details about
|
|
642
|
+
the Wasm implementation
|
|
643
|
+
- [**Runtime Compatibility**](docs/Runtime-Compatibility.md) - Platform-specific
|
|
644
|
+
setup and considerations
|
|
550
645
|
|
|
551
646
|
## 🌐 Runtime Compatibility
|
|
552
647
|
|
|
553
|
-
`taglib-wasm` works
|
|
648
|
+
`taglib-wasm` works across all major JavaScript runtimes:
|
|
554
649
|
|
|
555
|
-
| Runtime | Status | Installation
|
|
556
|
-
| ----------- | ------- |
|
|
557
|
-
| **Deno** | ✅ Full | `npm:taglib-wasm`
|
|
558
|
-
| **Bun** | ✅ Full | `bun add taglib-wasm`
|
|
559
|
-
| **Node.js** | ✅ Full | `npm install taglib-wasm`
|
|
560
|
-
| **Browser** | ✅ Full | CDN/bundler
|
|
650
|
+
| Runtime | Status | Installation | Performance | TypeScript |
|
|
651
|
+
| ----------- | ------- | ------------------------- | ----------- | ---------- |
|
|
652
|
+
| **Deno** | ✅ Full | `npm:taglib-wasm` | Excellent | Native |
|
|
653
|
+
| **Bun** | ✅ Full | `bun add taglib-wasm` | Excellent | Native |
|
|
654
|
+
| **Node.js** | ✅ Full | `npm install taglib-wasm` | Good | Native/tsx |
|
|
655
|
+
| **Browser** | ✅ Full | CDN/bundler | Good | Via build |
|
|
561
656
|
|
|
562
|
-
**📖 See [docs/Runtime-Compatibility.md](docs/Runtime-Compatibility.md) for
|
|
657
|
+
**📖 See [docs/Runtime-Compatibility.md](docs/Runtime-Compatibility.md) for
|
|
658
|
+
detailed runtime information**
|
|
563
659
|
|
|
564
660
|
## 🚧 Known Limitations
|
|
565
661
|
|
|
566
|
-
- **File Writing
|
|
567
|
-
|
|
568
|
-
- **
|
|
662
|
+
- **File Writing** – Saves only affect in-memory representation (no filesystem
|
|
663
|
+
persistence)
|
|
664
|
+
- **Large Files** – Memory usage scales with file size (entire file loaded into
|
|
665
|
+
memory)
|
|
666
|
+
- **Concurrent Access** – Not thread-safe (JavaScript single-threaded nature)
|
|
569
667
|
|
|
570
668
|
## 🤝 Contributing
|
|
571
669
|
|
|
572
|
-
Contributions welcome!
|
|
573
|
-
|
|
574
|
-
- Additional format support (DSF, DSDIFF, etc.)
|
|
575
|
-
- Advanced metadata implementation (PropertyMap integration)
|
|
576
|
-
- Performance optimizations
|
|
577
|
-
- Runtime-specific optimizations
|
|
578
|
-
- Documentation improvements
|
|
670
|
+
Contributions welcome!
|
|
579
671
|
|
|
580
672
|
## 📄 License
|
|
581
673
|
|
|
582
674
|
- **This project**: MIT License (see [LICENSE](LICENSE))
|
|
583
|
-
- **TagLib library**: LGPL/MPL dual license (see
|
|
675
|
+
- **TagLib library**: LGPL/MPL dual license (see
|
|
676
|
+
[lib/taglib/COPYING.LGPL](lib/taglib/COPYING.LGPL))
|
|
584
677
|
|
|
585
678
|
## 🙏 Acknowledgments
|
|
586
679
|
|