audioJS

@audio/encode-opus

Status calibrated

npm1.3.2licenseMIT

Encode PCM audio samples to Ogg Opus (libopus WASM)

Overview

Install
Updated
Family
encode, 14 packages under it

Encode PCM audio samples to Ogg Opus format.
libopus WASM (single-file module, no side files — loads from any CDN, Node, workers and AudioWorklets) with a built-in Ogg muxer.

import opus from '@audio/encode-opus';

const encoder = await opus({ sampleRate: 48000, channels: 1, bitrate: 96 });
const chunk = encoder.encode(channelData); // → Uint8Array (Ogg pages)
const tail = encoder.flush();              // → Uint8Array (remaining + EOS)
// concatenate chunk + tail for complete Ogg Opus file

Options

Option Default Description
sampleRate — Input sample rate (required). Resampled to 48kHz internally.
channels 1 1 (mono) or 2 (stereo)
bitrate 64 Target bitrate in kbps
application 'audio' 'audio', 'voip', or 'lowdelay'
complexity 10 libopus encoder effort, 0-10
meta — VorbisComment tags (title, artist, …) written into OpusTags

Opus always encodes at 48kHz. Other rates are resampled to it as one stream (polyphase FIR, its phase and history carried across chunks): any chunking encodes as one chunk does, sample for sample, on time.

Streaming

const encoder = await opus({ sampleRate: 44100, channels: 1, bitrate: 128 });
const a = encoder.encode(chunk1); // → Uint8Array (Ogg pages with headers)
const b = encoder.encode(chunk2); // → Uint8Array (Ogg audio pages)
const c = encoder.flush();        // → Uint8Array (final page + EOS)
// complete Ogg Opus = concat(a, b, c)
encoder.free();

License

MIT

ॐ

Raw packets

Container muxers build on the packet encoder directly (@audio/encode-webm does):

import { createOpusEncoder, createResampler, toOpusRate, FRAME } from '@audio/encode-opus/core'

let enc = await createOpusEncoder({ channels: 2, bitrate: 96 })
enc.lookahead                       // encoder delay in 48 kHz samples: Ogg pre-skip / Matroska CodecDelay
let pcm = toOpusRate(channelData, 44100)   // a whole signal → interleaved 48 kHz float
let packet = enc.encode(pcm.subarray(0, FRAME * 2))
enc.free()

let rs = createResampler(44100, 2)  // a chunked one: one stream
rs.write(chunk)                     // planar chunk → interleaved 48 kHz, what is ready
rs.flush()                          // the rest: round(n · 48000 / 44100) in all