简体   繁体   English

在开始阅读下一个之前等待每个 playStream() 完成

[英]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!欢迎任何建议,提前致谢!

  • You want to play multiple MP3 files by downloading them from the specific folder in Google Drive.您想通过从 Google Drive 中的特定文件夹下载多个 MP3 文件来播放它们。
  • You have already been able to play the MP3 data at the voice channel and use Drive API.您已经可以在语音通道播放 MP3 数据并使用 Drive API。
  • You want to achieve this using discord.js and googleapis with Node.js.您想使用 discord.js 和 googleapis 和 Node.js 来实现这一点。

If my understanding is correct, how about this answer?如果我的理解是正确的,这个答案怎么样? Please think of this as just one of several possible answers.请将此视为几种可能的答案之一。

Modification points:改装要点:

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 放入语音通道。

Modified script:修改后的脚本:

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));
  }
);
  • In this sample script, when all MP3 files were finished, end is shown in the console.在此示例脚本中,当所有 MP3 文件完成后,控制台中会显示end

References:参考:

If I misunderstood your question and this was not the direction you want, I apologize.如果我误解了您的问题并且这不是您想要的方向,我深表歉意。

Edit:编辑:

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 上特定文件夹中的所有文件都会下载每个文件,并与流一起播放。

Sample script:示例脚本:

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));
  }
);
  • The function of playFiles() is called from above script. playFiles()的函数是从上面的脚本中调用的。
Function of playFiles() 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)); } ); }
  • In this case, 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.我确认,当不使用它时,存在下一次​​播放时无法从第二个文件中听到声音的情况。 Please be careful this.请注意这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 nodejs 中开始下一个循环之前,等待每个 for 循环迭代完成 - Wait on each for loop iteration to finish before starting the next in nodejs 如何在开始下一个功能之前等待功能完成? - How to wait for function finish before starting with next function? 等待一个插件完成注册,然后再继续注册下一个插件 - Wait for one plugin to finish registering, before proceeding to register the next one Jest:在运行下一个测试之前等待异步测试完成 - Jest: Wait for an async test to finish before running the next one 在执行下一个操作之前等待循环完成 - Wait for the loop to finish before performing the next action 在执行下一个 function 之前等待 writestream 完成 - wait for writestream to finish before executing next function 等待 promise 完成,然后执行下一个 - wait for a promise to finish and then execute the next one createReadStream 在启动第二个 createReadStream 之前等待第一个完成 - createReadStream wait for first to finish before starting second createReadStream 等待函数完成,然后在Node JS中触发下一个函数 - Wait for a function to finish before firing the next in Node JS 在运行下一个 .then - node.js 之前等待下载方法完成 - Wait for download method to finish before running next .then - node.js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM