SDK AWS Polly Javascript «ThrottlingException: превышена скорость» - PullRequest
0 голосов
/ 24 января 2019

В настоящее время я использую amazon polly для создания звуковых файлов из данных, однако, когда я запускаю свой скрипт, я получаю сообщение об ошибке:

ThrottlingException: скорость превышена.

Что у меня сейчас

Вот функция, которую я использую

function createAudioFiles(data, outputDir) {
  console.log('in createAudioFiles with data: ' , data);

  return new Promise((resolve, reject) => {
    let successessfullyCompletedAmount = 0;

    for ({ audioText, filename } of data) {

        createAudio(audioText, filename, outputDir)
        .then(({ status, message }) => {
          if (status == "success") {
            successessfullyCompletedAmount++;
            console.log(message);
          }

          // if all audio files have been created
          if (successessfullyCompletedAmount == data.length) {
            resolve({
              status: 'success',
              message: "successfully created audioFiles"
            })
          }

        })

    }
  });
}

Функция createAudio в этой функции:

function createAudio(text, filename, outputDir) {

  let params = {
    'Text': text,
    'OutputFormat': 'mp3',
    'VoiceId': 'Amy'
  };

  return new Promise((resolve, reject) => {

        Polly.synthesizeSpeech(params, (err, data) => {

            if (err) {
                console.log("errors found");
                console.log(err);
            } else if (data) {
                if (data.AudioStream instanceof Buffer) {
                    fs.writeFile(`${outputDir}/${filename}`, data.AudioStream, function (err) {
                        if (err) {
                            return reject({
                                status: "error",
                                message: err
                            })
                        }
                        resolve({
                            status: "success",
                            message: filename + " saved"
                        });
                    })
                }
            }

        });

  })



}.

Что я пытался.

Я попытался добавить оболочку setTimeout() в цикл for следующим образом:

setTimeout(function() {
        for ({ audioText, filename } of data) {

            createAudio(audioText, filename, outputDir)
            .then(({ status, message }) => {
            if (status == "success") {
                successessfullyCompletedAmount++;
                console.log(message);
            }

            // if all audio files have been created
            if (successessfullyCompletedAmount == data.length) {
                resolve({
                status: 'success',
                message: "successfully created audioFiles"
                })
            }

            })
        }
    }, 2000);

но это, похоже, ничего не меняет. Я думаю, что происходит, когда все данные собираются и отправляются одновременно.

Что я хочу, чтобы произошло.

Я бы хотел добавить небольшую задержку между каждым 'get' от amazon, чтобы замедлить скорость.

1 Ответ

0 голосов
/ 25 января 2019

, чтобы добавить некоторую задержку между каждым вызовом createAudio, вы можете сделать что-то вроде этого:

return new Promise((resolve, reject) => {
    let successessfullyCompletedAmount = 0;
    let timeOutputDelay = 0;
    for ({ audioText, filename } of data) {
        setTimeout(function() {
            createAudio(audioText, filename, outputDir)
                .then(({ status, message }) => {
                    // [...]
                })
        } 1000 * timeOutputDelay);
        timeOutputDelay++;
    }
});

каждый setTimeout() будет иметь задержку в зависимости от того, сколько элементов уже зациклено.

Это решение не идеально, потому что вы не ждете, пока предыдущее поколение будет выполнено, прежде чем запускать следующее.

Таким образом, другой подход состоит в том, чтобы связать все Promise.then с помощью:

  • массив генерации аудио.
  • Помощник Array.reduce.

При таком подходе вы объедините каждый элемент в цепочку, и ваш код будет ждать окончания тока перед тем, как начинать следующий.

const createDummyAsyncPromise = (audio : {text: string, delay: number}) => {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(`Mp3 generated for text : ${audio.text}`);
      }, audio.delay);
  });
}

const audios = [
  {text: 'text 1', delay: 2000},
  {text: 'text 2', delay: 200},
  {text: 'text 3', delay: 10},
  {text: 'text 4', delay: 1000}
];
audios.reduce((promiseChain, audio) => {
    return promiseChain.then(audioResults =>
        createDummyAsyncPromise(audio).then(audioResult =>
            [ ...audioResults, audioResult ]
        )
    );
}, Promise.resolve([])).then(audios => {
    // Do something with all results
    console.log(audios);
});

живой образец

...