Discord.js v13音乐机器人报错ReferenceError: channel is not defined求助
问题修复方案
错误根因
- 代码第17行调用
joinVoiceChannel时使用的channel变量从未定义,直接触发ReferenceError - 连接语音频道的逻辑放在了用户语音频道权限校验之前,即使修复变量问题,也会出现用户未进入语音频道但机器人尝试连接的逻辑错误
- 播放逻辑仍使用discord.js v12的旧API,和v13配套的
@discordjs/voice不兼容,修复变量后仍会出现播放报错
修复步骤
- 把
joinVoiceChannel的调用移到权限校验通过后的队列初始化try代码块中,参数替换为已定义的voice_channel变量 - 新增音频播放器、音频资源的创建逻辑,适配
@discordjs/voice的API要求 - 调整skip、stop方法的停止逻辑,适配新的播放器实例
修改后的完整代码
const ytdl = require('ytdl-core'); const ytSearch = require('yt-search'); const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus } = require('@discordjs/voice'); // 全局队列,每个服务器对应一个队列实例 const queue = new Map(); module.exports = { name: 'play', aliases: ['skip', 'stop'], cooldown: 0, description: 'Advanced music bot', async execute(message, args, cmd, client, Discord){ // 先校验用户语音频道和权限 const voice_channel = message.member.voice.channel; if (!voice_channel) return message.channel.send('You need to be in a channel to execute this command!'); const permissions = voice_channel.permissionsFor(message.client.user); if (!permissions.has('CONNECT')) return message.channel.send('You dont have the correct permissions'); if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissions'); const server_queue = queue.get(message.guild.id); if (cmd === 'play'){ if (!args.length) return message.channel.send('You need to send the second argument!'); let song = {}; // 链接解析逻辑 if (ytdl.validateURL(args[0])) { const song_info = await ytdl.getInfo(args[0]); song = { title: song_info.videoDetails.title, url: song_info.videoDetails.video_url } } else { // 关键词搜索逻辑 const video_finder = async (query) =>{ const video_result = await ytSearch(query); return (video_result.videos.length > 1) ? video_result.videos[0] : null; } const video = await video_finder(args.join(' ')); if (video){ song = { title: video.title, url: video.url } } else { return message.channel.send('Error finding video.'); } } // 队列为空时新建队列 if (!server_queue){ const queue_constructor = { voice_channel: voice_channel, text_channel: message.channel, connection: null, player: null, songs: [] } queue.set(message.guild.id, queue_constructor); queue_constructor.songs.push(song); try { // 这里才初始化语音连接,用已经校验过的voice_channel const connection = joinVoiceChannel({ channelId: voice_channel.id, guildId: voice_channel.guild.id, adapterCreator: voice_channel.guild.voiceAdapterCreator, }); // 创建音频播放器 const player = createAudioPlayer(); connection.subscribe(player); queue_constructor.connection = connection; queue_constructor.player = player; video_player(message.guild, queue_constructor.songs[0]); } catch (err) { queue.delete(message.guild.id); message.channel.send('There was an error connecting!'); throw err; } } else{ server_queue.songs.push(song); return message.channel.send(`👍 **${song.title}** added to queue!`); } } else if(cmd === 'skip') skip_song(message, server_queue); else if(cmd === 'stop') stop_song(message, server_queue); } } const video_player = async (guild, song) => { const song_queue = queue.get(guild.id); if (!song) { song_queue.connection.destroy(); queue.delete(guild.id); return; } const stream = ytdl(song.url, { filter: 'audioonly', highWaterMark: 1<<25 }); // 创建音频资源 const resource = createAudioResource(stream, { inlineVolume: true }); resource.volume.setVolume(0.5); // 播放音频 song_queue.player.play(resource); // 监听播放结束事件 song_queue.player.on(AudioPlayerStatus.Idle, () => { song_queue.songs.shift(); video_player(guild, song_queue.songs[0]); }); await song_queue.text_channel.send(`🎶 Now playing **${song.title}**`) } const skip_song = (message, server_queue) => { if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!'); if(!server_queue){ return message.channel.send(`There are no songs in queue 😔`); } server_queue.player.stop(); } const stop_song = (message, server_queue) => { if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!'); server_queue.songs = []; server_queue.player.stop(); }
额外注意事项
- 启动机器人时需要在Client配置中开启
GUILD_VOICE_STATES意图,否则无法正常连接语音频道 - 确保已经安装了
libsodium-wrappers(或sodium)依赖,否则语音功能无法正常运行
内容的提问来源于stack exchange,提问作者ThePangel
相关产品推荐
相关产品推荐

