AWS Polly Javascript SDK'ThrottlingException:超出速率'

时间:2019-01-24 17:04:09

标签: javascript amazon-web-services promise amazon-polly

我目前正在使用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);

但是这似乎并没有改变任何东西。我认为正在发生的事情是似乎所有数据都可以立即收集并发送。

我想发生的事情。

我想在每次从亚马逊“获得”之间添加一个小的延迟,以减慢汇率。

1 个答案:

答案 0 :(得分:0)

要在每次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);
});

live sample