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

Discord.js v13音乐机器人进语音频道但无声音问题求助

Discord.js v13 音乐播放器无声问题解决方案

核心依赖修复

Discord.js v13已将语音功能拆分至独立模块,缺少依赖是无声问题的最常见诱因,先确保安装全部必要包:

npm install discord.js@13 @discordjs/voice ffmpeg-static libsodium-wrappers @discordjs/opus

修正后的完整MusicPlayer代码

以下代码实现你需求的三个功能,同时修复了连接状态管理、音频资源配置等可能导致无声的问题:

const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, VoiceConnectionStatus, entersState } = require('@discordjs/voice');

class MusicPlayer {
  constructor() {
    this.connections = new Map(); // 存储各服务器的语音连接与播放器实例
  }

  async background(mp3Url, voiceChannel) {
    const guildId = voiceChannel.guild.id;
    let entry = this.connections.get(guildId);

    // 初始化语音连接
    if (!entry) {
      const connection = joinVoiceChannel({
        channelId: voiceChannel.id,
        guildId: guildId,
        adapterCreator: voiceChannel.guild.voiceAdapterCreator,
      });

      // 等待连接就绪,避免未就绪时播放
      try {
        await entersState(connection, VoiceConnectionStatus.Ready, 30000);
      } catch (err) {
        connection.destroy();
        throw new Error(`连接失败:${err.message}`);
      }

      entry = { connection, backgroundPlayer: null, soundPlayers: new Set() };
      this.connections.set(guildId, entry);
    }

    // 替换旧背景播放器
    if (entry.backgroundPlayer) entry.backgroundPlayer.stop();

    // 创建带音量控制的音频资源
    const resource = createAudioResource(mp3Url, { inlineVolume: true });
    resource.volume.setVolume(0.5);

    // 创建背景播放器并设置循环
    const bgPlayer = createAudioPlayer();
    bgPlayer.on(AudioPlayerStatus.Idle, () => bgPlayer.play(resource));
    bgPlayer.on('error', err => console.error('背景播放错误:', err));

    // 订阅播放器到语音连接
    const subscription = entry.connection.subscribe(bgPlayer);
    if (!subscription) throw new Error('无法订阅播放器到语音连接');

    bgPlayer.play(resource);
    entry.backgroundPlayer = bgPlayer;
  }

  async playSound(mp3Url, voiceChannel) {
    const guildId = voiceChannel.guild.id;
    let entry = this.connections.get(guildId);

    // 无连接时初始化
    if (!entry) {
      const connection = joinVoiceChannel({
        channelId: voiceChannel.id,
        guildId: guildId,
        adapterCreator: voiceChannel.guild.voiceAdapterCreator,
      });

      try {
        await entersState(connection, VoiceConnectionStatus.Ready, 30000);
      } catch (err) {
        connection.destroy();
        throw new Error(`连接失败:${err.message}`);
      }

      entry = { connection, backgroundPlayer: null, soundPlayers: new Set() };
      this.connections.set(guildId, entry);
    }

    // 创建音效播放器
    const soundPlayer = createAudioPlayer();
    const resource = createAudioResource(mp3Url, { inlineVolume: true });
    resource.volume.setVolume(1.0);

    // 播放完成后自动清理
    soundPlayer.on(AudioPlayerStatus.Idle, () => {
      soundPlayer.stop();
      entry.soundPlayers.delete(soundPlayer);
    });
    soundPlayer.on('error', err => console.error('音效播放错误:', err));

    const subscription = entry.connection.subscribe(soundPlayer);
    if (!subscription) throw new Error('无法订阅音效播放器到语音连接');

    soundPlayer.play(resource);
    entry.soundPlayers.add(soundPlayer);
  }

  stop(voiceChannel) {
    const guildId = voiceChannel.guild.id;
    const entry = this.connections.get(guildId);
    if (!entry) return;

    // 停止所有播放器
    if (entry.backgroundPlayer) entry.backgroundPlayer.stop();
    entry.soundPlayers.forEach(player => player.stop());

    // 断开连接并清理资源
    entry.connection.destroy();
    this.connections.delete(guildId);
  }
}

module.exports = MusicPlayer;

额外排查步骤

若仍无声音,按以下顺序验证:

  • 资源有效性:确认MP3 URL可直接访问(本地文件用绝对路径,远程URL需能在浏览器中直接播放)。
  • 机器人权限:确保机器人在目标语音频道拥有Connect和Speak权限,可在服务器角色设置中检查。
  • 错误日志:通过播放器的error事件监听,查看是否存在音频解码或资源加载错误。
  • FFmpeg可用性:运行npx ffmpeg -version确认FFmpeg可正常调用,ffmpeg-static会自动提供二进制文件,无需全局安装。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 18:35:02