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

Discord音乐机器人无法播放音频问题求助(附代码)

Discord音乐机器人无法播放音频(已成功加入语音频道)

我正在开发一款Discord音乐机器人,它能成功加入语音频道,但无法播放任何音频。已尝试多种方法均未解决问题,开发环境为VS Code、Node.js 18.7.0以及discord.js v13。

相关代码如下:

const ytdl = require("ytdl-core")
const ytSearch = require("yt-search")
const {
    joinVoiceChannel,
    createAudioPlayer,
    createAudioResource
} = require('@discordjs/voice')

module.exports = {
    name: "play",
    description: "Plays a song of your choice.",
    async execute(messageCreate, args) {
        const voiceChannel = messageCreate.member.voice.channel

        if (!voiceChannel) return messageCreate.channel.send("You must be in a voice channel to run this command.")
        const permissions = voiceChannel.permissionsFor(messageCreate.client.user)
        if (!permissions.has("CONNECT")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
        if (!permissions.has("SPEAK")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
        if (!args.length) return messageCreate.channel.send("You must specify some keywords to identify the song you are looking for.")

        joinVoiceChannel({
            channelId: messageCreate.member.voice.channel.id,
            guildId: messageCreate.guild.id,
            adapterCreator: messageCreate.guild.voiceAdapterCreator
        })
        
        const videoFinder = async (query) => {
            const videoResult = await ytSearch(query)

            return (videoResult.videos.length > 1) ? videoResult.videos[0] : null

        }
        
        const video = await videoFinder(args.join(" "))

        if (video) {
            const stream = ytdl(video.url, {filter: "audioonly"})
            const player = createAudioPlayer()
            const resource = createAudioResource(stream)

            async function play() {
                await player.play(resource)
                connection.subscribe(player)
            connection.play(stream, {seek: 0, volume: 1})
            .on("finish", () => {
                voiceChannel.leave()
            })
            }

            await messageCreate.reply(`:thumbsup: Now playing: ***${video.title}***.`)

        } else {
            messageCreate.channel.send("No video results found.")
        }
    }

}

问题排查与修复方案

1. 未保存语音连接实例

调用joinVoiceChannel后没有将返回的连接对象赋值给变量,导致后续代码中的connection未定义,无法完成播放器订阅和播放操作。

修复:

const connection = joinVoiceChannel({
    channelId: voiceChannel.id,
    guildId: messageCreate.guild.id,
    adapterCreator: messageCreate.guild.voiceAdapterCreator
})

2. 混合使用新旧音频API

你同时使用了@discordjs/voice的player.play(resource)和旧版discord.js的connection.play(stream),两者会产生冲突。discord.js v13推荐完全使用@discordjs/voice的API,删除旧版播放逻辑。

3. 未执行播放函数

定义了play()函数但从未调用,导致播放器从未启动播放。直接移除不必要的函数封装,将播放逻辑直接执行即可。

4. 视频搜索判断逻辑错误

videoFinder中的videoResult.videos.length > 1条件有误,应该判断是否有结果(> 0),否则当搜索结果只有1个时会返回null。

修复:

return (videoResult.videos.length > 0) ? videoResult.videos[0] : null

完整修复后的代码

const ytdl = require("ytdl-core")
const ytSearch = require("yt-search")
const {
    joinVoiceChannel,
    createAudioPlayer,
    createAudioResource,
    AudioPlayerStatus
} = require('@discordjs/voice')

module.exports = {
    name: "play",
    description: "Plays a song of your choice.",
    async execute(messageCreate, args) {
        const voiceChannel = messageCreate.member.voice.channel

        if (!voiceChannel) return messageCreate.channel.send("You must be in a voice channel to run this command.")
        const permissions = voiceChannel.permissionsFor(messageCreate.client.user)
        if (!permissions.has("CONNECT")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
        if (!permissions.has("SPEAK")) return messageCreate.channel.send("You do not have the sufficient permissions to do this.")
        if (!args.length) return messageCreate.channel.send("You must specify some keywords to identify the song you are looking for.")

        // 保存连接实例
        const connection = joinVoiceChannel({
            channelId: voiceChannel.id,
            guildId: messageCreate.guild.id,
            adapterCreator: messageCreate.guild.voiceAdapterCreator
        })
        
        const videoFinder = async (query) => {
            const videoResult = await ytSearch(query)
            // 修复结果判断逻辑
            return (videoResult.videos.length > 0) ? videoResult.videos[0] : null
        }
        
        const video = await videoFinder(args.join(" "))

        if (video) {
            const stream = ytdl(video.url, {filter: "audioonly"})
            const player = createAudioPlayer()
            const resource = createAudioResource(stream)

            // 订阅播放器到语音连接
            connection.subscribe(player)
            // 启动播放
            player.play(resource)

            // 监听播放结束事件,销毁连接
            player.on(AudioPlayerStatus.Idle, () => {
                connection.destroy()
            })

            // 监听播放器错误
            player.on('error', error => {
                console.error(`播放错误: ${error.message}`)
                messageCreate.channel.send(`播放出错: ${error.message}`)
            })

            await messageCreate.reply(`:thumbsup: Now playing: ***${video.title}***.`)
        } else {
            messageCreate.channel.send("No video results found.")
        }
    }
}

额外注意事项

  • 确保ytdl-core是最新版本,YouTube的音频流获取规则可能变动,旧版本可能失效。
  • 检查机器人在目标语音频道中是否有SPEAK和CONNECT权限,且未被静音。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 07:24:19