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

Discord.js TypeScript机器人播放音频数秒后停止问题求助

问题分析与解决方案

你的问题核心确实是下载未完成就开始播放:代码中调用download.pipe(writestream)后立刻读取本地文件创建音频资源,但文件此时还在写入过程中,播放器读到文件当前的末尾(未完成的部分)就会停止,甚至可能因为文件还未生成直接播放失败。

优化方案(推荐直接用流播放,无需本地文件)

不需要把音频保存到本地,@discordjs/voice支持直接传入可读流创建音频资源,这样既省磁盘空间,又能避免文件写入的异步问题。修改后的execute函数如下:

export async function execute(interaction: CommandInteraction) {
    if (!interaction.guildId) {
        return interaction.reply("出现严重错误。");
    }

    const url = interaction.options.getString("link");
    const connection = getVoiceConnection(interaction.guildId);

    if (!connection) {
        return interaction.reply("机器人当前不在语音频道,请先让机器人加入频道再使用此命令。");
    }

    const audioplayer = createAudioPlayer({
        behaviors: {
            noSubscriber: NoSubscriberBehavior.Pause,
        },
    });

    // 直接用ytdl的流创建音频资源,无需保存本地
    const stream = ytdl(url, { filter: 'audioonly', highWaterMark: 1 << 25 });
    const resource = createAudioResource(stream, {
        inlineVolume: true,
        metadata: {
            title: "SONG",
        },
    });

    audioplayer.play(resource);
    connection.subscribe(audioplayer);

    return interaction.reply(`正在播放:${url}`);
}

备选方案(等待文件下载完成再播放)

如果一定要保存本地文件,需要监听文件写入完成的事件,再开始播放。可以把文件写入逻辑封装成Promise:

export async function execute(interaction: CommandInteraction) {
    if (!interaction.guildId) {
        return interaction.reply("出现严重错误。");
    }

    const url = interaction.options.getString("link");
    const connection = getVoiceConnection(interaction.guildId);

    if (!connection) {
        return interaction.reply("机器人当前不在语音频道,请先让机器人加入频道再使用此命令。");
    }

    const audioplayer = createAudioPlayer({
        behaviors: {
            noSubscriber: NoSubscriberBehavior.Pause,
        },
    });

    const download = ytdl(url, { filter: 'audioonly' });
    const writestream = fs.createWriteStream('audio.mp4');
    const pathtoresource = join('audio.mp4');

    // 封装文件写入完成的Promise
    await new Promise((resolve, reject) => {
        download.pipe(writestream);
        writestream.on('finish', resolve);
        writestream.on('error', reject);
        download.on('error', reject);
    });

    // 下载完成后再创建资源并播放
    const resource = createAudioResource(pathtoresource, {
        inlineVolume: true,
        metadata: {
            title: "SONG",
        },
    });

    audioplayer.play(resource);
    connection.subscribe(audioplayer);

    return interaction.reply(`正在播放:${url}`);
}

注意事项

  • 推荐使用第一种流播放方案,避免本地文件管理的麻烦,同时播放响应更快。
  • 你的intents配置没有问题,GuildVoiceStates已经包含了语音状态所需的权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:23:31