🔨 Auto inject smooth volume
This commit is contained in:
parent
6c46957f3f
commit
99b9cabdcf
9 changed files with 71 additions and 22 deletions
|
@ -1,7 +1,6 @@
|
|||
require("dotenv").config({
|
||||
path: __dirname+"/.env"
|
||||
});
|
||||
require("discord-player/smoothVolume");
|
||||
const { Client, GuildMember, Intents } = require("discord.js");
|
||||
const config = require("./config");
|
||||
const { Player, QueryType, QueueRepeatMode } = require("discord-player");
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
},
|
||||
"./smoothVolume": "./dist/smoothVolume.js"
|
||||
"./smoothVolume": "./dist/smoothVolume.js",
|
||||
"./src/*": "./dist/*",
|
||||
"./dist/*": "./dist/*"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "cd example/test && ts-node index.ts",
|
||||
|
@ -86,7 +88,7 @@
|
|||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"discord-api-types": "^0.24.0",
|
||||
"discord.js": "^13.3.1",
|
||||
"discord.js": "^13.6.0",
|
||||
"eslint": "^8.3.0",
|
||||
"gen-esm-wrapper": "^1.1.3",
|
||||
"husky": "^7.0.4",
|
||||
|
|
|
@ -45,7 +45,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
*/
|
||||
this.client = client;
|
||||
|
||||
if (!new Intents(this.client.options.intents).has(Intents.FLAGS.GUILD_VOICE_STATES)) {
|
||||
if (this.client?.options?.intents && !new Intents(this.client?.options?.intents).has(Intents.FLAGS.GUILD_VOICE_STATES)) {
|
||||
throw new PlayerError('client is missing "GUILD_VOICE_STATES" intent');
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
|
||||
const _meta = queueInitOptions.metadata;
|
||||
delete queueInitOptions["metadata"];
|
||||
queueInitOptions.volumeSmoothness ??= 0.1;
|
||||
queueInitOptions.volumeSmoothness ??= 0.08;
|
||||
queueInitOptions.ytdlOptions ??= this.options.ytdlOptions;
|
||||
const queue = new Queue(this, guild, queueInitOptions);
|
||||
queue.metadata = _meta;
|
||||
|
|
|
@ -10,6 +10,7 @@ import YouTube from "youtube-sr";
|
|||
import AudioFilters from "../utils/AudioFilters";
|
||||
import { PlayerError, ErrorStatusCode } from "./PlayerError";
|
||||
import type { Readable } from "stream";
|
||||
import { VolumeTransformer } from "../VoiceInterface/VolumeTransformer";
|
||||
|
||||
class Queue<T = unknown> {
|
||||
public readonly guild: Guild;
|
||||
|
@ -154,8 +155,7 @@ class Queue<T = unknown> {
|
|||
if (!["GUILD_STAGE_VOICE", "GUILD_VOICE"].includes(_channel?.type))
|
||||
throw new PlayerError(`Channel type must be GUILD_VOICE or GUILD_STAGE_VOICE, got ${_channel?.type}!`, ErrorStatusCode.INVALID_ARG_TYPE);
|
||||
const connection = await this.player.voiceUtils.connect(_channel, {
|
||||
deaf: this.options.autoSelfDeaf,
|
||||
maxTime: this.player.options.connectionTimeout || 20000
|
||||
deaf: this.options.autoSelfDeaf
|
||||
});
|
||||
this.connection = connection;
|
||||
|
||||
|
@ -206,6 +206,10 @@ class Queue<T = unknown> {
|
|||
}
|
||||
});
|
||||
|
||||
await this.player.voiceUtils.enterReady(this.connection.voiceConnection, {
|
||||
maxTime: this.player.options.connectionTimeout || 30_000
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -703,8 +707,9 @@ class Queue<T = unknown> {
|
|||
if (options.seek) this._streamTime = options.seek;
|
||||
this._filtersUpdate = options.filtersUpdate;
|
||||
|
||||
if (resource.volume && typeof this.options.volumeSmoothness === "number") {
|
||||
Reflect.set(resource.volume, "_smoothing", this.options.volumeSmoothness || 0);
|
||||
const volumeTransformer = resource.volume as VolumeTransformer;
|
||||
if (volumeTransformer?.hasSmoothness && typeof this.options.volumeSmoothness === "number") {
|
||||
if (typeof volumeTransformer.setSmoothness === "function") volumeTransformer.setSmoothness(this.options.volumeSmoothness || 0);
|
||||
}
|
||||
|
||||
this.setVolume(this.options.initialVolume);
|
||||
|
|
|
@ -49,13 +49,17 @@ class VoiceUtils {
|
|||
maxTime?: number;
|
||||
}
|
||||
) {
|
||||
let conn = joinVoiceChannel({
|
||||
const conn = joinVoiceChannel({
|
||||
guildId: channel.guild.id,
|
||||
channelId: channel.id,
|
||||
adapterCreator: channel.guild.voiceAdapterCreator as unknown as DiscordGatewayAdapterCreator,
|
||||
selfDeaf: Boolean(options.deaf)
|
||||
});
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
public async enterReady(conn: VoiceConnection, options: { maxTime?: number } = {}) {
|
||||
try {
|
||||
conn = await entersState(conn, VoiceConnectionStatus.Ready, options?.maxTime ?? 20000);
|
||||
return conn;
|
||||
|
|
|
@ -16,6 +16,7 @@ export class VolumeTransformer extends Transform {
|
|||
private _chunk: Buffer;
|
||||
public volume: number;
|
||||
private _targetVolume: number;
|
||||
public type: "s16le" | "s32le" | "s16be" | "s32be";
|
||||
constructor(options: VolumeTransformerOptions = {}) {
|
||||
super(options);
|
||||
switch (options.type) {
|
||||
|
@ -42,9 +43,11 @@ export class VolumeTransformer extends Transform {
|
|||
default:
|
||||
throw new Error("VolumeTransformer type should be one of s16le, s16be, s32le, s32be");
|
||||
}
|
||||
this.type = options.type;
|
||||
this._bytes = this._bits / 8;
|
||||
this._extremum = Math.pow(2, this._bits - 1);
|
||||
this.volume = typeof options.volume === "undefined" ? 1 : options.volume;
|
||||
this.volume = Number.isNaN(options.volume) ? 1 : Number(options.volume);
|
||||
if (!Number.isFinite(this.volume)) this.volume = 1;
|
||||
this._targetVolume = this.volume;
|
||||
this._chunk = Buffer.alloc(0);
|
||||
this._smoothing = options.smoothness || 0;
|
||||
|
@ -57,14 +60,16 @@ export class VolumeTransformer extends Transform {
|
|||
return index;
|
||||
}
|
||||
|
||||
_transform(chunk: Buffer, encoding: BufferEncoding, done: () => unknown) {
|
||||
if (this._smoothing > 0 && this.volume !== this._targetVolume) {
|
||||
if (this.volume < this._targetVolume) {
|
||||
this.volume = this.volume + this._smoothing >= this._targetVolume ? this._targetVolume : this.volume + this._smoothing;
|
||||
} else if (this.volume > this._targetVolume) {
|
||||
this.volume = this.volume - this._smoothing <= this._targetVolume ? this._targetVolume : this.volume - this._smoothing;
|
||||
}
|
||||
_applySmoothness() {
|
||||
if (this.volume < this._targetVolume) {
|
||||
this.volume = this.volume + this._smoothing >= this._targetVolume ? this._targetVolume : this.volume + this._smoothing;
|
||||
} else if (this.volume > this._targetVolume) {
|
||||
this.volume = this.volume - this._smoothing <= this._targetVolume ? this._targetVolume : this.volume - this._smoothing;
|
||||
}
|
||||
}
|
||||
|
||||
_transform(chunk: Buffer, encoding: BufferEncoding, done: () => unknown) {
|
||||
if (this.smoothingEnabled() && this.volume !== this._targetVolume) this._applySmoothness();
|
||||
|
||||
if (this.volume === 1) {
|
||||
this.push(chunk);
|
||||
|
@ -94,6 +99,9 @@ export class VolumeTransformer extends Transform {
|
|||
}
|
||||
|
||||
setVolume(volume: number) {
|
||||
if (Number.isNaN(volume)) volume = 1;
|
||||
if (typeof volume !== "number") volume = Number(volume);
|
||||
if (!Number.isFinite(volume)) volume = volume < 0 ? 0 : 1;
|
||||
this._targetVolume = volume;
|
||||
if (this._smoothing <= 0) this.volume = volume;
|
||||
}
|
||||
|
@ -113,4 +121,24 @@ export class VolumeTransformer extends Transform {
|
|||
get volumeLogarithmic() {
|
||||
return Math.pow(this.volume, 1 / 1.660964);
|
||||
}
|
||||
|
||||
get smoothness() {
|
||||
return this._smoothing;
|
||||
}
|
||||
|
||||
setSmoothness(smoothness: number) {
|
||||
this._smoothing = smoothness;
|
||||
}
|
||||
|
||||
smoothingEnabled() {
|
||||
return Number.isFinite(this._smoothing) && this._smoothing > 0;
|
||||
}
|
||||
|
||||
get hasSmoothness() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static get hasSmoothing() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
// try applying smooth volume patch on load
|
||||
import "./smoothVolume";
|
||||
|
||||
export { AudioFilters } from "./utils/AudioFilters";
|
||||
export { ExtractorModel } from "./Structures/ExtractorModel";
|
||||
export { Playlist } from "./Structures/Playlist";
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
import { VolumeTransformer } from "./VolumeTransformer";
|
||||
import { VolumeTransformer as VolumeTransformerMock } from "./VoiceInterface/VolumeTransformer";
|
||||
|
||||
// eslint-disable-next-line
|
||||
(require("prism-media") as typeof import("prism-media")).VolumeTransformer = VolumeTransformer;
|
||||
try {
|
||||
// eslint-disable-next-line
|
||||
const mod = require("prism-media") as typeof import("prism-media") & { VolumeTransformer: typeof VolumeTransformerMock };
|
||||
|
||||
if (typeof mod.VolumeTransformer.hasSmoothing !== "boolean") {
|
||||
Reflect.set(mod, "VolumeTransformer", VolumeTransformerMock);
|
||||
}
|
||||
} catch {
|
||||
/* do nothing */
|
||||
}
|
||||
|
|
|
@ -1990,7 +1990,7 @@ discord-ytdl-core@^5.0.4:
|
|||
dependencies:
|
||||
prism-media "^1.2.9"
|
||||
|
||||
discord.js@^13.3.1:
|
||||
discord.js@^13.6.0:
|
||||
version "13.6.0"
|
||||
resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.6.0.tgz#d8a8a591dbf25cbcf9c783d5ddf22c4694860475"
|
||||
integrity sha512-tXNR8zgsEPxPBvGk3AQjJ9ljIIC6/LOPjzKwpwz8Y1Q2X66Vi3ZqFgRHYwnHKC0jC0F+l4LzxlhmOJsBZDNg9g==
|
||||
|
|
Loading…
Reference in a new issue