Skip to content

Repository files navigation

npm versionlicensedownloads

Discord voice client

  • Работает на любых библиотеках такие как discord.js, seyfert, eris...
  • Нет поддержки плеера, но готовая реализация есть тут

🎧 Основные возможности

🔊 Голосовой движок

  • Реализация Voice Gateway Version 8(WebSocket + UDP + SRTP + Opus + Sodium) + End-to-End Encryption (DAVE Protocol)
  • Полная реализация SRTP: aead_aes256_gcm, xchacha20_poly1305 (через библиотеки)
  • Адаптивная система отправки пакетов, без полноценного WebRTP ничего толкового не сделать!
  • Работает с готовыми Ogg/Opus фреймами!
  • Требуется FFmpeg, он отвечает за аудио!
  • Работает даже при сильном event loop lag

🎵 Аудио

  • Есть свой парсер Ogg/Opus для получения чистого opus!
  • Есть возможность переиспользовать аудио без конвертации
  • Есть поддержка длинных видео, Live видео пока сыровато.

Warning

Это компонент из другого проекта UnTitles, данный модуль предоставляется как есть!

Tip

Вам потребуется AudioPlayer!!! Без него отправка аудио фреймов будет затруднительна
Рекомендуется отправлять аудио фреймы через 20 ms от прошло фрейма

📦 Установка

npm install discord-voice-client

Discord.js

import{BufferedAudioResource,PipeAudioResource,VoiceConnection}from"discord-voice-client";import{TaskCycle}from"snpk-cycle";// Проще из-за нативной поддержки adaptersconstadapter=message.guild.voiceAdapterCreator;constconfig={self_deaf: true,self_mute: false,guild_id: guild.id,channel_id: message.voice.channel.id};// Голосовое подключение готовоconstvoice=newVoiceConnection(config,adapter);// Debugvoice.websocket.on("debug",console.log);voice.websocket.on("warn",console.log);// Буферезированный аудио потокconstbufferedAudio=newBufferedAudioResource("urlOrPathFile",{seek: 10,filters: null});// Прямой аудио поток из ffmpeg с буфером в 14 секconstpipeAudio=newPipeAudioResource("urlOrPathFile",{seek: 10,filters: null});// Как отправлять циклично пакетыclassSender<TextendsVoiceConnection>extendsTaskCycle<T>{publicconstructor(){super({// Время до следующего прогона циклаduration: 20,drift: false,// Функция проверкиfilter: (item)=>item.ready,// Функция отправки аудио фреймаexecute: (connection)=>{connection.packet=audio.packet}});};};// Отправка пакетовvoice.packet=audio.packet;

Seyfert

  • Реализация voiceAdapterCreator
