Skip to main content
Version: v2.10.4 (deprecated)

Voice Receive and Events

Enable Voice Receiveโ€‹

The server must enable voiceReceive.enabled and choose a supported format such as opus or pcm_s16le. The player must be connected to the intended Discord voice channel before receiving speaker audio.

import { ManagerEventTypes } from "magmastream";

if (!player.node.isNodeLink) {
throw new Error("Voice receive requires NodeLink.");
}

manager.on(ManagerEventTypes.VoiceReceiverData, (eventPlayer, frame) => {
if (eventPlayer.guildId !== player.guildId) return;
// frame.data is binary audio in frame.type, not a text/base64 payload.
console.log(frame.userId, frame.type, frame.data.length);
});

manager.on(ManagerEventTypes.VoiceReceiverError, (eventPlayer, error) => {
console.error(eventPlayer.guildId, error);
});

await player.setupVoiceReceiver();

The receiver uses the node's authenticated /v4/websocket/voice/<guildId> socket. Binary start/audio/stop frames are parsed by the client. Legacy JSON speaking payloads remain accepted.

Receiver Eventsโ€‹

EventArguments
voiceReceiverConnectplayer
voiceReceiverDisconnectplayer
voiceReceiverErrorplayer, error
voiceReceiverStartSpeakingplayer, data
voiceReceiverDataplayer, frame: VoiceReceiverData
voiceReceiverEndSpeakingplayer, data

Speaking refers to the received speaker, not the bot beginning playback. Live frames contain guildId, userId, data: Buffer, format, SSRC, and timestamp. Binary stop events include accumulated audio as a Buffer. The public start/end callback tuples remain typed as unknown, so validate them before use.

Opus packets are not automatically a playable Ogg/WAV file. PCM needs the server's sample-rate/channel configuration. Do not blindly concatenate either format and label it as a different codec.

The client buffers speaking chunks until a stop event. Process live frames promptly, apply your own recording limits, and remove the receiver when it is no longer needed:

await player.removeVoiceReceiver();

Destroying a player also clears receiver resources. Handle reconnect/error events and obtain appropriate consent before recording Discord users.

Native Gateway Eventsโ€‹

The dedicated manager callbacks cover mixer, connection diagnostics, worker failure, volume/filter/seek/pause updates, player lifecycle, Eternal Box, and stream metadata. See the exact argument tuples in ManagerEvents.

import { ManagerEventTypes } from "magmastream";

manager.on(ManagerEventTypes.NodeLinkVolumeChanged, (eventPlayer, payload) => {
console.log(eventPlayer.guildId, payload);
});

manager.on(ManagerEventTypes.NodeLinkEvent, (node, payload) => {
console.log(node.options.identifier, payload.type);
});

Recognized volume, pause, seek, filter, and lifecycle events synchronize local player state. Global events without a guild ID are supported where applicable.

nodeLinkEvent forwards native events and unknown/plugin event payloads. Unknown NodeLink event names are not reported as ordinary unknown-event nodeError failures. Use dedicated callbacks for typed handling; the generic callback does not replace every standard track/lyrics callback.

Standard Player Updatesโ€‹

playerUpdate is emitted for both Lavalink and NodeLink:

import { ManagerEventTypes } from "magmastream";

manager.on(ManagerEventTypes.PlayerUpdate, (eventPlayer, message) => {
console.log(eventPlayer.guildId, message.state.position, message.state.connected);
});

message.state.connected is the server's voice-transport observation. Since 2.10.4, these periodic packets update position but do not overwrite the library's player.state lifecycle. Explicit connection operations, voice leave/socket closure, and native NodeLink lifecycle events retain their state handling. Track-start callbacks do not force a connection or guarantee that Discord is already receiving audio. Reconnect through the normal connection flow or native lifecycle event rather than relying on periodic telemetry to change state.

Lyrics, chapter, and SponsorBlock callbacks may have no usable current track. Check for null; do not assume those events always accompany active playback.