
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
@0biwank/getsystemaudio
Advanced tools
Capture macOS system audio in Node.js as real-time PCM frames from a native N-API addon.
This package is designed for pipelines like:
npm install @0biwank/getsystemaudio
npm run rebuild
Starts capture.
Stops capture.
Registers PCM callback.
Returns runtime diagnostics and queue/callback counters.
Backward-compatible alias for setCallback.
import {
startCapture,
stopCapture,
setCallback,
getCaptureDiagnostics,
} from '@0biwank/getsystemaudio';
setCallback((pcm, meta) => {
// pcm is interleaved float32
// for stereo: [L0, R0, L1, R1, ...]
if (meta.source === 'system') {
// process real system audio
}
});
startCapture();
setTimeout(() => {
stopCapture();
console.log(getCaptureDiagnostics());
}, 5000);
Keep capture in the main process. Push PCM to renderer via IPC. Convert to MediaStream in renderer using AudioWorklet.
// main.js
import { app, BrowserWindow, ipcMain } from 'electron';
import {
startCapture,
stopCapture,
setCallback,
getCaptureDiagnostics,
} from '@0biwank/getsystemaudio';
let win;
function createWindow() {
win = new BrowserWindow({
webPreferences: {
preload: new URL('./preload.js', import.meta.url).pathname,
contextIsolation: true,
nodeIntegration: false,
},
});
win.loadURL('http://localhost:3000');
}
app.whenReady().then(() => {
createWindow();
setCallback((pcm, meta) => {
// Transfer plain array-like data to renderer.
// For higher throughput, consider chunk batching and shared memory.
win?.webContents.send('system-audio:pcm', {
pcm: Array.from(pcm),
meta,
});
});
});
ipcMain.handle('system-audio:start', () => {
startCapture();
return getCaptureDiagnostics();
});
ipcMain.handle('system-audio:stop', () => {
stopCapture();
return getCaptureDiagnostics();
});
ipcMain.handle('system-audio:diag', () => getCaptureDiagnostics());
// preload.js
import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('systemAudio', {
start: () => ipcRenderer.invoke('system-audio:start'),
stop: () => ipcRenderer.invoke('system-audio:stop'),
diagnostics: () => ipcRenderer.invoke('system-audio:diag'),
onPcm: (handler) => {
const listener = (_event, payload) => handler(payload);
ipcRenderer.on('system-audio:pcm', listener);
return () => ipcRenderer.removeListener('system-audio:pcm', listener);
},
});
// renderer.js
async function createSystemMediaStream() {
const context = new AudioContext({ sampleRate: 48000 });
await context.audioWorklet.addModule('/audio/system-audio-processor.js');
const node = new AudioWorkletNode(context, 'system-audio-processor', {
numberOfInputs: 0,
numberOfOutputs: 1,
outputChannelCount: [2],
});
const destination = context.createMediaStreamDestination();
node.connect(destination);
const unsubscribe = window.systemAudio.onPcm(({ pcm, meta }) => {
// Recreate Float32Array in renderer
node.port.postMessage({ pcm: new Float32Array(pcm), meta });
});
await window.systemAudio.start();
return {
stream: destination.stream,
stop: async () => {
unsubscribe();
await window.systemAudio.stop();
node.disconnect();
await context.close();
},
};
}
// public/audio/system-audio-processor.js
class SystemAudioProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.queue = [];
this.readOffset = 0;
this.port.onmessage = (event) => {
const payload = event.data;
if (!payload || !(payload.pcm instanceof Float32Array)) return;
this.queue.push(payload.pcm);
};
}
process(_inputs, outputs) {
const output = outputs[0];
const left = output[0];
const right = output[1] || output[0];
left.fill(0);
right.fill(0);
let frameIndex = 0;
while (frameIndex < left.length && this.queue.length > 0) {
const chunk = this.queue[0];
const availableSamples = chunk.length - this.readOffset;
const availableFrames = Math.floor(availableSamples / 2);
const neededFrames = left.length - frameIndex;
const toCopyFrames = Math.min(availableFrames, neededFrames);
for (let i = 0; i < toCopyFrames; i++) {
const base = this.readOffset + i * 2;
left[frameIndex + i] = chunk[base];
right[frameIndex + i] = chunk[base + 1] ?? chunk[base];
}
frameIndex += toCopyFrames;
this.readOffset += toCopyFrames * 2;
if (this.readOffset >= chunk.length) {
this.queue.shift();
this.readOffset = 0;
}
}
return true;
}
}
registerProcessor('system-audio-processor', SystemAudioProcessor);
At this point you can use destination.stream as a standard MediaStream:
Call getCaptureDiagnostics() periodically when tuning.
Useful fields:
For smooth output:
If you only get fallback frames:
Before npm publish:
npm run rebuild
npm test
npm pack
MIT
FAQs
A Node.js module to get the system audio level on MacOS.
We found that @0biwank/getsystemaudio 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
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.