{"id":28329320,"url":"https://github.com/snippik/discordvoiceclient","last_synced_at":"2025-06-24T22:31:08.590Z","repository":{"id":294620807,"uuid":"984236428","full_name":"SNIPPIK/DiscordVoiceClient","owner":"SNIPPIK","description":"Voice Discord System and more...","archived":false,"fork":false,"pushed_at":"2025-05-25T15:02:53.000Z","size":66,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-02T21:24:03.011Z","etag":null,"topics":["discord","discord-voice","discordjs","seyfert","seyfert-voice"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SNIPPIK.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-15T15:51:53.000Z","updated_at":"2025-05-25T15:02:57.000Z","dependencies_parsed_at":"2025-05-22T09:33:13.646Z","dependency_job_id":null,"html_url":"https://github.com/SNIPPIK/DiscordVoiceClient","commit_stats":null,"previous_names":["snippik/discordvoiceclient"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SNIPPIK/DiscordVoiceClient","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SNIPPIK%2FDiscordVoiceClient","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SNIPPIK%2FDiscordVoiceClient/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SNIPPIK%2FDiscordVoiceClient/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SNIPPIK%2FDiscordVoiceClient/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SNIPPIK","download_url":"https://codeload.github.com/SNIPPIK/DiscordVoiceClient/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SNIPPIK%2FDiscordVoiceClient/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261766568,"owners_count":23206648,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["discord","discord-voice","discordjs","seyfert","seyfert-voice"],"created_at":"2025-05-26T11:11:52.377Z","updated_at":"2025-06-24T22:31:08.582Z","avatar_url":"https://github.com/SNIPPIK.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm version](https://img.shields.io/npm/v/discord-voice-client)](https://www.npmjs.com/package/discord-voice-client)\n[![license](https://img.shields.io/npm/l/discord-voice-client)](./LICENSE)\n[![downloads](https://img.shields.io/npm/dt/discord-voice-client.svg)](https://www.npmjs.com/package/discord-voice-client)\n\n# Discord voice client\n- Работает на следующих библиотеках (discord.js, seyfert)\n- Нет поддержки плеера, но готовая реализация есть [тут](https://github.com/SNIPPIK/UnTitles)\n- Требуется `FFmpeg`, `Node.js \u003e=23`\n- Используется [`Voice Gateway Version 8`](https://discord.com/developers/docs/topics/voice-connections)\n\n\n\u003e [!TIP]\n\u003e Вам потребуется AudioPlayer!!! Без него отправка аудио фреймов будет затруднительна\\\n\u003e Рекомендуется отправлять аудио фреймы через 20 ms от прошло фрейма\n\n\n## 📦 Установка\n```bash\nnpm install discord-voice-client\n```\n\n## Discord.js\n```ts\nimport {AudioResource, VoiceConnection} from \"discord-voice-client\";\n\n// Проще из-за нативной поддержки adapters\nconst adapter = message.guild.voiceAdapterCreator;\nconst config = {\n    self_deaf: true,\n    self_mute: false,\n    guild_id: guild.id,\n    channel_id: message.voice.channel.id\n};\n\n// Голосовое подключение готово\nconst voice = new VoiceConnection(config, adapter);\nconst audio = new AudioResource(\"urlOrPathFile\", {seek: 10, filters: null});\n\n// Отправка пакетов\nvoice.packet = audio.packet;\n```\n\n\n\n## Seyfert\n- Реализация voiceAdapterCreator\n```ts\nimport {GatewayVoiceServerUpdateDispatchData, GatewayVoiceStateUpdateDispatchData} from \"discord-api-types/v10\";\nimport {DiscordClient} from \"../client\"; // Класс вашего клиента\n\n/**\n * @description Класс для взаимодействия с клиентским websocket'ом\n * @class VoiceManager\n */\nexport class VoiceManager\u003cClient extends DiscordClient\u003e {\n    /**\n     * @description Коллекция адаптеров для общения голоса с клиентским websocket'ом\n     * @readonly\n     * @private\n     */\n    public readonly adapters = new Map\u003cstring, DiscordGatewayAdapterLibraryMethods\u003e();\n\n    /**\n     * @description Копия клиента\n     * @private\n     */\n    private client: Client;\n\n    /**\n     * @description ID осколка\n     * @private\n     */\n    private shardID: number;\n\n    /**\n     * @description Создание класса\n     * @param client - Класс клиента\n     */\n    public constructor(client: Client) {\n        this.client = client;\n    };\n\n    /**\n     * @description Адаптер состояния голоса для этой гильдии, который можно использовать с `@discordjs/voice` для воспроизведения звука в голосовых и сценических каналах.\n     * @public\n     */\n    public voiceAdapterCreator = (guildID: string): DiscordGatewayAdapterCreator =\u003e {\n        // Если нет ID осколка\n        if (!this.shardID) this.shardID = this.client.gateway.calculateShardId(guildID);\n\n        return methods =\u003e {\n            this.adapters.set(guildID, methods);\n\n            return {\n                sendPayload: (data) =\u003e {\n                    this.client.gateway.send(this.shardID, data);\n                    return true;\n                },\n                destroy: () =\u003e {\n                    this.adapters.delete(guildID);\n                }\n            };\n        };\n    };\n\n    /**\n     * @description Функция обновления данных о подключении к голосовому каналу\n     * @param payload - Данные голосового состояния\n     */\n    public onVoiceServer = (payload: GatewayVoiceServerUpdateDispatchData) =\u003e {\n        this.adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);\n    };\n\n    /**\n     * @description Функция обновления данных о текущем голосовом состоянии\n     * @param payload - Данные голосового состояния\n     */\n    public onVoiceStateUpdate = (payload: GatewayVoiceStateUpdateDispatchData) =\u003e {\n        this.adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);\n    };\n}\n\n/**\n * @description Шлюз Discord Адаптер, шлюза Discord.\n * @interface DiscordGatewayAdapterLibraryMethods\n */\nexport interface DiscordGatewayAdapterLibraryMethods {\n    /**\n     * @description Call this when the adapter can no longer be used (e.g. due to a disconnect from the main gateway)\n     */\n    destroy(): void;\n    /**\n     * @description Call this when you receive a VOICE_SERVER_UPDATE payload that is relevant to the adapter.\n     * @param data - The inner data of the VOICE_SERVER_UPDATE payload\n     */\n    onVoiceServerUpdate(data: GatewayVoiceServerUpdateDispatchData): void;\n    /**\n     * @description Call this when you receive a VOICE_STATE_UPDATE payload that is relevant to the adapter.\n     * @param data - The inner data of the VOICE_STATE_UPDATE payload\n     */\n    onVoiceStateUpdate(data: GatewayVoiceStateUpdateDispatchData): void;\n}\n\n/**\n * @description Методы, предоставляемые разработчиком адаптера Discord Gateway для DiscordGatewayAdapter.\n * @interface DiscordGatewayAdapterImplementerMethods\n */\nexport interface DiscordGatewayAdapterImplementerMethods {\n    /**\n     * @description Это будет вызвано voice, когда адаптер можно будет безопасно уничтожить, поскольку он больше не будет использоваться.\n     */\n    destroy(): void;\n    /**\n     * @description Реализуйте этот метод таким образом, чтобы данная полезная нагрузка отправлялась на основное соединение Discord gateway.\n     * @param payload - Полезная нагрузка для отправки на основное соединение Discord gateway\n     * @returns `false`, если полезная нагрузка определенно не была отправлена - в этом случае голосовое соединение отключается\n     */\n    sendPayload(payload: any): boolean;\n}\n\n/**\n * Функция, используемая для создания адаптеров. Она принимает параметр methods, содержащий функции, которые\n * могут быть вызваны разработчиком при получении новых данных по его шлюзовому соединению. В свою очередь,\n * разработчик вернет некоторые методы, которые может вызывать библиотека - например, для отправки сообщений на\n * шлюз или для подачи сигнала о том, что адаптер может быть удален.\n * @type DiscordGatewayAdapterCreator\n */\nexport type DiscordGatewayAdapterCreator = ( methods: DiscordGatewayAdapterLibraryMethods) =\u003e DiscordGatewayAdapterImplementerMethods;\n```\n\n- Как использовать реализацию voiceAdapterCreator\n```ts\n/**\n * @description Реализация клиента discord\n * @class DiscordClient\n */\nexport class DiscordClient extends Client {\n    /**\n     * @description Класс для общения с websocket\n     * @public\n     */\n    public voice = new VoiceManager(this);\n    //...\n}\n\n// Создадим события для отправки данных в adapter\nimport { createEvent } from 'seyfert';\n\n// VOICE_SERVER_UPDATE\nexport default createEvent({\n    data: { name: 'voiceServerUpdate' },\n    async run(packet, client) {\n        // Отправляем данные в adapter\n        return client.voice.onVoiceServer({ ...packet, guild_id: packet.guildId });\n    }\n});\n\n// VOICE_STATE_UPDATE\nexport default createEvent({\n    data: { name: 'voiceStateUpdate' },\n    async run(state, client) {\n        const payload = state[0];\n\n        // Если нет данных\n        if (!payload) return;\n\n        // Отправляем данные в adapter\n        client.voice.onVoiceStateUpdate({\n            session_id: payload.sessionId,\n            channel_id: payload.channelId,\n            guild_id: payload.guildId,\n            user_id: payload.userId,\n\n            self_stream: payload.selfStream,\n            self_video: payload.selfVideo,\n            self_mute: payload.selfMute,\n            self_deaf: payload.selfDeaf,\n            request_to_speak_timestamp: payload.requestToSpeakTimestamp,\n\n            deaf: payload.deaf,\n            mute: payload.mute,\n            suppress: payload.suppress,\n            member: null\n        });\n    }\n});\n```\n\n- Вот теперь можно отправлять пакеты в seyfert\n```ts\nimport {AudioResource, VoiceConnection} from \"discord-voice-client\";\n\nconst adapter = client.voice.voiceAdapterCreator(guild.id);\nconst config = {\n    self_deaf: true,\n    self_mute: false,\n    guild_id: ctx.guildId,\n    channel_id: ctx.member.voice(\"cache\").id\n};\n\n// Голосовое подключение готово\nconst voice = new VoiceConnection(config, adapter);\nconst audio = new AudioResource(\"urlOrPathFile\", {seek: 10, filters: null});\n\n// Отправка пакетов\nvoice.packet = audio.packet;\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnippik%2Fdiscordvoiceclient","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnippik%2Fdiscordvoiceclient","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnippik%2Fdiscordvoiceclient/lists"}