taglib-ts
    Preparing search index...

    taglib-ts

    taglib-ts

    TypeScript Build & Test

    Native TypeScript port of TagLib for browsers, Node.js, and any JavaScript runtime. Reads and writes audio metadata (ID3v1, ID3v2, APE, Vorbis comments, MP4 atoms, RIFF Info, ASF, Matroska tags, and more) for 21 container formats β€” no WASM, no native bindings.

    • 🎡 21 audio formats: MP3, FLAC, MP4/AAC, OGG (Vorbis / Opus / Speex / FLAC), WAV, AIFF, MPC, WavPack, Monkey's Audio, TrueAudio, DSF, DSDIFF, ASF/WMA, Matroska/WebM, MOD, S3M, XM, IT, Shorten
    • 🏷️ All major tag formats: ID3v1, ID3v2 (v2.2 / v2.3 / v2.4), APEv2, Vorbis Comment, FLAC Picture, RIFF Info, DSDIFF DIIN, ASF, Matroska
    • πŸ“¦ Code splitting: format readers are lazy-loaded via dynamic import() β€” only the formats you use land in your bundle
    • 🌐 Browser-first: accepts File, Blob, and Uint8Array inputs
    • βœ… 360+ tests ported from the C++ CppUnit suite

    npm install @dantheman827/taglib-ts 
    
    import { readTags } from '@dantheman827/taglib-ts/simpleApi.js';

    // Browser File picker
    const [file] = await showOpenFilePicker({ types: [{ accept: { 'audio/*': [] } }] });
    const tags = await readTags(await file.getFile());

    console.log(tags.title); // "Bohemian Rhapsody"
    console.log(tags.artist); // "Queen"
    console.log(tags.audioProperties?.bitrate); // 320 (kb/s)
    console.log(tags.audioProperties?.lengthInSeconds); // 354
    import { writeTags } from '@dantheman827/taglib-ts/simpleApi.js';

    const modified = await writeTags(file, {
    title: 'My Track',
    artist: 'My Artist',
    album: 'My Album',
    year: 2024,
    track: 1,
    });

    if (modified) {
    const blob = new Blob([modified], { type: 'audio/mpeg' });
    // trigger a download, send to a server, etc.
    }

    Use FileRef when you need direct access to tags, audio properties, or format-specific metadata.

    import { FileRef } from '@dantheman827/taglib-ts/fileRef.js';
    import { ReadStyle } from "@dantheman827/taglib-ts/toolkit/types.js";

    const ref = await FileRef.fromBlob(blob, 'track.mp3');

    if (ref.isValid) {
    const tag = ref.tag();
    const ap = ref.audioProperties();

    console.log(tag?.title, tag?.artist);
    console.log(ap?.sampleRate, ap?.channels);

    // Modify and save
    if (tag) {
    tag.title = 'Updated Title';
    tag.artist = 'Updated Artist';
    }
    ref.save(); // writes into the in-memory stream

    // Retrieve the modified bytes
    const modified = ref.file()!.stream() as ByteVectorStream;
    const bytes = modified.data().data; // Uint8Array
    }

    Read tags and optionally audio properties from an audio file.

    Parameter Type Default Description
    input AudioInput β€” Audio data (see below)
    readAudioProperties boolean true Whether to extract audio properties

    AudioInput can be:

    • File β€” browser File object; filename is used for format detection
    • Blob β€” content-based format detection
    • Uint8Array β€” raw bytes; content-based detection
    • { data: Uint8Array; filename: string } β€” raw bytes with explicit filename

    Returns a Tags object:

    interface Tags {
    title: string;
    artist: string;
    album: string;
    comment: string;
    genre: string;
    year: number; // 0 if not set
    track: number; // 0 if not set
    audioProperties: AudioPropertiesInfo | null;
    }

    interface AudioPropertiesInfo {
    lengthInSeconds: number;
    lengthInMilliseconds: number;
    bitrate: number; // kb/s
    sampleRate: number; // Hz
    channels: number;
    }

    If the format is not recognised the function returns an object with all string fields as "", numeric fields as 0, and audioProperties as null.


    Write tags to an audio file and return the modified bytes.

    Parameter Type Description
    input AudioInput Audio data to modify (never mutated in place)
    tags TagsToWrite Fields to update; undefined fields are left unchanged
    interface TagsToWrite {
    title?: string;
    artist?: string;
    album?: string;
    comment?: string;
    genre?: string;
    year?: number;
    track?: number;
    }

    Returns null if the format is unknown, the file is invalid, or the save failed.


    FileRef is the main entry point for advanced usage.

    // From an IOStream (any custom stream implementing IOStream)
    static async open(stream: IOStream, readProperties?: boolean, readStyle?: ReadStyle): Promise<FileRef>

    // From a Uint8Array (with optional filename for extension-based detection)
    static async fromByteArray(data: Uint8Array, filename?: string, readProperties?: boolean, readStyle?: ReadStyle): Promise<FileRef>

    // From a Blob or browser File
    static async fromBlob(blob: Blob, filename?: string, readProperties?: boolean, readStyle?: ReadStyle): Promise<FileRef>
    Member Returns Description
    isValid boolean true if the file was parsed successfully
    isNull boolean true if no underlying file is attached
    tag() Tag | null The unified tag for this file
    audioProperties() AudioProperties | null Stream audio properties
    file() File | null The underlying format-specific File object
    save() boolean Save tag changes back to the in-memory stream
    properties() PropertyMap All tags as a key→string[] map
    setProperties(map) PropertyMap Set tags from a PropertyMap; returns unsupported keys
    complexPropertyKeys() string[] Keys with complex (non-string) values (e.g. PICTURE)
    complexProperties(key) VariantMap[] Get complex property values
    setComplexProperties(key, value) boolean Set complex property values
    FileRef.defaultFileExtensions() string[] All supported file extensions

    The Tag abstract class is implemented by all format-specific tag classes and exposed via FileRef.tag() and readTags().

    abstract class Tag {
    // Getters / setters
    abstract title: string;
    abstract artist: string;
    abstract album: string;
    abstract comment: string;
    abstract genre: string;
    abstract year: number;
    abstract track: number;

    // Helpers
    readonly isEmpty: boolean;

    // PropertyMap interface
    properties(): PropertyMap;
    setProperties(map: PropertyMap): PropertyMap;
    complexPropertyKeys(): string[];
    complexProperties(key: string): VariantMap[];
    setComplexProperties(key: string, value: VariantMap[]): boolean;

    // Static utilities
    static duplicate(source: Tag, target: Tag, overwrite: boolean): void;
    static joinTagValues(values: string[]): string;
    }

    abstract class AudioProperties {
    readonly lengthInSeconds: number; // rounded to nearest second
    readonly lengthInMilliseconds: number;
    readonly bitrate: number; // kb/s
    readonly sampleRate: number; // Hz
    abstract readonly channels: number;
    }

    A case-insensitive, ordered Map<string, string[]> for storing tag key/value pairs.

    const map = new PropertyMap();
    map.replace('TITLE', ['My Song']);
    map.replace('ARTIST', ['My Artist', 'Another Artist']);

    for (const [key, values] of map.entries()) {
    console.log(key, values);
    }

    import { detectByExtension, detectByContent } from '@dantheman827/taglib-ts/formatDetection.js';

    const format = detectByExtension('track.mp3'); // 'mpeg'
    const format2 = detectByContent(stream); // null | format string

    Extension(s) Format Tags
    .mp3, .mp2, .aac MPEG Audio ID3v1, ID3v2, APEv2
    .flac FLAC Vorbis Comment, FLAC Picture
    .m4a, .m4b, .mp4, .aax MP4/AAC, ALAC MP4 atoms (iTunes)
    .ogg, .oga OGG Vorbis Vorbis Comment
    .opus OGG Opus Vorbis Comment
    .spx OGG Speex Vorbis Comment
    .flac (in OGG) OGG FLAC Vorbis Comment
    .wav WAV / RIFF ID3v2, RIFF Info
    .aif, .aiff, .aifc AIFF ID3v2
    .mpc Musepack (SV4–SV8) APEv2, ID3v1
    .wv WavPack APEv2, ID3v1
    .ape Monkey's Audio APEv2, ID3v1
    .tta TrueAudio ID3v2, ID3v1
    .dsf DSF (DSD) ID3v2
    .dff, .dsdiff DSDIFF (DSD) ID3v2, DIIN

    All format readers work on an in-memory ByteVectorStream. There is no file system access β€” audio data is passed in as a Uint8Array and the (possibly modified) bytes are returned as a Uint8Array.

    import { ByteVectorStream } from "@dantheman827/taglib-ts/toolkit/byteVectorStream.js";
    import { ByteVector } from '@dantheman827/taglib-ts/byteVector.js';

    const bv = ByteVector.fromByteArray(myUint8Array);
    const stream = new ByteVectorStream(bv);
    const ref = await FileRef.open(stream);

    Control how much of the file is scanned for audio properties:

    import { ReadStyle } from '@dantheman827/taglib-ts/toolkit/types.js';

    ReadStyle.Fast // Minimal scan β€” may be less accurate
    ReadStyle.Average // Default β€” good balance of speed and accuracy
    ReadStyle.Accurate // Full scan β€” most accurate bitrate/duration for VBR

    LGPL-2.1-or-later (same as the original C++ TagLib)