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
相关产品推荐
相关产品推荐

