A pure JavaScript, high-quality PCM audio resampler for Node.js. Converts s16le PCM between arbitrary sample rates and channel layouts (mono/stereo) with windowed-sinc filtering. Includes built-in volume control.
- Pure JavaScript, no native dependencies
- High-quality windowed-sinc resampling with anti-alias filtering
- Arbitrary input/output sample rates (e.g. 48kHz ↔ 24kHz)
- Channel mixing: stereo→mono (average), mono→stereo (duplicate)
- Streams API: drop-in replacement for ffmpeg pipes in Node.js
- Supports s16le PCM (signed 16-bit little-endian)
- Built-in output volume control
- TypeScript type definitions included
- Node.js 26 or newer
- s16le PCM input for stream processing
npm install @eliware/resamplerimport{Resampler}from'@eliware/resampler';importfsfrom'fs';// Downsample 48kHz stereo to 24kHz monoconstresampler=newResampler({inRate: 48000,outRate: 24000,inChannels: 2,outChannels: 1});fs.createReadStream('input-48k-stereo.s16le').pipe(resampler).pipe(fs.createWriteStream('output-24k-mono.s16le'));// Downsample with half volumeconstresamplerQuiet=newResampler({inRate: 48000,outRate: 24000,inChannels: 2,outChannels: 1,volume: 0.5});fs.createReadStream('input-48k-stereo.s16le').pipe(resamplerQuiet).pipe(fs.createWriteStream('output-24k-mono-quiet.s16le'));Creates a Transform stream that resamples s16le PCM audio.
inRate(number): Input sample rate, finite, greater than 0, and at most 1,000,000 (e.g. 48000)outRate(number): Output sample rate, finite, greater than 0, and at most 1,000,000 (e.g. 24000)inChannels(number, default 1): Number of input channels (1=mono, 2=stereo)outChannels(number, default 1): Number of output channels (1=mono, 2=stereo)filterWindow(number, default 8): Positive integer sinc filter window size, at most 4096 (higher = better quality, more CPU)volume(number, default 1.0): Finite output volume multiplier (0.0 = silence, 1.0 = unchanged, >1.0 = amplify, negative = polarity inversion)
constresampler=newResampler({inRate: 48000,outRate: 24000,inChannels: 2,outChannels: 1,volume: 0.5});Input must contain complete s16le PCM frames. Incomplete frames split across stream chunks are buffered; an incomplete final frame emits an error.
The sinc filter introduces edge latency. Output begins after enough input is available for the configured filter window, and the stream flush pads the input with filterWindow zero samples to emit the available tail. Consequently, output length includes the filter's edge behavior and may differ slightly from the simple inputFrames * outRate / inRate estimate. For exact framing, treat the emitted stream length as authoritative.
Pipe PCM data through the resampler:
inputStream.pipe(resampler).pipe(outputStream);Options are validated before processing. Supported channel layouts are mono and stereo. Input must contain complete s16le frames; an incomplete final frame emits an error. Filter latency and output length include documented edge behavior.
npm test
npm run test:gaps
npm run lint
npm run typecheck
npm run pack
npm run benchmark -- 48000 5 960The resampler performs local audio processing and has no network access. Treat input/output paths, file streams, and any audio data as application-controlled resources; validate untrusted paths and avoid exposing sensitive audio in logs or artifacts.
Type definitions are included:
import{Resampler,ResamplerOptions}from'@eliware/resampler';constresampler: Resampler=newResampler({inRate: 48000,outRate: 24000,inChannels: 2,outChannels: 1,volume: 0.5,});For help, questions, or to chat with the author and community, visit:


