@remedia/node reference
Create an embedded engine, choose a session, and find the detailed API contracts.
@remedia/node embeds the Rust audio engine in Node.js. Follow the embedded quickstart for a working Discord bot. This reference covers direct access to the engine.
Engine API
| Member | Purpose |
|---|---|
Remedia.create(options?) | Initialize an independent engine. Pass { send } for Discord Gateway integration. |
createPlaybackSession<Metadata>() | Create a silent decoder session with a null output. |
createDiscordSession<Metadata>(options) | Register one voice session per guild. |
receive(packet) | Forward raw Gateway dispatches for this bot. |
probe(source, options?) | Inspect a disposable source without playback. |
processResources() | Read cached process-wide CPU and memory counters. |
droppedDebugEvents | Count dropped native diagnostic events. |
close() | Dispose owned sessions, stop workers, and flush telemetry. Safe to repeat. |
Create and close an instance
Create each independent engine context with await Remedia.create(). The
instance owns its playback sessions, voice connections, bounded diagnostics
queue, and optional OpenTelemetry providers. Call close() during normal
shutdown. It stops playback, disconnects voice transports, flushes telemetry,
and releases native workers. It can be called more than once.
import { Remedia } from '@remedia/node';
const remedia = await Remedia.create();
const playback = remedia.createPlaybackSession();
try {
const media = await playback.play({ file: './audio/example.wav' });
console.log(media.codec, media.durationMs);
const finalState = await playback.wait();
console.log(finalState, playback.position);
} finally {
await playback.dispose();
await remedia.close();
}MediaSource is an explicit union: { file: string }, { url: string },
{ buffer: Buffer | Uint8Array }, or { stream: Readable }. The binding does
not infer a source type from arbitrary strings. The returned
AudioStreamInfo contains the selected stream index, codec, original sample
rate and channel layout when known, duration when known, bit rate, and media
metadata.
Standalone sessions currently use NullOutput, which consumes decoded PCM as
fast as possible and does not produce sound. Discord sessions use the
transport-independent core Opus adapter and send the resulting packets through
their associated voice connection.
Playback controls
PlaybackSession.state reports idle, starting, playing, pausing,
resuming, paused, stopping, stopped, completed, or failed.
play() resolves only after the native decoder has opened and selected an
audio stream. It rejects on initialization failure. Starting a second source
while one is active is rejected. Stop the current source first.
The session methods are Promise-based where they wait on native work:
await playback.pause();
await playback.resume();
await playback.seek(12_500); // milliseconds
await playback.stop();
const outcome = await playback.wait();Pausing and seeking take effect at a decoder/output boundary. stop() cancels
playback but does not disconnect an associated Discord voice transport. A
normal EOF moves to completed. An unrecoverable decoder or output error moves
to failed and is available as playback.error. API failures reject their
Promise and remain separate from debug diagnostics.
Read playback positions before using position or durationMs in a user interface.
Session API
| Member | Contract |
|---|---|
play(source, options?) | Start encoded media. Options include local customMetadata and signal. |
pause(), resume(), stop(), seek(ms), wait() | Control or observe one source generation. |
filters.set(graph), filters.clear(), setVolume(gain) | Change trusted processing and gain. |
configureCrossfade(options) | Configure an idle standalone playback session. Discord sessions use creation options. |
stageNext(source, options), clearStage() | Prepare or cancel the next source. |
stagedSource | Staging snapshot getter. The client SDK instead exposes stagedSource(). |
dispose() | Release the session. |
Discord sessions also expose connect(), disconnect(), move(), setSelfDeaf(), and setSelfMute(). Direct Node sessions have no node pool or cross-node migrate() API.
Detailed contracts
| Topic | Reference |
|---|---|
| Input types, ownership, backpressure, probing | Buffers and streams |
| Discord connection, movement, recovery | Embedded voice and session lifecycle |
| Filtergraph replacement and gain | Embedded filters |
| Events, generations, metadata, hooks | Events and hooks |
| Loaded libraries and import failures | FFmpeg runtime API |
| Debug callbacks and telemetry | Embedded diagnostics |
| Source build and generated loaders | Build the addon |
| Staging and promotion | Crossfading |
Direct Node playback events use nodeId: null. Standalone playback has no guildId. Discord events include it. The owning Remedia forwards session lifecycle events and emits debug diagnostics.