簡體   English   中英

在開始閱讀下一個之前等待每個 playStream() 完成

[英]Wait for each playStream() to finish before starting to read the next one

我在 Google Drive 文件夾中存儲了一個 .mp3 格式的音樂庫,里面有一堆音樂文件,我希望能夠一個接一個地播放。 我能夠單獨讀取和流式傳輸每個文件,但是當我嘗試將文件夾中的所有文件“排隊”並一個接一個播放它們時,它不會等到一個流(歌曲)播放完畢才能播放next,而是立即開始下一首,這會導致整個文件夾中只播放最后一首歌曲。 我假設我必須處理我之前在 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()是正常的,因為我不希望它在歌曲播放完畢后立即離開。

歡迎任何建議,提前致謝!

  • 您想通過從 Google Drive 中的特定文件夾下載多個 MP3 文件來播放它們。
  • 您已經可以在語音通道播放 MP3 數據並使用 Drive API。
  • 您想使用 discord.js 和 googleapis 和 Node.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));
  }
);
  • 在此示例腳本中,當所有 MP3 文件完成后,控制台中會顯示end

參考:

如果我誤解了您的問題並且這不是您想要的方向,我深表歉意。

編輯:

在以下示例腳本中,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()的函數是從上面的腳本中調用的。
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()很重要。 我確認,當不使用它時,存在下一次​​播放時無法從第二個文件中聽到聲音的情況。 請注意這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM