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โ
| Event | Arguments |
|---|---|
voiceReceiverConnect | player |
voiceReceiverDisconnect | player |
voiceReceiverError | player, error |
voiceReceiverStartSpeaking | player, data |
voiceReceiverData | player, frame: VoiceReceiverData |
voiceReceiverEndSpeaking | player, 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);
});
Lyrics, chapter, and SponsorBlock callbacks may have no usable current track.
Check for null; do not assume those events always accompany active playback.