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

discord.js v13音乐机器人报错song_queue.connection.play is not a function如何解决

解决方案

报错原因

discord.js v13对语音模块做了全量重构,@discordjs/voice返回的语音连接对象已不再内置play方法,必须配合官方规范的AudioPlayer+AudioResource流程实现播放,你使用的v12版本代码逻辑完全不兼容v13接口。

需要修改的核心点

  • 修复代码笔误:获取Youtube视频信息时变量名写错,song_title应为song_info
  • 新增AudioPlayer实例存储字段,将播放器绑定到语音连接
  • 重写播放逻辑,替换原有废弃的connection.play调用
  • 替换原有语音频道退出方法,改用connection.destroy()

修改后完整代码

const ytdl = require('ytdl-core');
const ytSearch = require('yt-search');
// 新增引入StreamType
const { joinVoiceChannel, createAudioPlayer, createAudioResource, StreamType } = require('@discordjs/voice');

const queue = new Map();
// queue (message.guild.id, queue_constructor object { voice channel, text channel, connection, audioPlayer, song[]});
module.exports = {
    name: 'play',
    aliases: ['skip', 'stop'],
    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 permission to do that');
        if (!permissions.has('SPEAK')) return message.channel.send('You dont have permission to do that');

        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 {
                //If the video is not a URL then use keywords to find that video.
                const video_finder = async (query) =>{
                    const videoResult = await ytSearch(query);
                    return (videoResult.videos.length > 1) ? videoResult.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 your video');
                }
            }

            if (!server_queue){
                
                const queue_constructor = {
                    voice_channel: voice_channel,
                    text_channel: message.channel,
                    connection: null,
                    audioPlayer: null, // 新增播放器存储字段
                    songs: []
                }
    
                queue.set(message.guild.id, queue_constructor);
                queue_constructor.songs.push(song);
    
                try {
                    const connection = await joinVoiceChannel({
                        channelId: message.member.voice.channel.id,
                        guildId: message.guild.id,
                        adapterCreator: message.guild.voiceAdapterCreator
                      })
                    // 创建播放器并绑定到连接
                    const audioPlayer = createAudioPlayer();
                    connection.subscribe(audioPlayer);
                    queue_constructor.connection = connection;
                    queue_constructor.audioPlayer = audioPlayer;
                    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(`<:seelio:811951350660595772> **${song.title}** added to queue`);
            }
        }
    }
}

const video_player = async (guild, song) => {
    const song_queue = queue.get(guild.id);
        
    if(!song) {
        // 替换原有leave方法
        song_queue.connection.destroy();
        queue.delete(guild.id);
        return;
    }
    const stream = ytdl(song.url, { filter: 'audioonly', highWaterMark: 1 << 25 });
    // 创建音频资源
    const audioResource = createAudioResource(stream, {
        inputType: StreamType.Arbitrary,
        inlineVolume: true
    });
    // 设置音量
    audioResource.volume.setVolume(0.5);
    // 调用播放器播放
    song_queue.audioPlayer.play(audioResource);
    
    // 监听播放结束事件
    song_queue.audioPlayer.once('idle', () => {
        song_queue.songs.shift();
        video_player(guild, song_queue.songs[0]);
    });
    // 监听播放错误
    song_queue.audioPlayer.once('error', (err) => {
        console.error('播放出错:', err);
        song_queue.songs.shift();
        video_player(guild, song_queue.songs[0]);
    });
    
    // 修复模板字符串语法错误,替换单引号为反引号
    await song_queue.text_channel.send(`<:seelio:811951350660595772> Now Playing **${song.title}**`)
}

额外注意

如果运行后仍出现无法拉取音频流的问题,可将ytdl-core依赖更新到最新版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:27:01