使用 discord.js 和 ytdl-core 播放音频文件

Playing an audio file using discord.js and ytdl-core

我正在尝试使用 ytdl 和 discord.js 下载并播放从 youtube 获取的音频文件:

        ytdl(url)
            .pipe(fs.createWriteStream('./music/downloads/music.mp3'));

        var voiceChannel = message.member.voiceChannel;
        voiceChannel.join().then(connection => {
            console.log("joined channel");
            const dispatcher = connection.playFile('./music/downloads/music.mp3');
            dispatcher.on("end", end => {
                console.log("left channel");
                voiceChannel.leave();
            });
        }).catch(err => console.log(err));
        isReady = true

我成功播放了 ./music/downloads/ 中没有 ytdl 部分的 mp3 文件 (ytdl(url).pipe(fs.createWriteStream('./music/downloads/music.mp3'));)。但是当那部分在代码中时,机器人只是加入和离开。

这是带有 ytdl 部分的输出:

Bot has started, with 107 users, in 43 channels of 3 guilds.
joined channel
left channel

这里是没有 ytdl 部分的输出:

Bot has started, with 107 users, in 43 channels of 3 guilds.
joined channel
[plays mp3 file]
left channel

为什么会这样,我该如何解决?

当您需要播放音频流时,请使用 playStream 而不是 playFile。

const streamOptions = { seek: 0, volume: 1 };
var voiceChannel = message.member.voiceChannel;
        voiceChannel.join().then(connection => {
            console.log("joined channel");
            const stream = ytdl('https://www.youtube.com/watch?v=gOMhN-hfMtY', { filter : 'audioonly' });
            const dispatcher = connection.playStream(stream, streamOptions);
            dispatcher.on("end", end => {
                console.log("left channel");
                voiceChannel.leave();
            });
        }).catch(err => console.log(err));

You're doing it in an inefficient way. There's no synchronization between reading and writing.
Wait for the file to be written to the filesystem, then read it!

直接直播

重定向 YTDL 的视频输出到调度程序,它会首先转换为 opus 音频数据包,然后从您的计算机流式传输到 Discord。

message.member.voiceChannel.join()
.then(connection => {
    console.log('joined channel');

    connection.playStream(ytdl(url))
    // When no packets left to send, leave the channel.
    .on('end', () => {
        console.log('left channel');
        connection.channel.leave();
    })
    // Handle error without crashing the app.
    .catch(console.error);
})
.catch(console.error);

FWTR(先写后读)

您使用的方法非常接近成功,但失败是在您不同步时 read/write。

var stream = ytdl(url);

// Wait until writing is finished
stream.pipe(fs.createWriteStream('tmp_buf_audio.mp3'))
.on('end', () => {
    message.member.voiceChannel.join()
    .then(connection => {
        console.log('joined channel');

        connection.playStream(fs.createReadStream('tmp_buf_audio.mp3'))
        // When no packets left to send, leave the channel.
        .on('end', () => {
            console.log('left channel');
            connection.channel.leave();
        })
        // Handle error without crashing the app.
        .catch(console.error);
    })
    .catch(console.error);
});