@audio/ encode-mp3
Status calibrated
npm2.0.1licenseMIT
Encode PCM audio samples to MP3 format via WASM
Overview
- Install
- Updated
- Family
- encode, 14 packages under it
- Tags
- read & write
Encode PCM audio samples to MP3 format.
WASM (libmp3lame via wasm-media-encoders) — works in both node and browser.
import mp3 from '@audio/encode-mp3';
const encoder = await mp3({ sampleRate: 44100, channels: 1, bitrate: 128 });
const chunk = encoder.encode(channelData); // → Uint8Array (MP3 frames)
const tail = encoder.flush(); // → Uint8Array (remaining)
// concatenate chunk + tail, then write encoder.head() over the start
Gapless
The output opens with an Info (CBR) or Xing (VBR) frame carrying LAME's tag: the frame and byte counts, a seek TOC, and the encoder delay (576 samples) and padding that decoders trim (ffmpeg, mpg123, Apple's AudioToolbox, LAME's own), so a decoded file has the source's exact length and timing. The totals are known at the end: head() after flush() returns the finished frame (after the ID3 tag when one leads) to write over the start; the whole-file encode.mp3(...) of @audio/encode does it for you. Unpatched (a pipe), the placeholder still carries the delay, and with frames (the exact length upfront) the frame count and padding too.
Options
| Option | Default | Description |
|---|---|---|
sampleRate |
— | Sample rate (required) |
channels |
2 |
1 (mono) or 2 (stereo) |
bitrate |
128 |
CBR bitrate in kbps |
quality |
— | VBR quality 0–9 (0=best). If set, overrides bitrate. |
Streaming
const encoder = await mp3({ sampleRate: 44100, channels: 1, bitrate: 192 });
const a = encoder.encode(chunk1); // → Uint8Array
const b = encoder.encode(chunk2); // → Uint8Array
const c = encoder.flush(); // → Uint8Array
// complete MP3 = concat(a, b, c), encoder.head() written over its start
encoder.free();
Streaming output
chapters: [{ time, title }] (seconds) become ID3v2 CTOC/CHAP frames (ID3v2 Chapter Frame Addendum), in writeMeta too. stream: true puts the tag (meta, chapters) ahead of the first frames; the last chapter's end is unknown until head() returns the finished tag after flush(), unless frames gives the exact length upfront.
License
MIT