Remedia

@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

MemberPurpose
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.
droppedDebugEventsCount 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

MemberContract
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.
stagedSourceStaging 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

TopicReference
Input types, ownership, backpressure, probingBuffers and streams
Discord connection, movement, recoveryEmbedded voice and session lifecycle
Filtergraph replacement and gainEmbedded filters
Events, generations, metadata, hooksEvents and hooks
Loaded libraries and import failuresFFmpeg runtime API
Debug callbacks and telemetryEmbedded diagnostics
Source build and generated loadersBuild the addon
Staging and promotionCrossfading

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.

On this page