Core functionality for establishing and managing Discord voice connections, including joining channels, handling disconnections, reconnections, and managing connection state throughout the lifecycle.
Creates and establishes a connection to a Discord voice channel with comprehensive configuration options.
/**
* Creates a VoiceConnection to a Discord voice channel
* @param options - Configuration for joining the voice channel and connection behavior
* @returns VoiceConnection instance for the established connection
*/
function joinVoiceChannel(options: CreateVoiceConnectionOptions & JoinVoiceChannelOptions): VoiceConnection;
interface CreateVoiceConnectionOptions {
/** Discord gateway adapter creator function */
adapterCreator: DiscordGatewayAdapterCreator;
/** Whether to use DAVE protocol for end-to-end encryption (default: true) */
daveEncryption?: boolean;
/** Enable debug messages for connection and components (default: false) */
debug?: boolean;
/** Consecutive decryption failures before re-initializing encrypted session (default: 24) */
decryptionFailureTolerance?: number;
}
interface JoinVoiceChannelOptions {
/** Discord voice channel ID to join */
channelId: string;
/** Guild ID that contains the voice channel */
guildId: string;
/** Optional group identifier for organizing connections (default: "default") */
group?: string;
/** Join the channel deafened (default: true) */
selfDeaf?: boolean;
/** Join the channel muted (default: true) */
selfMute?: boolean;
}Usage Example:
import { joinVoiceChannel } from "@discordjs/voice";
// Basic voice channel join
const connection = joinVoiceChannel({
channelId: "123456789012345678",
guildId: "987654321098765432",
adapterCreator: guild.voiceAdapterCreator,
});
// Advanced configuration with DAVE encryption disabled
const connection = joinVoiceChannel({
channelId: "123456789012345678",
guildId: "987654321098765432",
adapterCreator: guild.voiceAdapterCreator,
daveEncryption: false,
debug: true,
selfDeaf: false,
selfMute: false,
group: "music-bots",
});Main class representing an active voice connection with full lifecycle management.
class VoiceConnection extends EventEmitter {
/** Current connection state */
readonly state: VoiceConnectionState;
/** Join configuration used for this connection */
readonly joinConfig: JoinConfig;
/** Voice receiver for incoming audio (when connection is ready) */
readonly receiver: VoiceReceiver;
/** Destroy the connection permanently (cannot be reused) */
destroy(): void;
/** Disconnect temporarily (can be reconnected) */
disconnect(): VoiceConnectionDisconnectReason;
/** Rejoin voice channel with new configuration */
rejoin(joinConfig?: JoinConfig): void;
/** Subscribe an AudioPlayer to this connection */
subscribe(player: AudioPlayer): PlayerSubscription;
/** Unsubscribe the current AudioPlayer */
unsubscribe(): void;
/** Configure network and encryption components */
configureNetworking(): void;
/** Set speaking status for this connection */
setSpeaking(speaking: boolean): void;
/** Play an Opus audio packet directly */
playOpusPacket(opusPacket: Buffer): void;
}
// Connection state interfaces
type VoiceConnectionState =
| VoiceConnectionSignallingState
| VoiceConnectionConnectingState
| VoiceConnectionReadyState
| VoiceConnectionDisconnectedState
| VoiceConnectionDestroyedState;
interface VoiceConnectionSignallingState {
status: VoiceConnectionStatus.Signalling;
adapter: DiscordGatewayAdapterImplementerMethods;
subscription?: PlayerSubscription;
}
interface VoiceConnectionConnectingState {
status: VoiceConnectionStatus.Connecting;
adapter: DiscordGatewayAdapterImplementerMethods;
networking: Networking;
subscription?: PlayerSubscription;
}
interface VoiceConnectionReadyState {
status: VoiceConnectionStatus.Ready;
adapter: DiscordGatewayAdapterImplementerMethods;
networking: Networking;
subscription?: PlayerSubscription;
}
interface VoiceConnectionDisconnectedState {
status: VoiceConnectionStatus.Disconnected;
adapter: DiscordGatewayAdapterImplementerMethods;
reason: VoiceConnectionDisconnectReason;
closeCode?: number;
subscription?: PlayerSubscription;
}
interface VoiceConnectionDestroyedState {
status: VoiceConnectionStatus.Destroyed;
}Usage Example:
import { VoiceConnectionStatus, entersState } from "@discordjs/voice";
// Monitor connection state changes
connection.on("stateChange", (oldState, newState) => {
console.log(`Connection state changed from ${oldState.status} to ${newState.status}`);
});
// Wait for connection to be ready
try {
await entersState(connection, VoiceConnectionStatus.Ready, 30_000);
console.log("Connection is ready!");
} catch (error) {
console.error("Failed to connect within 30 seconds");
}
// Handle disconnections
connection.on(VoiceConnectionStatus.Disconnected, () => {
console.log("Connection lost, attempting to reconnect...");
connection.rejoin();
});Functions for retrieving existing voice connections and managing connection groups.
/**
* Retrieves an existing voice connection for a guild
* @param guildId - Guild ID to search for
* @param group - Optional group name (default: "default")
* @returns VoiceConnection if found, undefined otherwise
*/
function getVoiceConnection(guildId: string, group?: string): VoiceConnection | undefined;
/**
* Gets all voice connections for a specific group
* @param group - Group name (default: "default")
* @returns ReadonlyMap of guild ID to VoiceConnection
*/
function getVoiceConnections(group?: string): ReadonlyMap<string, VoiceConnection>;
/**
* Gets all connection groups
* @returns Map of group names to guild ID -> VoiceConnection maps
*/
function getGroups(): ReadonlyMap<string, ReadonlyMap<string, VoiceConnection>>;Usage Example:
// Check if connection already exists
const existingConnection = getVoiceConnection("123456789012345678");
if (existingConnection) {
console.log("Already connected to this guild");
} else {
// Create new connection
const connection = joinVoiceChannel({
channelId: "123456789012345678",
guildId: "987654321098765432",
adapterCreator: guild.voiceAdapterCreator,
});
}
// Get all connections in default group
const allConnections = getVoiceConnections();
console.log(`Active connections: ${allConnections.size}`);
// Work with grouped connections
const musicBotConnections = getVoiceConnections("music-bots");
for (const [guildId, connection] of musicBotConnections) {
console.log(`Guild ${guildId}: ${connection.state.status}`);
}Enums and interfaces defining connection states and disconnection reasons.
enum VoiceConnectionStatus {
/** Sending gateway packets to indicate voice state change */
Signalling = "signalling",
/** Attempting to establish voice connection after receiving gateway packets */
Connecting = "connecting",
/** Voice connection established and ready for audio */
Ready = "ready",
/** Voice connection severed or not established */
Disconnected = "disconnected",
/** Voice connection destroyed permanently and untracked */
Destroyed = "destroyed"
}
enum VoiceConnectionDisconnectReason {
/** WebSocket connection was closed */
WebSocketClose,
/** Adapter was unable to send required message */
AdapterUnavailable,
/** VOICE_SERVER_UPDATE packet received with null endpoint */
EndpointRemoved,
/** Manual disconnect was requested */
Manual
}System for linking AudioPlayers to voice connections.
class PlayerSubscription {
/** The voice connection this subscription is associated with */
readonly connection: VoiceConnection;
/** The audio player this subscription is associated with */
readonly player: AudioPlayer;
/** Remove this subscription, unlinking player from connection */
unsubscribe(): void;
}Usage Example:
import { createAudioPlayer } from "@discordjs/voice";
const player = createAudioPlayer();
const subscription = connection.subscribe(player);
// Later, unsubscribe when done
subscription.unsubscribe();
// or
connection.unsubscribe();Voice connections can fail for various reasons. Handle errors appropriately:
connection.on("error", (error) => {
console.error("Voice connection error:", error);
});
connection.on(VoiceConnectionStatus.Disconnected, (oldState, newState) => {
if (newState.reason === VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {
console.error("Disconnected: Do not have permission to connect to voice channel");
}
});