
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
native-recorder-nodejs
Advanced tools
High-performance, low-latency native audio recording SDK for Node.js. Supports both microphone input and system audio capture (loopback) on Windows and macOS.
| Platform | Architecture | Input (Mic) | Output (System Audio) |
|---|---|---|---|
| Windows 10/11 | x64 | Supported | Supported (per-device) |
| Windows 10/11 | ia32 | Supported | Supported (per-device) |
| macOS 13.0+ | arm64 | Supported | Supported (system-wide) |
| macOS 13.0+ | x64 | Supported | Supported (system-wide) |
| Feature | Windows | macOS |
|---|---|---|
| Input Devices | Multiple (WASAPI) | Multiple (AVFoundation) |
| Output Devices | Multiple (per-device) | Single "System Audio" device |
| Permissions | None required | Microphone + Screen Recording |
| Min OS Version | Windows 10+ | macOS 13.0+ (for system audio) |
npm install native-recorder-nodejs
Prebuilt binaries are available for most platforms. If a prebuild is not available, the package will compile from source (requires CMake and a C++ compiler).
This package includes prebuilt binaries for Electron 29-40. In most cases, it will work out of the box. If you encounter issues:
# Option 1: Use electron-rebuild (recommended)
npx electron-rebuild
# Option 2: Rebuild using cmake-js with Electron runtime
npx cmake-js compile --runtime=electron --runtime-version=YOUR_ELECTRON_VERSION --arch=x64
Note: Make sure to rebuild native modules after updating Electron version.
import { AudioRecorder, SYSTEM_AUDIO_DEVICE_ID } from 'native-recorder-nodejs';
import * as fs from 'fs';
const recorder = new AudioRecorder();
// List available devices
const inputs = AudioRecorder.getDevices('input');
const outputs = AudioRecorder.getDevices('output');
console.log('Microphones:', inputs);
console.log('Output devices:', outputs);
// Record from default microphone
const mic = inputs.find(d => d.isDefault);
if (mic) {
const output = fs.createWriteStream('recording.raw');
recorder.on('data', (buffer) => {
output.write(buffer);
});
recorder.on('error', (error) => {
console.error('Recording error:', error);
});
await recorder.start({
deviceType: 'input',
deviceId: mic.id
});
// Record for 5 seconds
setTimeout(async () => {
await recorder.stop();
output.end();
console.log('Recording saved!');
}, 5000);
}
// Get system audio device
const outputs = AudioRecorder.getDevices('output');
const systemAudio = outputs.find(d => d.id === SYSTEM_AUDIO_DEVICE_ID)
|| outputs.find(d => d.isDefault);
if (systemAudio) {
await recorder.start({
deviceType: 'output',
deviceId: systemAudio.id
});
}
AudioRecorderThe main class for controlling audio recording.
const recorder = new AudioRecorder();
start(config: RecordingConfig): Promise<void>Starts recording from the specified device.
interface RecordingConfig {
deviceType: 'input' | 'output'; // Required
deviceId: string; // Required
}
await recorder.start({
deviceType: 'input',
deviceId: 'device-uuid'
});
stop(): Promise<void>Stops the recording session.
await recorder.stop();
getDevices(type?: DeviceType): AudioDevice[]Lists available audio devices.
interface AudioDevice {
id: string; // Unique identifier
name: string; // Human-readable name
type: 'input' | 'output';
isDefault: boolean;
}
const allDevices = AudioRecorder.getDevices();
const microphones = AudioRecorder.getDevices('input');
const outputs = AudioRecorder.getDevices('output');
getDeviceFormat(deviceId: string): AudioFormatGets the audio format of a device.
interface AudioFormat {
sampleRate: number; // e.g., 48000
channels: number; // 1 (mono) or 2 (stereo)
bitDepth: number; // Output bit depth (16)
rawBitDepth: number; // Native device bit depth
}
const format = AudioRecorder.getDeviceFormat(device.id);
checkPermission(): PermissionStatusChecks current permission status.
interface PermissionStatus {
mic: boolean; // Microphone permission
system: boolean; // System audio permission
}
const status = AudioRecorder.checkPermission();
requestPermission(type: 'mic' | 'system'): booleanRequests permission for recording.
const granted = AudioRecorder.requestPermission('mic');
const systemGranted = AudioRecorder.requestPermission('system');
'data'Emitted when audio data is available.
recorder.on('data', (buffer: Buffer) => {
// Raw PCM 16-bit LE audio data
});
'error'Emitted when an error occurs.
recorder.on('error', (error: Error) => {
console.error(error.message);
});
// Special device ID for system-wide audio capture on macOS
export const SYSTEM_AUDIO_DEVICE_ID = 'system';
The output is always:
You can play the recorded raw audio using FFplay:
ffplay -f s16le -ar 48000 -ch_layout stereo recording.raw
Or convert to WAV using FFmpeg:
ffmpeg -f s16le -ar 48000 -ac 2 -i recording.raw output.wav
On macOS, you need to grant permissions:
The SDK will automatically prompt for permissions when needed, or you can request them programmatically:
const permissions = AudioRecorder.checkPermission();
if (!permissions.mic) {
AudioRecorder.requestPermission('mic');
}
if (!permissions.system) {
AudioRecorder.requestPermission('system');
}
| Error Code | Description |
|---|---|
DEVICE_NOT_FOUND | Specified device ID does not exist |
DEVICE_TYPE_MISMATCH | Device ID doesn't match the specified type |
PERMISSION_DENIED | Missing required system permission |
ALREADY_RECORDING | Recording session already active |
DEVICE_DISCONNECTED | Device was disconnected during recording |
# Install dependencies
npm install
# Build native module
npm run build:native
# Build TypeScript
npm run build:ts
# Build everything
npm run build
# Run tests
npm test
# Build prebuilt binaries for current platform
npm run prebuild
# Upload prebuilts to GitHub Release (requires GITHUB_TOKEN)
npm run prebuild:upload
# Publish to npm (prebuilts should be uploaded first)
npm publish
The project uses GitHub Actions for automated builds and releases. The workflow is triggered by:
| Trigger | Action |
|---|---|
Push to main | Build and test on all platforms |
Pull Request to main | Build and test on all platforms |
Push tag v* (e.g., v1.0.0) | Build, test, publish to npm, and create GitHub Release |
To release a new version:
# 1. Update version in package.json
npm version patch # or minor, major
# 2. Push the tag to trigger the release workflow
git push origin main --tags
The CI will automatically:
Note: Ensure
NPM_TOKENis configured in repository secrets for npm publishing.
┌─────────────────────────────────────────────────┐
│ Node.js Application │
├─────────────────────────────────────────────────┤
│ TypeScript Wrapper │
├─────────────────────────────────────────────────┤
│ N-API Binding Layer │
├────────────────────┬────────────────────────────┤
│ Windows │ macOS │
│ (WASAPI) │ (AVFoundation + │
│ │ ScreenCaptureKit) │
└────────────────────┴────────────────────────────┘
For detailed architecture documentation, see docs/architecture.md.
For complete API documentation, see docs/api.md.
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE for details.
FAQs
Cross-platform (Win/Mac) Native Audio SDK for Node.js
We found that native-recorder-nodejs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.