@silyze/async-audio-mixer
v1.0.0
Published
Simple audio mixer that uses @silyze/async-audio-stream
Readme
Async Audio Mixer
@silyze/async-audio-mixer is a lightweight, battery‑included audio mixer built on top of @silyze/async-audio-stream.
It lets you combine any number of PCM/encoded streams, produce a single mixed
output, and even bridge two full‑duplex AudioStreams with automatic
transcoding when their formats differ.
Install
npm install @silyze/async-audio-mixerQuick start
import AudioMixer from "@silyze/async-audio-mixer";
import { OpusFormat } from "@silyze/async-audio-format-webm";
// Imagine three incoming Opus/WebM streams (8 kHz mono):
const format = new OpusFormat(8000);
const speakers = [streamA, streamB, streamC].map((s) => format.decode(s));
// Mix to PCM and then re‑encode to Opus:
const mixedOpus = AudioMixer.mix(speakers, { format });
// Pipe to a WebSocket or file:
await mixedOpus.pipe(wsWritable);API
AudioMixer.mix(streams, config?) ⇒ AsyncReadStream<Buffer>
| Parameter | Type & Default | Description |
| --------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| streams | Iterable<AudioOutputStream> | Any audio output streams to be mixed. All must share the same PCM sample‑rate. |
| config.signal | AbortSignal (optional) | Cancel mixing early. |
| config.buffer | number (ms) default 100 | Length of each mixing frame in milliseconds. |
| config.live | boolean default false | If true, the mixer starts emitting only new audio frames (live broadcast). If false, the full buffer history is replayed once a consumer attaches. |
| config.format | AudioFormat (optional) | If supplied, the PCM mix is encoded with format.encode() before being returned. |
The returned stream is PCM‑16‑LE unless you supply
config.format.
AudioMixer.connect(a, b, pipeConfig?) ⇒ Promise<void>
Bidirectionally connects two AudioStreams (a ⇆ b).
If the streams already share the same format & sample‑rate, raw data is piped.
Otherwise each direction is transcoded on‑the‑fly using the respective encode/decode methods.
pipeConfig is forwarded to AsyncTransform.pipe() for back‑pressure and error
handling options.
Example – Simple Voice Chat Room
// listenerStreams: Set<AudioOutputStream> coming from WebRTC peers
const mix = AudioMixer.mix(listenerStreams, {
buffer: 20, // 20 ms frames → low latency
live: true,
});
// Broadcast the mixed PCM to a speech‑to‑text service …
await mix.pipe(sttInputWritable);Internals
- Frame‑based mixing – samples are summed per frame, with hard clipping at
±32768 to avoid overflow. - Mono‑only – each input is treated as mono; stereo mixing is out of scope
(PRs welcome!). - Sample‑rate safety – a runtime assertion prevents accidental mixing of
streams that use different PCM sample‑rates.
