Skip to content

Cloudflare Workers ​

taglib-wasm works on Cloudflare Workers using the same unified API as every other platform. No separate import path or limited API is needed.

Overview ​

Cloudflare Workers provide a serverless execution environment on Cloudflare's global edge network. With TagLib-Wasm, you can process audio metadata without managing servers.

Installation ​

bash
npm install taglib-wasm

Basic Setup ​

1. Create a Worker ​

typescript
// src/index.ts
import { TagLib } from "taglib-wasm";

let taglib: Awaited<ReturnType<typeof TagLib.initialize>> | null = null;

export default {
  async fetch(request: Request): Promise<Response> {
    if (!taglib) {
      taglib = await TagLib.initialize();
    }

    const url = new URL(request.url);

    if (url.pathname === "/metadata" && request.method === "POST") {
      return handleMetadata(request);
    }

    return new Response("Audio Metadata Service", {
      headers: { "content-type": "text/plain" },
    });
  },
};

async function handleMetadata(request: Request): Promise<Response> {
  try {
    const audioData = new Uint8Array(await request.arrayBuffer());

    using file = await taglib!.open(audioData);
    const tag = file.tag();
    const props = file.audioProperties();

    return Response.json({
      title: tag.title,
      artist: tag.artist,
      album: tag.album,
      duration: props?.duration,
    });
  } catch (error) {
    return Response.json({ error: (error as Error).message }, { status: 500 });
  }
}

2. Configure wrangler.toml ​

toml
name = "audio-metadata-service"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[build]
command = "npm run build"

[[rules]]
type = "Data"
globs = ["**/*.wasm"]
fallthrough = true

3. Deploy ​

bash
wrangler deploy

# Test locally
wrangler dev

Writing Tags ​

typescript
async function handleEdit(request: Request): Promise<Response> {
  const audioData = new Uint8Array(await request.arrayBuffer());

  const modified = await taglib!.edit(audioData, (file) => {
    file.tag().setTitle("New Title");
    file.tag().setArtist("New Artist");
  });

  return new Response(modified, {
    headers: { "content-type": "application/octet-stream" },
  });
}

Batch Processing ​

Process multiple files in a single request:

typescript
interface BatchRequest {
  files: Array<{
    name: string;
    data: string; // base64 encoded
  }>;
}

async function handleBatch(request: Request): Promise<Response> {
  const { files } = (await request.json()) as BatchRequest;

  const results = await Promise.all(
    files.map(async (file) => {
      try {
        const audioData = Uint8Array.from(atob(file.data), (c) =>
          c.charCodeAt(0),
        );
        using audioFile = await taglib!.open(audioData);
        const tag = audioFile.tag();
        const props = audioFile.audioProperties();
        return {
          name: file.name,
          title: tag.title,
          artist: tag.artist,
          duration: props?.duration,
        };
      } catch (error) {
        return { name: file.name, error: (error as Error).message };
      }
    }),
  );

  return Response.json(results);
}

Workers Environment Limits ​

  • Memory: 128MB limit per request
  • CPU Time: 50ms (free) or 30s (paid) per request
  • Request Size: 100MB maximum

Testing ​

bash
# Start local dev server
wrangler dev

# Test with curl
curl -X POST http://localhost:8787/metadata \
  --data-binary @test.mp3 \
  --header "Content-Type: application/octet-stream"

Resources ​

Released under the MIT License.