0

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

但这似乎并没有改变任何东西。我认为正在发生的是所有数据似乎都是一次收集和发送的。

我想要发生的事情。

我想在亚马逊的每个“获取”之间添加一个小延迟以减慢速度。

4

1 回答 1

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);
});

现场样品

于 2019-01-25T05:47:10.583 回答