我在Google云端硬盘文件夹中存储了一个.mp3格式的音乐库,其中包含一堆我希望能够一个接一个播放的音乐文件。我能够分别读取和流式传输每个文件,但是当我尝试从文件夹中“排队”所有文件并一个接一个地播放时,它不会等到一个流(歌曲)播放完毕后再播放。下一步,而是立即开始下一首歌曲,这将导致整个文件夹中只播放最后一首歌曲。我以为我必须弄乱我先前在discord.js开发中所做的async / await,或者不熟悉的Promises和Promise.all()。这是代码的相关部分。
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));
});
});
});
请注意,我有一条命令使漫游器离开频道,因此正常情况下我的代码中没有任何voiceChannel.leave()
,因为我不希望它在歌曲播放完毕后就离开玩。
欢迎任何建议,谢谢!
答案 0 :(得分:1)
如果我的理解正确,那么这个答案如何?请认为这只是几个可能的答案之一。
在此答案中,由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
。如果我误解了您的问题,而这不是您想要的方向,我深表歉意。
在以下示例脚本中,每一个文件都会下载Google云端硬盘上特定文件夹中的所有文件,并与流一起播放。
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()
的功能是从上面的脚本调用的。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()
很重要。我确认不使用此功能时,在某些情况下,下一场播放时,无法从第二个文件收听声音。请注意这一点。