JSPM

tagpilot-lib

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 10
  • Score
    100M100P100Q40976F
  • License MIT

A high-performance Node.js library for reading and writing audio metadata and cover art, built with Rust and NAPI-RS

Package Exports

  • tagpilot-lib
  • tagpilot-lib/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (tagpilot-lib) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

tagpilot-lib

A high-performance Node.js library for reading and writing audio metadata and cover art, built with Rust and NAPI-RS.

Features

  • 🚀 High Performance: Native Rust implementation for maximum speed
  • 🎵 Audio Metadata: Read and write ID3 tags, MP3 metadata, and more
  • 🖼️ Cover Art: Extract, embed, and manage album artwork
  • 📦 Buffer Support: Work with audio data directly in memory
  • 🔄 Async/Await: Promise-based API for modern JavaScript
  • 🛡️ TypeScript: Full TypeScript support with type definitions
  • 🌐 Cross Platform: Works on Windows, macOS, and Linux

Installation

npm install tagpilot-lib

Quick Start

const { readTags, writeTags, readCoverImage, writeCoverImage } = require('tagpilot-lib');

// Read audio metadata
const tags = await readTags('./music/song.mp3');
console.log(tags.title); // "Song Title"
console.log(tags.artist); // "Artist Name"

// Write audio metadata
await writeTags('./music/song.mp3', {
  title: 'New Title',
  artist: 'New Artist',
  album: 'Album Name',
  year: 2024,
  genre: 'Rock',
  track: 1,
  trackTotal: 12
});

// Read cover image
const coverImage = await readCoverImage(audioBuffer);
if (coverImage) {
  console.log('Cover image found:', coverImage.length, 'bytes');
}

// Write cover image
const imageBuffer = fs.readFileSync('./cover.jpg');
const modifiedAudio = await writeCoverImage(audioBuffer, imageBuffer);

API Reference

Audio Tags

readTags(filePath: string): Promise<AudioTags>

Reads metadata from an audio file.

Parameters:

  • filePath (string): Path to the audio file

Returns: Promise

Example:

const tags = await readTags('./music/song.mp3');
console.log(tags);
// {
//   title: "Song Title",
//   artist: "Artist Name",
//   album: "Album Name",
//   year: 2024,
//   genre: "Rock",
//   track: 1,
//   trackTotal: 12,
//   albumArtist: "Album Artist",
//   comment: "Comment",
//   disc: 1,
//   discTotal: 2
// }

writeTags(filePath: string, tags: AudioTags): Promise<void>

Writes metadata to an audio file.

Parameters:

  • filePath (string): Path to the audio file
  • tags (AudioTags): Metadata to write

Returns: Promise

Example:

await writeTags('./music/song.mp3', {
  title: 'New Title',
  artist: 'New Artist',
  album: 'Album Name',
  year: 2024,
  genre: 'Rock',
  track: 1,
  trackTotal: 12,
  albumArtist: 'Album Artist',
  comment: 'My comment',
  disc: 1,
  discTotal: 2
});

clearTags(filePath: string): Promise<void>

Clears all metadata from an audio file.

Parameters:

  • filePath (string): Path to the audio file

Returns: Promise

Example:

await clearTags('./music/song.mp3');

Buffer Operations

readTagsFromBuffer(buffer: Buffer): Promise<AudioTags>

Reads metadata from an audio buffer.

Parameters:

  • buffer (Buffer): Audio data buffer

Returns: Promise

Example:

const audioBuffer = fs.readFileSync('./music/song.mp3');
const tags = await readTagsFromBuffer(audioBuffer);

writeTagsToBuffer(buffer: Buffer, tags: AudioTags): Promise<Buffer>

Writes metadata to an audio buffer and returns the modified buffer.

Parameters:

  • buffer (Buffer): Audio data buffer
  • tags (AudioTags): Metadata to write

Returns: Promise

Example:

const audioBuffer = fs.readFileSync('./music/song.mp3');
const modifiedBuffer = await writeTagsToBuffer(audioBuffer, {
  title: 'New Title',
  artist: 'New Artist'
});
fs.writeFileSync('./music/modified-song.mp3', modifiedBuffer);

Cover Art

readCoverImage(buffer: Buffer): Promise<Buffer | null>

Reads cover art from an audio buffer.

Parameters:

  • buffer (Buffer): Audio data buffer

Returns: Promise<Buffer | null>

Example:

const audioBuffer = fs.readFileSync('./music/song.mp3');
const coverImage = await readCoverImage(audioBuffer);
if (coverImage) {
  fs.writeFileSync('./cover.jpg', coverImage);
}

writeCoverImage(buffer: Buffer, imageData: Buffer): Promise<Buffer>

Writes cover art to an audio buffer and returns the modified buffer.

Parameters:

  • buffer (Buffer): Audio data buffer
  • imageData (Buffer): Image data (JPEG, PNG, GIF, BMP, TIFF)

Returns: Promise

Example:

const audioBuffer = fs.readFileSync('./music/song.mp3');
const imageBuffer = fs.readFileSync('./cover.jpg');
const modifiedAudio = await writeCoverImage(audioBuffer, imageBuffer);
fs.writeFileSync('./music/song-with-cover.mp3', modifiedAudio);

Types

AudioTags

interface AudioTags {
  title?: string;
  artist?: string;
  album?: string;
  year?: number;
  genre?: string;
  track?: number;
  trackTotal?: number;
  albumArtist?: string;
  comment?: string;
  disc?: number;
  discTotal?: number;
}

Examples

Basic Usage

const { readTags, writeTags } = require('tagpilot-lib');

async function updateSongMetadata() {
  // Read existing metadata
  const tags = await readTags('./music/song.mp3');
  console.log('Current title:', tags.title);

  // Update metadata
  await writeTags('./music/song.mp3', {
    ...tags,
    title: 'Updated Title',
    year: 2024
  });

  console.log('Metadata updated successfully!');
}

Cover Art Management

const { readCoverImage, writeCoverImage } = require('tagpilot-lib');
const fs = require('fs');

async function manageCoverArt() {
  const audioBuffer = fs.readFileSync('./music/song.mp3');
  
  // Read existing cover art
  const existingCover = await readCoverImage(audioBuffer);
  if (existingCover) {
    console.log('Existing cover art found:', existingCover.length, 'bytes');
    fs.writeFileSync('./existing-cover.jpg', existingCover);
  }

  // Add new cover art
  const newCover = fs.readFileSync('./new-cover.jpg');
  const modifiedAudio = await writeCoverImage(audioBuffer, newCover);
  fs.writeFileSync('./music/song-with-new-cover.mp3', modifiedAudio);
}

Batch Processing

const { readTags, writeTags } = require('tagpilot-lib');
const fs = require('fs');
const path = require('path');

async function batchUpdateMetadata() {
  const musicDir = './music';
  const files = fs.readdirSync(musicDir).filter(f => f.endsWith('.mp3'));

  for (const file of files) {
    const filePath = path.join(musicDir, file);
    const tags = await readTags(filePath);
    
    // Update all files with a common album name
    await writeTags(filePath, {
      ...tags,
      album: 'My Greatest Hits',
      year: 2024
    });
    
    console.log(`Updated: ${file}`);
  }
}

Data URL Generation

const { readCoverImage } = require('tagpilot-lib');
const fs = require('fs');

function bufferToDataURL(buffer, mimeType = 'image/jpeg') {
  const base64 = buffer.toString('base64');
  return `data:${mimeType};base64,${base64}`;
}

async function getCoverAsDataURL() {
  const audioBuffer = fs.readFileSync('./music/song.mp3');
  const coverImage = await readCoverImage(audioBuffer);
  
  if (coverImage) {
    const dataURL = bufferToDataURL(coverImage, 'image/jpeg');
    console.log('Cover art data URL:', dataURL.substring(0, 100) + '...');
    return dataURL;
  }
  
  return null;
}

Supported Formats

Audio Formats

  • MP3 (ID3v1, ID3v2)
  • FLAC
  • M4A (MPEG-4 Audio)
  • OGG (Vorbis)
  • WAV
  • WAVPACK
  • AAC
  • AIFF
  • OPUS
  • Speex

Image Formats

  • JPEG
  • PNG
  • GIF
  • BMP
  • TIFF

Performance

tagpilot-lib is built with Rust and NAPI-RS for maximum performance:

  • Fast: Native implementation with minimal overhead
  • Memory Efficient: Direct buffer operations without temporary files
  • Scalable: Handles large audio files efficiently
  • Concurrent: Async operations for better throughput

Development

Prerequisites

  • Node.js 16+
  • Rust toolchain
  • npm or yarn

Building from Source

git clone https://github.com/yortyrh/tagpilot-lib.git
cd tagpilot-lib
npm install
npm run build

Running Tests

npm test

Running Examples

# Read tags example
node examples/read-tags-example.js ./music/song.mp3

# Write tags example
node examples/write-tags-example.js ./music/song.mp3

# Cover image example
node examples/cover-image-buffer-example.js ./music/song.mp3 ./cover.jpg

# Read cover image as data URL
node examples/read-cover-image-example.js ./music/song.mp3

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Run the test suite
  6. Submit a pull request

License

MIT License - see LICENSE file for details.

Changelog

v1.0.0

  • Initial release
  • Audio metadata reading and writing
  • Cover art extraction and embedding
  • Buffer-based operations
  • TypeScript support
  • Comprehensive examples

Support

Acknowledgments

  • Built with NAPI-RS for Node.js native addons
  • Audio metadata handling powered by lofty
  • Image format detection using infer