Plugin
VolumeBooster
Allows you to set the user and stream volume above the default maximum
1
/*2
* FiveCord — a Discord client mod3
* Copyright (c) 2025 FiveCord4
* SPDX-License-Identifier: GPL-3.0-or-later5
*/6
7
import { definePluginSettings } from "@api/Settings";8
import { Devs } from "@utils/constants";9
import definePlugin, { makeRange, OptionType } from "@utils/types";10
11
const settings = definePluginSettings({12
multiplier: {13
description: "Volume Multiplier",14
type: OptionType.SLIDER,15
markers: makeRange(1, 5, 0.5),16
default: 2,17
stickToMarkers: true,18
}19
});20
21
interface StreamData {22
audioContext: AudioContext,23
audioElement: HTMLAudioElement,24
emitter: any,25
// added by this plugin26
gainNode?: GainNode,27
id: string,28
levelNode: AudioWorkletNode,29
sinkId: string | "default",30
stream: MediaStream,31
streamSourceNode?: MediaStreamAudioSourceNode,32
videoStreamId: string,33
_mute: boolean,34
_speakingFlags: number,35
_volume: number;36
}37
38
export default definePlugin({39
name: "VolumeBooster",40
authors: [Devs.Nuckyz, Devs.sadan],41
description: "Allows you to set the user and stream volume above the default maximum",42
tags: ["Voice", "Utility"],43
settings,44
45
patches: [46
// Change the max volume for sliders to allow for values above 20047
{48
find: "#{intl::USER_VOLUME}",49
replacement: {50
match: /(?<=maxValue:)\i\.isPlatformEmbedded\?(\i\.\i):\i\.\i(?=,)/,51
replace: (_, higherMaxVolume) => `${higherMaxVolume}*$self.settings.store.multiplier`52
}53
},54
// Change the max volume for sliders to allow for values above 20055
{56
find: "currentVolume:",57
replacement: {58
match: /(?<=maxValue:)\i\.\i\?(\d+?):\d+?(?=,)/,59
replace: (_, higherMaxVolume) => `${higherMaxVolume}*$self.settings.store.multiplier`60
}61
},62
// Patches needed for web/vesktop63
{64
find: "streamSourceNode",65
predicate: () => !IS_DISCORD_DESKTOP,66
group: true,67
replacement: [68
// Remove rounding algorithm69
{70
match: /Math\.max.{0,30}\)\)/,71
replace: "arguments[0]"72
},73
// Fix streams not playing audio until you update them74
{75
match: /\}return"video"/,76
replace: "this.updateAudioElement();$&"77
},78
// Patch the volume79
{80
match: /\.volume=this\._volume\/100;/,81
replace: ".volume=0.00;$self.patchVolume(this);"82
}83
]84
},85
// Prevent Audio Context Settings sync from trying to sync with values above 200, changing them to 200 before we send to Discord86
{87
find: "AudioContextSettingsMigrated",88
replacement: [89
{90
match: /(?<=isLocalMute\(\i,\i\),volume:(\i).+?\(0,\i\.\i\)\(\i,\i,\{volume:)\1(?=\}\))/,91
replace: "$&>200?200:$&"92
},93
{94
match: /(?<=Object\.entries\(\i\.localMutes\).+?volume:).+?(?=,)/,95
replace: "$&>200?200:$&"96
},97
{98
match: /(?<=Object\.entries\(\i\.localVolumes\).+?volume:).+?(?=})/,99
replace: "$&>200?200:$&"100
}101
]102
},103
// Prevent the MediaEngineStore from overwriting our LocalVolumes above 200 with the ones the Discord Audio Context Settings sync sends104
{105
find: 039;="MediaEngineStore",039;,106
replacement: [107
{108
match: /(\.settings\.audioContextSettings.+?)(\i\[\i\])=(\i\.volume)(.+?setLocalVolume\(\i,).+?\)/,109
replace: (_, rest1, localVolume, syncVolume, rest2) => rest1110
+ `(${localVolume}>200?void 0:${localVolume}=${syncVolume})`111
+ rest2112
+ `${localVolume}??${syncVolume})`113
}114
]115
}116
],117
118
patchVolume(data: StreamData) {119
if (data.stream.getAudioTracks().length === 0) return;120
121
data.streamSourceNode ??= data.audioContext.createMediaStreamSource(data.stream);122
123
if (!data.gainNode) {124
const gain = data.gainNode = data.audioContext.createGain();125
data.streamSourceNode.connect(gain);126
gain.connect(data.audioContext.destination);127
}128
129
// @ts-expect-error130
if (data.sinkId != null && data.sinkId !== data.audioContext.sinkId && "setSinkId" in AudioContext.prototype) {131
// @ts-expect-error https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/setSinkId132
data.audioContext.setSinkId(data.sinkId === "default" ? "" : data.sinkId);133
}134
135
data.gainNode.gain.value = data._mute136
? 0137
: data._volume / 100;138
}139
});140