Skip to main content

Overview

The VoiceUtils class provides utilities for managing voice connections, joining voice channels, and creating stream dispatchers. It’s the core interface for voice connectivity in Discord Player.

Constructor

new VoiceUtils(player: Player)
player
Player
required
The Discord Player instance
VoiceUtils is automatically instantiated by the Player. Access it via player.voiceUtils.

Properties

player

The Discord Player instance.
voiceUtils.player: Player

cache

This property is deprecated and will be removed in a future version. It only exists for compatibility reasons.
Voice connection cache storing stream dispatchers.
voiceUtils.cache: Collection<Snowflake, StreamDispatcher>

Methods

connect()

Joins a voice channel and creates a stream dispatcher for audio playback.
await voiceUtils.connect(
  channel: VoiceChannel | StageChannel,
  options?: ConnectOptions
): Promise<StreamDispatcher>
channel
VoiceChannel | StageChannel
required
The voice or stage channel to join
options
ConnectOptions
Connection options
options.queue
GuildQueue
required
The guild queue instance
options.deaf
boolean
default:false
Whether the bot should be deafened
options.maxTime
number
Maximum connection time in milliseconds
options.audioPlayer
AudioPlayer
Custom audio player instance
options.group
string
Connection group identifier
options.daveEncryption
boolean
default:true
Enable DAVE E2E encryption
options.decryptionFailureTolerance
number
default:24
Number of consecutive decryption failures before disconnecting
dispatcher
StreamDispatcher
The stream dispatcher for managing audio playback

Example

const channel = interaction.member.voice.channel;
const queue = player.queues.cache.get(interaction.guildId);

const dispatcher = await player.voiceUtils.connect(channel, {
  queue: queue,
  deaf: true
});

console.log('Connected to voice channel');

join()

Joins a voice channel and returns the voice connection (without creating a stream dispatcher).
await voiceUtils.join(
  channel: VoiceChannel | StageChannel,
  options?: JoinOptions
): Promise<VoiceConnection>
channel
VoiceChannel | StageChannel
required
The voice or stage channel to join
options
JoinOptions
Join options
options.deaf
boolean
default:false
Whether the bot should be deafened
options.maxTime
number
Maximum connection time in milliseconds
options.group
string
Connection group identifier
options.daveEncryption
boolean
default:true
Enable DAVE E2E encryption for voice data
options.decryptionFailureTolerance
number
default:24
Number of consecutive decryption failures allowed before automatic disconnect
connection
VoiceConnection
The voice connection instance

Example

const channel = interaction.member.voice.channel;

// Join without creating a dispatcher
const connection = await player.voiceUtils.join(channel, {
  deaf: true,
  daveEncryption: true,
  decryptionFailureTolerance: 50
});

console.log('Joined voice channel');
If an existing connection to the same channel exists and is not destroyed, it will be reused instead of creating a new connection.

disconnect()

Disconnects from a voice channel.
voiceUtils.disconnect(connection: VoiceConnection | StreamDispatcher): void
connection
VoiceConnection | StreamDispatcher
required
The voice connection or stream dispatcher to disconnect

Example

const connection = player.voiceUtils.getConnection(guildId);

if (connection) {
  player.voiceUtils.disconnect(connection);
  console.log('Disconnected from voice');
}

// Or disconnect a dispatcher
const dispatcher = queue.dispatcher;
if (dispatcher) {
  player.voiceUtils.disconnect(dispatcher);
}
If you pass a StreamDispatcher, it will automatically extract and destroy the underlying VoiceConnection.

getConnection()

Retrieves an active voice connection for a guild.
voiceUtils.getConnection(guild: Snowflake, group?: string): VoiceConnection | undefined
guild
Snowflake
required
The guild ID
group
string
The connection group identifier (if using groups)
connection
VoiceConnection | undefined
The voice connection if it exists, otherwise undefined

Example

const connection = player.voiceUtils.getConnection(interaction.guildId);

if (connection) {
  console.log(`Connected to channel: ${connection.joinConfig.channelId}`);
  console.log(`Status: ${connection.state.status}`);
} else {
  console.log('Not connected to any voice channel');
}

// With connection groups
const groupedConnection = player.voiceUtils.getConnection(
  interaction.guildId,
  'music-bot'
);

Complete Usage Example

import { Player, GuildQueue } from 'discord-player';
import { VoiceConnectionStatus } from 'discord-voip';

const player = new Player(client);

// Play command handler
client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;
  if (interaction.commandName !== 'play') return;

  const channel = interaction.member.voice.channel;
  if (!channel) {
    return interaction.reply('You need to be in a voice channel!');
  }

  const query = interaction.options.getString('song', true);

  // Create or get queue
  let queue = player.queues.cache.get(interaction.guildId);
  
  if (!queue) {
    queue = player.queues.create(interaction.guildId);
  }

  // Connect to voice channel
  try {
    const dispatcher = await player.voiceUtils.connect(channel, {
      queue: queue,
      deaf: true,
      daveEncryption: true // Enable E2E encryption
    });

    // Search and play
    const result = await player.search(query);
    queue.addTrack(result.tracks[0]);
    
    if (!queue.isPlaying()) {
      await queue.node.play();
    }

    await interaction.reply(`Now playing: ${result.tracks[0].title}`);
  } catch (error) {
    console.error('Failed to connect:', error);
    await interaction.reply('Could not join voice channel!');
  }
});

// Disconnect command
client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;
  if (interaction.commandName !== 'disconnect') return;

  const connection = player.voiceUtils.getConnection(interaction.guildId);
  
  if (!connection) {
    return interaction.reply('Not connected to voice!');
  }

  player.voiceUtils.disconnect(connection);
  await interaction.reply('Disconnected from voice channel');
});

// Monitor connection status
const connection = player.voiceUtils.getConnection(guildId);

if (connection) {
  connection.on('stateChange', (oldState, newState) => {
    console.log(`Connection state changed: ${oldState.status} -> ${newState.status}`);
    
    if (newState.status === VoiceConnectionStatus.Disconnected) {
      console.log('Connection lost, attempting to reconnect...');
    }
  });
}

Connection Groups

Connection groups allow you to manage multiple voice connections per guild (useful for multi-instance bots).
// Connect to a specific group
const dispatcher = await player.voiceUtils.connect(channel, {
  queue: queue,
  group: 'music-bot-1'
});

// Get connection from a specific group
const connection = player.voiceUtils.getConnection(guildId, 'music-bot-1');

// Each group maintains its own connection
const secondDispatcher = await player.voiceUtils.connect(otherChannel, {
  queue: otherQueue,
  group: 'music-bot-2'
});

DAVE Encryption

DAVE (Discord Audio/Video E2EE) provides end-to-end encryption for voice data.
// Enable DAVE encryption (default: true)
const dispatcher = await player.voiceUtils.connect(channel, {
  queue: queue,
  daveEncryption: true,
  decryptionFailureTolerance: 50 // Allow 50 consecutive failures
});
daveEncryption
boolean
default:true
When enabled, voice data is end-to-end encrypted
decryptionFailureTolerance
number
default:24
Number of consecutive decryption failures before automatic disconnect. Higher values are more tolerant of network issues but may result in longer periods of garbled audio.

Types

ConnectOptions

interface ConnectOptions {
  deaf?: boolean;
  maxTime?: number;
  queue: GuildQueue;
  audioPlayer?: AudioPlayer;
  group?: string;
  daveEncryption?: boolean;
  decryptionFailureTolerance?: number;
}

JoinOptions

interface JoinOptions {
  deaf?: boolean;
  maxTime?: number;
  group?: string;
  daveEncryption?: boolean;
  decryptionFailureTolerance?: number;
}

Build docs developers (and LLMs) love