我目前正在使用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);
但是这似乎并没有改变任何东西。我认为正在发生的事情是似乎所有数据都可以立即收集并发送。
我想在每次从亚马逊“获得”之间添加一个小的延迟,以减慢汇率。
答案 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
链接起来:
使用此方法,您可以将每个项目链接在一起,并且代码将在当前内容结束之前开始下一个项目。
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);
});