[英]Wait for each playStream() to finish before starting to read the next one
I have a music library in .mp3 format stored in a Google Drive folder, with a bunch of music files I want to be able to play one after the other.我在 Google Drive 文件夹中存储了一个 .mp3 格式的音乐库,里面有一堆音乐文件,我希望能够一个接一个地播放。 I am able to read and stream each file individually, but when I try to "queue" all the files from the folder and play them one after the other, it won't wait till one stream (song) is done playing to play the next, and instead starts the next one immediately, which results in only the last song being played out of the entire folder.
我能够单独读取和流式传输每个文件,但是当我尝试将文件夹中的所有文件“排队”并一个接一个播放它们时,它不会等到一个流(歌曲)播放完毕才能播放next,而是立即开始下一首,这会导致整个文件夹中只播放最后一首歌曲。 I'd assume I have to mess around with async/await which I have done earlier in discord.js development, or with Promises and Promise.all(), which I am not familiar with.
我假设我必须处理我之前在 discord.js 开发中完成的 async/await,或者我不熟悉的 Promises 和 Promise.all()。 Here's the relevant part of the code.
这是代码的相关部分。
var folderId = "'the-folder-id'";
drive.files.list({
q: folderId + " in parents", // to get all the files in the folder
fields: 'files(id)'
}, (err, res) => {
if (err) throw err;
const files = res.data.files;
files.map(file => {
drive.files.get({
fileId: file.id,
alt: 'media'
},
{ responseType: "stream" },
(err, { data }) => {
message.member.voiceChannel.join().then(connection => {
const dispatcher = connection.playStream(data); // doesn't wait for this to finish to play the next stream (song)
}).catch(err => console.log(err));
});
});
});
Note that I have a command to make the bot leave the channel, so it's normal that there isn't any voiceChannel.leave()
in my code, as I don't want it to leave right after the songs have finished playing.请注意,我有一个命令让机器人离开频道,所以我的代码中没有任何
voiceChannel.leave()
是正常的,因为我不希望它在歌曲播放完毕后立即离开。
Any advice is welcome, thanks in advance!欢迎任何建议,提前致谢!
If my understanding is correct, how about this answer?如果我的理解是正确的,这个答案怎么样? Please think of this as just one of several possible answers.
请将此视为几种可能的答案之一。
In this answer, the MP3 files downloaded by googleapis are converted to the stream and put to the voice channel with discord.js.在这个答案中,googleapis 下载的 MP3 文件被转换为流,并使用 discord.js 放入语音通道。
var folderId = "'the-folder-id'";
drive.files.list(
{
q: folderId + " in parents", // to get all the files in the folder
fields: "files(id)"
},
(err, res) => {
if (err) throw err;
const files = res.data.files;
Promise.all(
files.map(file => {
return new Promise((resolve, reject) => {
drive.files.get(
{
fileId: file.id,
alt: "media"
},
{ responseType: "stream" },
(err, { data }) => {
if (err) {
reject(err);
return;
}
let buf = [];
data.on("data", function(e) {
buf.push(e);
});
data.on("end", function() {
const buffer = Buffer.concat(buf);
resolve(buffer);
});
}
);
});
})
)
.then(e => {
const stream = require("stream");
let bufferStream = new stream.PassThrough();
bufferStream.end(Buffer.concat(e));
message.member.voiceChannel
.join()
.then(connection => {
const dispatcher = connection.playStream(bufferStream);
dispatcher.on("end", () => {
// do something
console.log("end");
});
})
.catch(e => console.log(e));
})
.catch(e => console.log(e));
}
);
end
is shown in the console.end
。 If I misunderstood your question and this was not the direction you want, I apologize.如果我误解了您的问题并且这不是您想要的方向,我深表歉意。
In the following sample script, all files in the specific folder on Google Drive are downloaded every one file and that is played with the stream.在以下示例脚本中,Google Drive 上特定文件夹中的所有文件都会下载每个文件,并与流一起播放。
var folderId = "'the-folder-id'";
drive.files.list(
{
q: folderId + " in parents",
fields: "files(id,name)"
},
(err, res) => {
if (err) throw err;
const channel = message.member.voiceChannel;
channel
.join()
.then(connection => playFiles(drive, channel, connection, res.data.files))
.catch(e => console.log(e));
}
);
playFiles()
is called from above script. playFiles()
的函数是从上面的脚本中调用的。function playFiles(drive, channel, connection, files) { if (files.length == 0) { channel.leave(); return; } drive.files.get( { fileId: files[0].id, alt: "media" }, { responseType: "stream" }, (err, { data }) => { if (err) throw new Error(err); console.log(files[0]); // Here, you can see the current playing file at console. connection .playStream(data) .on("end", () => { files.shift(); playFiles(drive, channel, connection, files); }) .on("error", err => console.log(err)); } ); }
channel.leave()
is important.channel.leave()
很重要。 I confirmed that when this is not used, there are the cases that at the next play, the sound cannot be listened from 2nd file.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.