DiscordJS音量命令故障排查:player与resource变量为空
Discord.js音量命令无法获取player/resource的问题解决
问题描述
我编写了一个Discord.js音乐命令类,执行play命令时机器人能正常播放歌曲,但执行volume命令时,player和resource变量始终为空,无法调整音量。相关代码如下:
class music_cmd{ constructor(client, message, prefix, cmd, args, generateDependencyReport, joinVoiceChannel, createAudioPlayer, createAudioResource, ytdl){ this.client = client; this.message = message; this.prefix = prefix; this.cmd = cmd; this.args = args; this.joinVoiceChannel = joinVoiceChannel; this.createAudioPlayer = createAudioPlayer; this.createAudioResource = createAudioResource; this.ytdl = ytdl; this.connection = null; this.players = new Map(); if(cmd === 'play'){ this.play(); } if(cmd === 'volume'){ this.volume(); } } async play(){ try{ this.connection = await this.joinVoiceChannel({ channelId: this.message.member.voice.channel.id, guildId: this.message.guild.id, adapterCreator: this.message.guild.voiceAdapterCreator }); const stream = this.ytdl(this.args[1], { filter: 'audioonly' }); const player = this.createAudioPlayer(); const resource = this.createAudioResource(stream); this.players.set(this.message.guild.id, { player, resource }); player.play(resource); this.connection.subscribe(player); this.message.channel.send('Rozpoczynam odtwarzanie utworu..'); } catch(error){ console.error(error); } } volume(){ const volume = parseInt(this.args[1]); if (isNaN(volume) || volume < 0 || volume > 100) { this.message.channel.send('Podaj poprawną wartość głośności (liczba od 0 do 100).'); return; } const guildId = this.message.guild.id; const { player, resource } = this.players.get(guildId) || {}; console.log(player); console.log(resource); if (!player || !resource) { this.message.channel.send('Nie odtwarzam żadnej muzyki.'); return; } resource.volume.setVolume(volume / 100); this.message.channel.send(`Głośność ustawiona na ${volume}%.`); } } export default music_cmd;
问题根源
每次触发Discord命令时,都会创建一个全新的music_cmd实例。你在constructor里初始化的this.players = new Map()是每个实例独有的,play命令将播放器状态存在当前实例的Map中,而volume命令的实例根本访问不到这个Map,自然拿不到player和resource。
解决方案
1. 共享播放器状态(核心修复)
将players改为类的静态属性,让所有music_cmd实例共享同一个Map:
class music_cmd{ // 改为静态属性,所有实例共享 static players = new Map(); constructor(client, message, prefix, cmd, args, generateDependencyReport, joinVoiceChannel, createAudioPlayer, createAudioResource, ytdl){ this.client = client; this.message = message; this.prefix = prefix; this.cmd = cmd; this.args = args; this.joinVoiceChannel = joinVoiceChannel; this.createAudioPlayer = createAudioPlayer; this.createAudioResource = createAudioResource; this.ytdl = ytdl; this.connection = null; // 移除this.players = new Map(); if(cmd === 'play'){ this.play(); } if(cmd === 'volume'){ this.volume(); } } async play(){ try{ this.connection = await this.joinVoiceChannel({ channelId: this.message.member.voice.channel.id, guildId: this.message.guild.id, adapterCreator: this.message.guild.voiceAdapterCreator }); const stream = this.ytdl(this.args[1], { filter: 'audioonly' }); const player = this.createAudioPlayer(); // 开启音量控制选项 const resource = this.createAudioResource(stream, { inlineVolume: true }); // 使用静态属性存储 music_cmd.players.set(this.message.guild.id, { player, resource }); player.play(resource); this.connection.subscribe(player); this.message.channel.send('Rozpoczynam odtwarzanie utworu..'); } catch(error){ console.error(error); } } volume(){ const volume = parseInt(this.args[1]); if (isNaN(volume) || volume < 0 || volume > 100) { this.message.channel.send('Podaj poprawną wartość głośności (liczba od 0 do 100).'); return; } const guildId = this.message.guild.id; // 从静态属性获取 const { player, resource } = music_cmd.players.get(guildId) || {}; if (!player || !resource) { this.message.channel.send('Nie odtwarzam żadnej muzyki.'); return; } resource.volume.setVolume(volume / 100); this.message.channel.send(`Głośność ustawiona na ${volume}%.`); } } export default music_cmd;
2. 额外注意:开启音量控制
创建AudioResource时必须添加inlineVolume: true选项,否则resource.volume会是undefined,即使拿到资源也无法调整音量。
其他可选方案
如果不想用静态属性,也可以将播放器状态存储在Discord客户端实例上,比如:
// 在客户端初始化时添加 client.musicPlayers = new Map(); // 在类中使用 this.client.musicPlayers.set(guildId, { player, resource }); const { player, resource } = this.client.musicPlayers.get(guildId) || {};
这种方式更适合多命令类共享状态的场景。
内容的提问来源于stack exchange,提问作者hguytkl
相关产品推荐
相关产品推荐

