bionic-audio
v1.1.1
Published
Professional Windows WASAPI audio recorder library for Node.js and Bun - record microphone and system audio with advanced features
Maintainers
Readme
bionic-audio
Professional Windows WASAPI audio recorder library for Node.js and Bun. Record microphone, system loopback, or both simultaneously with support for multiple audio formats and advanced quality settings.
Status: Production Ready | Platform: Windows 10/11 | Architecture: x64, ia32
Features
- 🎤 Microphone Recording: Capture input from your microphone
- 🔊 Loopback Recording: Capture system audio (what's playing on speakers)
- 🎙️ Dual Recording: Record both microphone and loopback simultaneously
- 📊 Multiple Formats: 16-bit PCM, 24-bit PCM, or 32-bit float WAV files
- ⏱️ Duration Control: Record for a specific duration or indefinitely
- 🎛️ Gain Control: Amplify or reduce signal strength
- 📡 Stream to stdout: Raw PCM streaming for real-time processing
- 🧵 Threaded Capture: Dedicated thread for capture operations
- 🔌 Easy Integration: EventEmitter-based interface with promise support
Installation
npm install bionic-audioOr globally for CLI access:
npm install -g bionic-audioRequirements
- Windows 10/11
- Node.js 14+ or Bun
recorder.exebinary (included in package, or build from source)
Quick Start
Basic Recording
import { recordToFile } from 'bionic-audio';
// Simple file recording - 5 seconds of system audio
await recordToFile('./output.wav', { duration: 5 });EventEmitter Interface
import { AudioRecorder } from 'bionic-audio';
const recorder = new AudioRecorder({
output: './recording.wav',
duration: 10,
preserve32: true // 32-bit float format
});
recorder.on('started', () => console.log('🎤 Recording started'));
recorder.on('data', (bytes) => console.log(`📝 Wrote ${bytes} bytes`));
recorder.on('error', (err) => console.error('❌ Error:', err));
recorder.on('complete', (result) => {
console.log('✅ Recording complete:', result);
});
recorder.start();
// Stop manually (or wait for duration to finish)
setTimeout(() => recorder.stop(), 5000);Promise-Based Interface
import { AudioRecorder } from 'bionic-audio';
const recorder = new AudioRecorder();
try {
const result = await recorder.record({
duration: 5,
output: './output.wav'
});
console.log(`✅ Recording finished with exit code ${result.code}`);
} catch (error) {
console.error('❌ Recording failed:', error);
}Convenience Functions
import {
recordToFile,
recordMicrophone,
recordLoopback,
recordBoth
} from 'bionic-audio';
// Record system audio (loopback) to file
await recordToFile('./output.wav', { duration: 10 });
// Record microphone only
await recordMicrophone('./mic.wav', { duration: 10 });
// Record system audio only
await recordLoopback('./system.wav', { duration: 10 });
// Record both simultaneously (two separate files)
await recordBoth('./combined.wav', { duration: 10 });Streaming to stdout
import { AudioRecorder } from 'bionic-audio';
import { createWriteStream } from 'fs';
const recorder = new AudioRecorder();
const output = createWriteStream('./stream.wav');
recorder.pipe(output);
recorder.start({ duration: 5, pcmOnly: true });API Reference
new AudioRecorder(options?)
Creates a new audio recorder instance.
Options:
output?: string- Output file path (required for file recording)duration?: number- Recording duration in seconds (0 = infinite, default: 0)gain?: number- Signal gain/amplitude multiplier (default: 1.0)preserve24?: boolean- Keep 24-bit native format (default: false)preserve32?: boolean- Keep 32-bit float format (default: false)pcmOnly?: boolean- Output raw PCM without WAV header (default: false)loopback?: boolean- Record system audio instead of microphone (default: false)microphone?: boolean- Record microphone (default: true)both?: boolean- Record both simultaneously (default: false)threaded?: boolean- Use dedicated capture thread (default: false)
Methods
start(options?): void
Starts recording with optional runtime options.
stop(): boolean
Stops the recording process. Returns true if stopped, false if not running.
isRecording(): boolean
Check if currently recording.
record(options?): Promise<RecorderResult>
Promise-based recording. Blocks until recording completes or errors.
const result = await recorder.record({ duration: 5 });
// result: { code: number, signal: string | null, stderr: string }pipe(destination: NodeJS.WritableStream): void
Pipe raw audio data to a writable stream (e.g., for real-time processing).
getProcess(): ChildProcess | null
Access the underlying child process directly.
Events
started- Recording has starteddata(bytes: number)- Data written (number of bytes)stderr(data: string)- Stderr output from recorderexit(code: number, signal: string | null)- Process exitedcomplete(result: RecorderResult)- Recording completed successfullyerror(error: Error)- Error occurred
Convenience Functions
recordToFile(path: string, options?: RecorderOptions): Promise<RecorderResult>
Quick file recording.
recordMicrophone(path: string, options?: RecorderOptions): Promise<RecorderResult>
Record microphone only.
recordLoopback(path: string, options?: RecorderOptions): Promise<RecorderResult>
Record system audio only.
recordBoth(path: string, options?: RecorderOptions): Promise<RecorderResult>
Record both microphone and loopback simultaneously.
Configuration
Audio Quality
- 16-bit PCM (default): Balanced quality and file size, ~1.5 MB/min for stereo at 48kHz
- 24-bit PCM (
preserve24: true): Higher quality, ~2.3 MB/min - 32-bit float (
preserve32: true): Highest quality, lossless internal format, ~3 MB/min
Gain Control
// Amplify by 2x
recorder.start({ gain: 2.0 });
// Reduce by half
recorder.start({ gain: 0.5 });Gain is applied before clipping to prevent distortion.
Electron Integration
import { AudioRecorder } from 'bionic-audio';
import { ipcMain } from 'electron';
let recorder: AudioRecorder | null = null;
ipcMain.handle('start-recording', async (event, options) => {
recorder = new AudioRecorder(options);
recorder.on('error', (err) => {
event.sender.send('recording-error', err.message);
});
recorder.start();
return { ok: true };
});
ipcMain.handle('stop-recording', async () => {
recorder?.stop();
return { ok: true };
});Building from Source
# Install dependencies
npm install
# Compile TypeScript
npm run build
# Build C++ recorder binary (requires MinGW or MSVC)
gcc -o recorder.exe main.c -lole32 -std=c99Troubleshooting
"recorder.exe not found"
Ensure the binary is in PATH or in one of these locations:
./recorder.exe./bin/recorder.exe../recorder.exe./dist/recorder.exe
Distorted/Noisy Audio
Try enabling gain control with values < 1.0:
recorder.start({ gain: 0.8 });File Won't Play
Ensure you're using a compatible audio player. 32-bit float WAV support varies. Try 16-bit output:
recorder.start({ preserve32: false });License
MIT
