You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

discord.js开发Discord音乐Bot出现connection未定义报错如何解决

问题原因分析
  • 队列Map作用域错误:你在play函数内部每次执行都重新初始化了const queue = new Map(),这个Map是局部变量,每次调用play都会清空,根本拿不到之前存储的serverQueue对象,自然不存在connection属性。
  • serverQueue对象未初始化connection字段:你需要在用户首次触发播放命令、把歌曲加入队列的阶段,就完成加入语音频道、获取connection对象并存入serverQueue的操作,而不是在play函数里再去获取。
修复步骤
  1. 把队列Map移到play函数外部,变成全局/模块级变量,保证整个运行过程中只有一个队列实例:
// 放到play函数外面,全局作用域
const queue = new Map()

function play(guild, song) { 
  const serverQueue = queue.get(guild.id);
  // 剩下原有代码
}
  1. 在处理播放命令的消息回调逻辑里,提前创建serverQueue、获取connection,示例如下:
// 你的消息监听逻辑里的播放命令处理部分
client.on('messageCreate', async message => {
  // 跳过机器人消息、无前缀消息
  if (!message.content.startsWith('!') || message.author.bot) return
  const args = message.content.slice(1).split(' ')
  const command = args.shift().toLowerCase()

  if (command === 'play') {
    const voiceChannel = message.member.voice.channel
    // 校验用户是否在语音频道
    if (!voiceChannel) return message.channel.send('你需要先加入一个语音频道')
    // 校验Bot的语音权限
    const permissions = voiceChannel.permissionsFor(message.client.user)
    if (!permissions.has('CONNECT') || !permissions.has('SPEAK')) {
      return message.channel.send('我没有加入该语音频道或发言的权限')
    }
    // 解析歌曲信息(你自己的ytdl解析逻辑)
    const songInfo = await ytdl.getInfo(args[0])
    const song = {
      title: songInfo.videoDetails.title,
      url: songInfo.videoDetails.video_url,
    }
    // 检查当前服务器有没有已存在的队列
    const serverQueue = queue.get(message.guild.id)
    if (!serverQueue) {
      // 新建队列对象
      const queueConstruct = {
        textChannel: message.channel,
        voiceChannel: voiceChannel,
        connection: null,
        songs: [],
        volume: 5,
        playing: true
      }
      queue.set(message.guild.id, queueConstruct)
      queueConstruct.songs.push(song)
      try {
        // 加入语音频道,获取connection并存入队列
        const connection = await voiceChannel.join()
        queueConstruct.connection = connection
        // 调用play函数开始播放
        play(message.guild, queueConstruct.songs[0])
      } catch (err) {
        console.log(err)
        queue.delete(message.guild.id)
        return message.channel.send(err)
      }
    } else {
      // 已有队列就直接加歌
      serverQueue.songs.push(song)
      return message.channel.send(`${song.title} 已加入播放队列`)
    }
  }
})
  1. 给play函数加serverQueue存在性校验,避免无队列时报错:
function play(guild, song) { 
  const serverQueue = queue.get(guild.id);
  // 新增校验:没有队列直接返回
  if (!serverQueue) return
  if (!song) {
    serverQueue.voiceChannel.leave();
    queue.delete(guild.id);
    return;
  }
  const dispatcher = serverQueue.connection
    .play(ytdl(song.url, { filter: 'audioonly' })) // 建议加audioonly过滤,减少带宽占用
    .on("finish", () => {
      serverQueue.songs.shift();
      play(guild, serverQueue.songs[0]);
    })
    .on("error", error => console.error(error));
  dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
  serverQueue.textChannel.send(`Start playing: **${song.title}**`);
}
额外注意点
  • 如果你使用的是discord.js v14及以上版本,语音相关功能已经拆分到@discordjs/voice包,voiceChannel.join()、connection.play()的API已经发生变化,需要适配新的语音API写法。
  • ytdl需要安装最新版本,否则可能出现无法拉取音频流的问题。

内容的提问来源于stack exchange,提问作者Ross Beckett

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:18:02