audio-encode [](https://github.com/audiojs/audio-encode/actions/workflows/test.js.yml)

June 22, 2026 · View on GitHub

Encode raw audio samples to any format.
JS / WASM – no ffmpeg, no native bindings, works in both node and browser.
Small API, minimal size, near-native performance, stream encoding.

npm install encode-audio

import encode from 'encode-audio';

const buf = await encode.wav(channelData, { sampleRate: 44100 });

Supported formats:

FormatPackageEngine
WAV@audio/encode-wavJS
MP3@audio/encode-mp3WASM
OGG Vorbis@audio/encode-oggWASM
Opus@audio/encode-opusWASM
WebM@audio/encode-webmWASM (Opus)
FLAC@audio/encode-flacWASM
AAC@audio/encode-aacWebCodecs*
AIFF@audio/encode-aiffJS
CAF@audio/encode-cafJS
QOA@audio/encode-qoaJS

* AAC uses the native WebCodecs AudioEncoder — browser-only (Chromium/Safari), throws in Node.

Whole-file encode

Specify the format as method name. Input is Float32Array[] (one per channel), a single Float32Array (mono), or an AudioBuffer.

import encode from 'encode-audio';

const wav  = await encode.wav(channelData, { sampleRate: 44100 });
const aiff = await encode.aiff(channelData, { sampleRate: 44100 });
const caf  = await encode.caf(channelData, { sampleRate: 44100 });
const mp3  = await encode.mp3(channelData, { sampleRate: 44100, bitrate: 128 });
const ogg  = await encode.ogg(channelData, { sampleRate: 44100, quality: 5 });
const flac = await encode.flac(channelData, { sampleRate: 44100 });
const opus = await encode.opus(channelData, { sampleRate: 48000, bitrate: 96 });
const webm = await encode.webm(channelData, { sampleRate: 48000, bitrate: 96 });
const qoa  = await encode.qoa(channelData, { sampleRate: 44100 });
const aac  = await encode.aac(channelData, { sampleRate: 44100, bitrate: 128 }); // browser only

encode.formats lists the supported names and encode.mime maps each to a MIME type — handy for format-agnostic pipelines.

Chunked encoding

Call with just options (no data) to create a streaming encoder:

import encode from 'encode-audio';

const enc = await encode.mp3({ sampleRate: 44100, bitrate: 128 });

const a = await enc(chunk1);  // Uint8Array
const b = await enc(chunk2);
const c = await enc(null);        // end of stream — flush + free

// explicit control: enc.flush(), enc.free()

Streaming

Pass an async iterable as data — returns an async generator:

import encode from 'encode-audio'

for await (let buf of encode.mp3(audioSource, { sampleRate: 44100, bitrate: 128 })) {
  // buf is Uint8Array
}

Works with any async iterable source.

Options

OptionDescriptionApplies to
sampleRateOutput sample rate (required)all
bitrateTarget bitrate in kbpsmp3, opus, webm, aac
qualityQuality 0–10 (VBR)ogg, mp3
channelsOutput channel countall
bitDepthBit depth: 16/24/32 (wav), 16/24 (aiff, flac), 16/32 (caf)wav, aiff, flac, caf
compressionFLAC compression level 0–8flac
application'audio', 'voip', or 'lowdelay'opus, webm
metaTags (see below)wav, mp3, flac, aiff, ogg, opus

Metadata

Pass meta (and, for wav, markers/regions) straight to the encoder:

let bytes = await encode.flac(channelData, {
  sampleRate: 44100,
  meta: { title: 'Hare Krishna', artist: 'Prabhupada', year: '1966' }
})

Tags work for wav, mp3, flac, aiff, ogg and opus. Cue markers and regions are wav-only. opus bakes tags into the OpusTags header at encode time (stays fully streaming); the others splice tags into the finished file — so passing meta to a streaming/chunked encode of wav/mp3/flac/aiff/ogg buffers the output and emits it on flush.

You can also tag already-encoded bytes via encode-audio/meta:

import { wav } from 'encode-audio/meta'

let out = wav(bytes, {
  meta: { title: 'Hare Krishna', artist: 'Prabhupada', year: '1966' },
  markers: [{ sample: 44100, label: 'verse' }],
  regions: [{ sample: 88200, length: 44100, label: 'chorus' }]
})

Each codec sub-package also exposes its writer directly:

import { writeMeta } from '@audio/encode-mp3/meta'
let tagged = writeMeta(mp3Bytes, { meta: { title: 'foo' } })

See also

License

MIT