Skip to content

Voice‐WebSocket

SNIPPIK edited this page Dec 7, 2025 · 1 revision

VoiceWebSocket

VoiceWebSocket — основной класс библиотеки, отвечающий за установку, поддержку и обработку WebSocket-соединения с голосовым шлюзом Discord (Discord Voice Gateway) по протоколу версии 8.

Класс реализует полное управление жизненным циклом голосового соединения, включая идентификацию, heartbeat-механизм, обработку всех стандартных и Dave-протокольных опкодов, а также автоматическое переподключение при разрывах. Наследуется от TypedEmitter — строготипизированного EventEmitter из внутренней структуры проекта.

Основные особенности

  • Полная поддержка Discord Voice Gateway v8
  • Автоматический heartbeat с расчётом средней задержки (latency)
  • Обработка бинарных Dave-пакетов (MLS/E2EE)
  • Умная обработка кодов закрытия (игнорирование безопасных кодов 4014 и 4022)
  • Возможность resume-сессии при переподключении
  • Детальная отладочная информация через события debug и warn

public constructor()

Создаёт экземпляр VoiceWebSocket и инициализирует внутренний HeartbeatManager с коллбэками:

  • send — отправка пакета op: 5 (Heartbeat)
  • onAck — обработка HEARTBEAT_ACK, расчёт и хранение средней latency за последние 10 измерений
  • onTimeout — эмит события при отсутствии timely HEARTBEAT_ACK с последующим переподключением

Публичные свойства и геттеры

Свойство Тип Описание
status WebSocketStatus (геттер) Текущий статус соединения (idle → connecting → connected → closed → reconnecting)
sequence number Последний полученный seq от Discord (используется для resume)
latency number | null Текущая средняя задержка в миллисекундах (усреднение за 10 последних heartbeat)
packet setter Удобный способ отправки пакетов (автоматически JSON-сериализует или отправляет Buffer)

Основные публичные методы

Метод Описание
connect(endpoint: string, code?: GatewayCloseCodes): void Устанавливает новое WebSocket-соединение по указанному wss://... эндпоинту. При code логирует причину переподключения.
reset(): void «Мягкое» закрытие текущего соединения: удаляет все слушатели, gracefully закрывает ws, очищает heartbeat и latency.
destroy(): void Полное уничтожение экземпляра: вызывает reset(), уничтожает heartbeat-менеджер и обнуляет все внутренние поля.

Внутренние обработчики

  • onReceiveMessage
Обрабатывает как текстовые JSON-пакеты, так и бинарные Dave-пакеты:
При бинарных данных — парсит заголовок (sequence + op) и эмитит событие binary
При JSON — обновляет sequence, обрабатывает стандартные опкоды и эмитит соответствующие события

Поддерживаемые опкоды и их события:

Opcode (VoiceOpcodes) Событие Описание
HeartbeatAck (9) — (внутренняя обработка) Подтверждение heartbeat → расчёт latency
Hello (8) — Получение heartbeat_interval → запуск heartbeat-менеджера
Ready (2) ready Готовность голосового соединения
SessionDescription (4) sessionDescription Получение ключей шифрования и параметров RTP
Speaking (5) speaking Кто-то начал/закончил говорить
ClientConnect / ClientDisconnect UsersRJC Пользователь присоединился или покинул канал
Все Dave-опкоды (30–43) daveSession Пакеты MLS/E2EE (Dave protocol)
  • onReceiveClose
Обрабатывает закрытие соединения.
Если код закрытия находится в GatewayCloseCodesIgnore (4014, 4022) — соединение считается «нормально» разорванным и переподключение не требуется.
В остальных случаях эмитится событие close.

События (ClientWebSocketEvents)

Событие Параметры Когда срабатывает
open — Успешное открытие WebSocket (readyState === OPEN)
close (code: GatewayCloseCodes, reason: string) Соединение закрыто (кроме игнорируемых кодов)
error (err: Error) Любая ошибка WebSocket или парсинга
warn (text: string) Предупреждения (heartbeat timeout, переподключение и т.д.)
debug (state: string, text: any) Отладочная информация (входящие/исходящие пакеты)
ready (opcodes: WebSocketOpcodes.ready) Получен опкод 2 (Ready)
sessionDescription (opcodes: WebSocketOpcodes.session) Получен опкод 4 (Session Description)
speaking (d: WebSocketOpcodes.speaking_get) Кто-то говорит/перестал говорить
UsersRJC (d: WebSocketOpcodes.connect | disconnect) Пользователь присоединился или отключился
daveSession (opcodes: WebSocketOpcodes.dave_opcodes) Любой Dave-пакет (MLS/E2EE)
binary { op, payload: Buffer } Бинарный Dave-пакет (сырые данные без JSON-парсинга)