Дождитесь окончания каждой playStream (), прежде чем начинать читать следующую - PullRequest
0 голосов
/ 23 декабря 2019

У меня есть музыкальная библиотека в формате .mp3, хранящаяся в папке Google Drive, с кучей музыкальных файлов, которые я хочу воспроизводить один за другим. Я могу читать и передавать каждый файл по отдельности, но когда я пытаюсь «поставить в очередь» все файлы из папки и воспроизводить их один за другим, он не будет ждать, пока не закончится воспроизведение одного потока (песни), чтобы воспроизвестиnext и сразу же запускает следующий, что приводит к тому, что из всей папки воспроизводится только последняя песня. Я предполагаю, что мне придется возиться с async / await, который я делал ранее при разработке discord.js, или с 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(), так как я нене хочу, чтобы он ушел сразу после того, как песни закончили играть.

Любой совет приветствуется, заранее спасибо!

1 Ответ

1 голос
/ 23 декабря 2019
  • Вы хотите воспроизвести несколько файлов MP3, загрузив их из определенной папки на Google Диске.
  • Вы уже можете воспроизводить данные MP3 на голосовом канале и использовать Drive API.
  • Вы хотите добиться этого, используя discord.js и googleapis с Node.js.

Если мое понимание верно, как насчет этого ответа? Пожалуйста, подумайте об этом как об одном из нескольких возможных ответов.

Точки изменения:

В этом ответе MP3-файлы, загруженные googleapis, преобразуются в поток и помещаются в голосовой канал с диссонансом. .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 Диске загружаются каждый файл, который воспроизводится в потоке.

Пример сценария:

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() важно. Я подтвердил, что когда это не используется, есть случаи, когда при следующем воспроизведении звук не может быть прослушан из 2-го файла. Пожалуйста, будьте осторожны с этим.
...