Direct access to networking components for advanced use cases, including WebSocket and UDP socket management, protocol handling, connection state control, and low-level Discord voice protocol implementation.
Core networking class that manages the complete Discord voice connection lifecycle.
/**
* Manages Discord voice connection networking including WebSocket and UDP components
*/
class Networking extends EventEmitter {
/** Current networking state */
readonly state: NetworkingState;
/**
* Create a new networking instance
* @param connectionOptions - Discord voice connection configuration
* @param options - Additional networking options
*/
constructor(connectionOptions: ConnectionOptions, options: NetworkingOptions);
/** Destroy the networking instance and all components */
destroy(): void;
/**
* Prepare an Opus audio packet for transmission
* @param opusPacket - Raw Opus audio data
* @returns Prepared packet buffer or undefined if not ready
*/
prepareAudioPacket(opusPacket: Buffer): Buffer | undefined;
/**
* Dispatch previously prepared audio packet
* @returns true if packet was sent successfully
*/
dispatchAudio(): boolean;
/**
* Set speaking status for this connection
* @param speaking - Whether currently speaking/sending audio
*/
setSpeaking(speaking: boolean): void;
}
interface ConnectionOptions {
/** Voice channel ID */
channelId: string;
/** Discord voice server endpoint */
endpoint: string;
/** Voice server ID */
serverId: string;
/** Voice session ID from gateway */
sessionId: string;
/** Voice connection token from gateway */
token: string;
/** Bot user ID */
userId: string;
}
interface NetworkingOptions {
/** Enable DAVE end-to-end encryption (default: true) */
daveEncryption?: boolean;
/** Enable debug logging (default: false) */
debug?: boolean;
/** Decryption failure tolerance for DAVE (default: 24) */
decryptionFailureTolerance?: number;
}Usage Example:
import { Networking } from "@discordjs/voice";
// Create networking instance (typically done internally by VoiceConnection)
const networking = new Networking(
{
channelId: "123456789012345678",
endpoint: "discord-voice-server.discord.gg",
serverId: "server-id-here",
sessionId: "session-id-here",
token: "voice-token-here",
userId: "bot-user-id-here",
},
{
daveEncryption: true,
debug: true,
decryptionFailureTolerance: 24,
}
);
// Monitor networking state
networking.on("stateChange", (oldState, newState) => {
console.log(`Networking: ${oldState.code} -> ${newState.code}`);
});
// Prepare and send audio
const opusPacket = Buffer.from(/* opus audio data */);
const preparedPacket = networking.prepareAudioPacket(opusPacket);
if (preparedPacket) {
networking.dispatchAudio();
}Comprehensive state management for voice connection lifecycle.
enum NetworkingStatusCode {
/** Opening WebSocket connection to voice gateway */
OpeningWs,
/** Identifying with voice gateway */
Identifying,
/** Performing UDP handshake for audio transmission */
UdpHandshaking,
/** Selecting voice protocol and encryption */
SelectingProtocol,
/** Ready for audio transmission and reception */
Ready,
/** Resuming existing voice connection */
Resuming,
/** Connection closed */
Closed
}
type NetworkingState =
| NetworkingOpeningWsState
| NetworkingIdentifyingState
| NetworkingUdpHandshakingState
| NetworkingSelectingProtocolState
| NetworkingReadyState
| NetworkingResumingState
| NetworkingClosedState;
interface NetworkingOpeningWsState {
code: NetworkingStatusCode.OpeningWs;
ws: VoiceWebSocket;
connectionOptions: ConnectionOptions;
}
interface NetworkingIdentifyingState {
code: NetworkingStatusCode.Identifying;
ws: VoiceWebSocket;
connectionOptions: ConnectionOptions;
}
interface NetworkingUdpHandshakingState {
code: NetworkingStatusCode.UdpHandshaking;
ws: VoiceWebSocket;
udp: VoiceUDPSocket;
connectionData: ConnectionData;
connectionOptions: ConnectionOptions;
}
interface NetworkingSelectingProtocolState {
code: NetworkingStatusCode.SelectingProtocol;
ws: VoiceWebSocket;
udp: VoiceUDPSocket;
connectionData: ConnectionData;
connectionOptions: ConnectionOptions;
}
interface NetworkingReadyState {
code: NetworkingStatusCode.Ready;
ws: VoiceWebSocket;
udp: VoiceUDPSocket;
connectionData: ConnectionData;
connectionOptions: ConnectionOptions;
preparedPacket?: Buffer;
dave?: DAVESession;
}
interface NetworkingResumingState {
code: NetworkingStatusCode.Resuming;
ws: VoiceWebSocket;
udp: VoiceUDPSocket;
connectionData: ConnectionData;
connectionOptions: ConnectionOptions;
preparedPacket?: Buffer;
dave?: DAVESession;
}
interface NetworkingClosedState {
code: NetworkingStatusCode.Closed;
}WebSocket wrapper for Discord voice gateway communication.
/**
* WebSocket wrapper for Discord voice gateway
*/
class VoiceWebSocket extends EventEmitter {
/** Last recorded ping in milliseconds */
ping?: number;
/** Last acknowledged sequence number */
sequence: number;
/**
* Create voice WebSocket connection
* @param address - WebSocket address to connect to
* @param debug - Enable debug logging
*/
constructor(address: string, debug: boolean);
/** Destroy the WebSocket connection */
destroy(): void;
/**
* Handle incoming message from WebSocket
* @param event - WebSocket message event
*/
onMessage(event: MessageEvent): void;
/**
* Send JSON packet to voice gateway
* @param packet - Voice gateway payload to send
*/
sendPacket(packet: VoiceSendPayload): void;
/**
* Send binary message to voice gateway
* @param opcode - Voice opcode for the message
* @param payload - Binary payload data
*/
sendBinaryMessage(opcode: VoiceOpcodes, payload: Buffer): void;
/**
* Set or clear heartbeat interval
* @param ms - Heartbeat interval in milliseconds, or -1 to clear
*/
setHeartbeatInterval(ms: number): void;
}
// Voice WebSocket Events
interface VoiceWebSocket extends EventEmitter {
/** Emitted when connection encounters an error */
on(event: "error", listener: (error: Error) => void): this;
/** Emitted when WebSocket connection opens */
on(event: "open", listener: () => void): this;
/** Emitted when WebSocket connection closes */
on(event: "close", listener: (code: number, reason: string) => void): this;
/** Emitted for debug messages */
on(event: "debug", listener: (message: string) => void): this;
/** Emitted when JSON packet is received */
on(event: "packet", listener: (packet: VoiceReceivePayload) => void): this;
/** Emitted when binary message is received */
on(event: "binary", listener: (message: BinaryWebSocketMessage) => void): this;
}
interface BinaryWebSocketMessage {
op: VoiceOpcodes;
payload: Buffer;
seq: number;
}Usage Example:
import { VoiceWebSocket } from "@discordjs/voice";
const ws = new VoiceWebSocket("wss://voice-gateway.discord.gg", true);
ws.on("open", () => {
console.log("Voice WebSocket connected");
});
ws.on("packet", (packet) => {
console.log("Received packet:", packet.op);
});
ws.on("close", (code, reason) => {
console.log(`WebSocket closed: ${code} - ${reason}`);
});
// Send identify packet
ws.sendPacket({
op: VoiceOpcodes.Identify,
d: {
server_id: "server-id",
user_id: "user-id",
session_id: "session-id",
token: "voice-token",
},
});UDP socket manager for audio packet transmission.
/**
* UDP socket for Discord voice audio transmission
*/
class VoiceUDPSocket extends EventEmitter {
/** Deprecated ping measurement */
ping?: number;
/**
* Create UDP socket connection to Discord voice server
* @param remote - Remote socket configuration (IP and port)
*/
constructor(remote: SocketConfig);
/**
* Send buffer to Discord voice server
* @param buffer - Audio or control data to send
*/
send(buffer: Buffer): void;
/** Close the UDP socket */
destroy(): void;
/**
* Perform IP discovery to determine external IP and port
* @param ssrc - SSRC identifier for this connection
* @returns Promise resolving to discovered socket configuration
*/
performIPDiscovery(ssrc: number): Promise<SocketConfig>;
}
interface SocketConfig {
/** IP address */
ip: string;
/** Port number */
port: number;
}
/**
* Parse IP discovery response packet
* @param message - Response buffer from IP discovery
* @returns Parsed socket configuration
*/
function parseLocalPacket(message: Buffer): SocketConfig;
// Voice UDP Socket Events
interface VoiceUDPSocket extends EventEmitter {
/** Emitted when socket encounters an error */
on(event: "error", listener: (error: Error) => void): this;
/** Emitted when socket is closed */
on(event: "close", listener: () => void): this;
/** Emitted for debug messages */
on(event: "debug", listener: (message: string) => void): this;
/** Emitted when message is received */
on(event: "message", listener: (message: Buffer) => void): this;
}Usage Example:
import { VoiceUDPSocket, parseLocalPacket } from "@discordjs/voice";
const udp = new VoiceUDPSocket({ ip: "162.159.130.1", port: 50001 });
udp.on("message", (message) => {
console.log("Received UDP message:", message.length, "bytes");
});
// Perform IP discovery
const ssrc = 12345;
const localConfig = await udp.performIPDiscovery(ssrc);
console.log("Discovered local IP:", localConfig.ip, "port:", localConfig.port);
// Send audio packet
const audioPacket = Buffer.from(/* encrypted audio data */);
udp.send(audioPacket);Runtime connection information and state data.
interface ConnectionData {
/** Set of connected client user IDs */
connectedClients: Set<string>;
/** Voice encryption mode being used */
encryptionMode: string;
/** Current nonce for encryption */
nonce: number;
/** Nonce buffer for encryption operations */
nonceBuffer: Buffer;
/** Number of audio packets sent */
packetsPlayed: number;
/** Encryption secret key */
secretKey: Uint8Array;
/** RTP sequence number */
sequence: number;
/** Current speaking status */
speaking: boolean;
/** SSRC identifier for this connection */
ssrc: number;
/** RTP timestamp */
timestamp: number;
}
/** Supported voice encryption modes */
const SUPPORTED_ENCRYPTION_MODES: VoiceEncryptionMode[];For advanced use cases, you can implement custom networking behavior:
import { Networking, NetworkingStatusCode } from "@discordjs/voice";
class CustomNetworking extends Networking {
constructor(connectionOptions, options) {
super(connectionOptions, options);
// Override state change handling
this.on("stateChange", (oldState, newState) => {
if (newState.code === NetworkingStatusCode.Ready) {
console.log("Custom networking ready for audio");
this.setupCustomAudioProcessing();
}
});
}
prepareAudioPacket(opusPacket) {
// Custom packet preparation logic
const prepared = super.prepareAudioPacket(opusPacket);
if (prepared) {
// Add custom headers or processing
return this.addCustomHeaders(prepared);
}
return prepared;
}
private addCustomHeaders(packet) {
// Custom implementation
return packet;
}
private setupCustomAudioProcessing() {
// Custom audio processing setup
}
}For maximum control, work directly with WebSocket and UDP components:
import { VoiceWebSocket, VoiceUDPSocket, VoiceOpcodes } from "@discordjs/voice";
// Direct WebSocket control
const ws = new VoiceWebSocket("wss://voice-server.discord.gg", true);
const udp = new VoiceUDPSocket({ ip: "127.0.0.1", port: 50001 });
ws.on("packet", (packet) => {
switch (packet.op) {
case VoiceOpcodes.Ready:
console.log("Voice ready, starting UDP handshake");
break;
case VoiceOpcodes.SessionDescription:
console.log("Received session description");
break;
case VoiceOpcodes.Speaking:
console.log("Speaking update:", packet.d);
break;
}
});
// Custom packet handling
ws.sendPacket({
op: VoiceOpcodes.SelectProtocol,
d: {
protocol: "udp",
data: {
address: "192.168.1.1",
port: 1234,
mode: "aead_aes256_gcm_rtpsize",
},
},
});Handle networking errors appropriately:
networking.on("error", (error) => {
console.error("Networking error:", error);
});
networking.on("close", () => {
console.log("Networking connection closed");
});
ws.on("error", (error) => {
console.error("WebSocket error:", error);
});
udp.on("error", (error) => {
console.error("UDP error:", error);
});