import{GatewayVoiceServerUpdateDispatchData,GatewayVoiceStateUpdateDispatchData}from"discord-api-types/v10";import{DiscordClient}from"../client";// Класс вашего клиента/** * @description Класс для взаимодействия с клиентским websocket'ом * @class VoiceManager */exportclassVoiceManager<ClientextendsDiscordClient>{/** * @description Коллекция адаптеров для общения голоса с клиентским websocket'ом * @readonly * @private */publicreadonlyadapters=newMap<string,DiscordGatewayAdapterLibraryMethods>();/** * @description Копия клиента * @private */privateclient: Client;/** * @description ID осколка * @private */privateshardID: number;/** * @description Создание класса * @param client - Класс клиента */publicconstructor(client: Client){this.client=client;};/** * @description Адаптер состояния голоса для этой гильдии, который можно использовать с `@discordjs/voice` для воспроизведения звука в голосовых и сценических каналах. * @public */publicvoiceAdapterCreator=(guildID: string): DiscordGatewayAdapterCreator=>{// Если нет ID осколкаif(!this.shardID)this.shardID=this.client.gateway.calculateShardId(guildID);returnmethods=>{this.adapters.set(guildID,methods);return{sendPayload: (data)=>{this.client.gateway.send(this.shardID,data);returntrue;},destroy: ()=>{this.adapters.delete(guildID);}};};};/** * @description Функция обновления данных о подключении к голосовому каналу * @param payload - Данные голосового состояния */publiconVoiceServer=(payload: GatewayVoiceServerUpdateDispatchData)=>{this.adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);};/** * @description Функция обновления данных о текущем голосовом состоянии * @param payload - Данные голосового состояния */publiconVoiceStateUpdate=(payload: GatewayVoiceStateUpdateDispatchData)=>{this.adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);};}/** * @description Шлюз Discord Адаптер, шлюза Discord. * @interface DiscordGatewayAdapterLibraryMethods */exportinterfaceDiscordGatewayAdapterLibraryMethods{/** * @description Call this when the adapter can no longer be used (e.g. due to a disconnect from the main gateway) */destroy(): void;/** * @description Call this when you receive a VOICE_SERVER_UPDATE payload that is relevant to the adapter. * @param data - The inner data of the VOICE_SERVER_UPDATE payload */onVoiceServerUpdate(data: GatewayVoiceServerUpdateDispatchData): void;/** * @description Call this when you receive a VOICE_STATE_UPDATE payload that is relevant to the adapter. * @param data - The inner data of the VOICE_STATE_UPDATE payload */onVoiceStateUpdate(data: GatewayVoiceStateUpdateDispatchData): void;}/** * @description Методы, предоставляемые разработчиком адаптера Discord Gateway для DiscordGatewayAdapter. * @interface DiscordGatewayAdapterImplementerMethods */exportinterfaceDiscordGatewayAdapterImplementerMethods{/** * @description Это будет вызвано voice, когда адаптер можно будет безопасно уничтожить, поскольку он больше не будет использоваться. */destroy(): void;/** * @description Реализуйте этот метод таким образом, чтобы данная полезная нагрузка отправлялась на основное соединение Discord gateway. * @param payload - Полезная нагрузка для отправки на основное соединение Discord gateway * @returns `false`, если полезная нагрузка определенно не была отправлена - в этом случае голосовое соединение отключается */sendPayload(payload: any): boolean;}/** * Функция, используемая для создания адаптеров. Она принимает параметр methods, содержащий функции, которые * могут быть вызваны разработчиком при получении новых данных по его шлюзовому соединению. В свою очередь, * разработчик вернет некоторые методы, которые может вызывать библиотека - например, для отправки сообщений на * шлюз или для подачи сигнала о том, что адаптер может быть удален. * @type DiscordGatewayAdapterCreator */exporttypeDiscordGatewayAdapterCreator=(methods: DiscordGatewayAdapterLibraryMethods)=>DiscordGatewayAdapterImplementerMethods;
  • Как использовать реализацию voiceAdapterCreator
/** * @description Реализация клиента discord * @class DiscordClient */exportclassDiscordClientextendsClient{/** * @description Класс для общения с websocket * @public */publicvoice=newVoiceManager(this);//...}// Создадим события для отправки данных в adapterimport{createEvent}from'seyfert';// VOICE_SERVER_UPDATEexportdefaultcreateEvent({data: {name: 'voiceServerUpdate'},asyncrun(packet,client){// Отправляем данные в adapterreturnclient.voice.onVoiceServer({ ...packet,guild_id: packet.guildId});}});// VOICE_STATE_UPDATEexportdefaultcreateEvent({data: {name: 'voiceStateUpdate'},asyncrun(state,client){constpayload=state[0];// Если нет данныхif(!payload)return;// Отправляем данные в adapterclient.voice.onVoiceStateUpdate({session_id: payload.sessionId,channel_id: payload.channelId,guild_id: payload.guildId,user_id: payload.userId,self_stream: payload.selfStream,self_video: payload.selfVideo,self_mute: payload.selfMute,self_deaf: payload.selfDeaf,request_to_speak_timestamp: payload.requestToSpeakTimestamp,deaf: payload.deaf,mute: payload.mute,suppress: payload.suppress,member: null});}});
  • Вот теперь можно отправлять пакеты под seyfert
import{BufferedAudioResource,PipeAudioResource,VoiceConnection,SyncCycle}from"discord-voice-client";import{TaskCycle}from"snpk-cycle";constadapter=client.voice.voiceAdapterCreator(guild.id);constconfig={self_deaf: true,self_mute: false,guild_id: ctx.guildId,channel_id: ctx.member.voice("cache").id};// Голосовое подключение готовоconstvoice=newVoiceConnection(config,adapter);// Буферезированный аудио потокconstbufferedAudio=newBufferedAudioResource("urlOrPathFile",{seek: 10,filters: null});// Прямой аудио поток из ffmpeg с буфером в 14 секconstpipeAudio=newPipeAudioResource("urlOrPathFile",{seek: 10,filters: null});// Как отправлять циклично пакетыclassSender<TextendsVoiceConnection>extendsTaskCycle<T>{publicconstructor(){super({// Время до следующего прогона циклаduration: 20,drift: false,// Функция проверкиfilter: (item)=>item.ready,// Функция отправки аудио фреймаexecute: (connection)=>{// Отправка пакетовconnection.packet=audio.packet}});};};

About

Voice Discord System and more...

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages