Skip to content

Installation ​

Package Managers ​

typescript
// From JSR (Deno-native)
import { TagLib } from "jsr:@charlesw/taglib-wasm";
// Or from npm
import { TagLib } from "npm:taglib-wasm";
bash
npm install taglib-wasm
bash
bun add taglib-wasm
html
<!-- Use a bundler like Vite, Webpack, or Parcel -->
<script type="module">
  import { TagLib } from "taglib-wasm";
</script>

Note: Deno can install from JSR (jsr:@charlesw/taglib-wasm) or from npm (npm:taglib-wasm) — both channels are published for every release.

Node.js Requirements ​

Requirements: Node.js v24.0.0 or higher (the Active LTS line)

TagLib-Wasm works out of the box on Node.js — the library automatically falls back to the Emscripten backend if WASI isn't available, and logs a warning that names the --experimental-wasm-exnref flag. Adding that flag (Node.js 24 LTS) gets you the WASI backend and its faster path-based I/O. Node.js 25+ supports exnref natively with no flag needed.

Deno and Bun work without any flags.

Running TypeScript ​

bash
# Option 1: Node's built-in TypeScript support (native since v23.6)
node --experimental-wasm-exnref your-script.ts

# Option 2: TypeScript loader (recommended)
npm install --save-dev tsx
node --experimental-wasm-exnref --import tsx your-script.ts

JavaScript (no extra tooling) ​

javascript
// The NPM package includes pre-compiled JavaScript
import { TagLib } from "taglib-wasm";
import { applyTags, readTags } from "taglib-wasm/simple";

// No loader or flag needed — same API as TypeScript
const taglib = await TagLib.initialize();
const tags = await readTags("song.mp3");

Runtime Requirements ​

Memory Requirements ​

Each backend declares its memory limits at build time, and the declaration is fixed — there is no runtime knob to raise it:

  • WASI backend (Deno, Node.js, Bun): 16 MiB initial, 2 GiB maximum. The module declares --initial-memory=16777216 and --max-memory=2147483648 (build/build-wasi.sh).
  • Emscripten backend (browsers, Web Workers, Cloudflare Workers, plain Node.js): memory growth enabled with a 4 GiB ceiling (-s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB, build/build-wasm.sh).
  • Cloudflare Workers: the platform caps memory at 128 MB per request, which you will reach long before either Wasm ceiling.

Browser Compatibility ​

Requires a modern browser:

  • WebAssembly support
  • ES2020 features
  • async/await support

Tested on:

  • Chrome 95+
  • Firefox 100+
  • Safari 15.2+
  • Edge 95+

TypeScript Configuration ​

For TypeScript projects, TagLib-Wasm includes complete type definitions:

json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "lib": ["ES2020", "DOM"]
  }
}

Telling TypeScript About the browser Condition ​

Some entries ship two builds: the barrel (taglib-wasm), taglib-wasm/simple, and taglib-wasm/web resolve a browser export condition, so a browser-targeted bundler gets a different — smaller, browser-safe — file. TypeScript resolves that condition only when it is asked to:

json
{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "customConditions": ["browser"]
  }
}

Without customConditions, TypeScript reads the Node declarations while the bundler ships the browser build. An import that cannot work in a browser — scanFolder from taglib-wasm, which walks a filesystem — then compiles cleanly and fails later, in the bundler. With the condition set, TypeScript uses dist/index.browser.d.ts and the same import is a compile error naming the missing export (TS2305). The pure helpers that do run in a browser (groupAlbums, discFolderInfo, bwf) still compile from the barrel.

Bundler Interop ​

dist/taglib-wrapper.js, the Emscripten glue, contains a dynamic import("node:module") that browser targets have no builtin for, so two bundlers need one line each: esbuild --external:node:module, and webpack externals: { module: "module" } (webpack target: "web" alone fails on it). Rollup needs nothing extra, and vite externalizes it for the browser with a warning.

Import Paths ​

ImportExportsWhere it runs
taglib-wasmThe barrel: Full API, Folder API, ratings, chapters, bwf, groupAlbumsAny runtime, resolving the browser condition — in a browser build the filesystem exports (scanFolder, findDuplicates, …) are absent, which is a compile error naming the export rather than a bundler error
taglib-wasm/simpleSimple API: readTags, applyTagsToFile, batch reads/writes, cover art, media checksumsAny runtime, resolving the browser condition
taglib-wasm/folderThe filesystem Folder API: scanFolder, findDuplicates, exportFolderMetadataDeno / Node.js / Bun only. The entry is Node-only by design (no browser condition), so a browser-targeted build fails loudly
taglib-wasm/disc-foldergroupAlbums, discFolderInfo — pure functions over a scan resultAny runtime, browsers included (pure JavaScript)
taglib-wasm/webBrowser media helpers: pictureToDataURL, dataURLToPicture, canvas and file helpersAny runtime; the browser condition resolves an Emscripten-only build that pulls taglib-web.wasm alone
taglib-wasm/ratingRatingUtils conversionsAny runtime (pure JavaScript)

Importing anything from the barrel does not pull in the Folder or Web API — on Node.js, Deno and Bun every bundler tree-shakes to leaf granularity (the pre-bundled browser entries do not shake to a leaf; the README section has the numbers). The measured per-entry bundle sizes, the export-condition rationale, and the exact esbuild/rollup/vite/webpack invocations behind these notes live in the repository README's Bundle Size and Tree-Shaking section.

Verification ​

Verify your installation:

typescript
import { TagLib } from "taglib-wasm";

const taglib = await TagLib.initialize();
console.log("TagLib-Wasm initialized successfully!");

Next Steps ​

Released under the MIT License.