如何等到循环内的语音结束?
How to wait until speech is finished inside Loop?
我想 halt/wait for 循环直到 window.speechSynthesis.speak(audio)
完成阅读文本,然后转到下一次迭代。我有以下代码:
var all = "Oak is strong and also gives shade \n \
Cats and dogs each hate the other \n \
The pipe began to rust while new \n Bye."
sentences = all.split('\n')
for (i = 0; i < sentences.length; i++) {
sentence = sentences[i]
console.log(sentences[i]);
audio = new SpeechSynthesisUtterance(sentence)
window.speechSynthesis.speak(audio)
}
现在我想要的是,每个 sentences[i]
打印一次。在window.speechSynthesis.speak(audio)
完成之前不会打印下一个sentences[i]
,一旦演讲结束,将在下一次迭代中打印sentences[i]
。
那么我怎样才能让循环等到一个函数没有完成呢?
注意:我可以让它等待一个恒定的时间,但我想要一个动态等待,即等待时间应该与window.speechSynthesis.speak(audio)
需要的时间一样长完成正文。
对于 SpeechSynthesisUtterance
API 有一个 onend
事件你可以玩 (SpeechSynthesisUtterance: end event)。
所以我想您可以在 onend
中添加一个事件侦听器,您需要在其中调用下一次迭代的代码。一种好的技术是在异步情况下使用 Promise
来等待回调完成。我根据你的问题为上述案例创建了一个工作示例:
(function() {
play();
async function play() {
let all = "Oak is strong and also gives shade \n \
Cats and dogs each hate the other \n \
The pipe began to rust while new \n Bye.";
sentences = all.split('\n');
for (i = 0; i < sentences.length; i++) {
await getNextAudio(sentences[i]);
}
async function getNextAudio(sentence) {
console.log(sentence);
let audio = new SpeechSynthesisUtterance(sentence);
window.speechSynthesis.speak(audio);
return new Promise(resolve => {
audio.onend = resolve;
});
}
}
})();
如果您对更多细节感兴趣,请访问以下链接进一步阅读:
该解决方案非常有效,希望对您有所帮助!
还有一个启动事件,您可以像这样使用它:
for (i = 0; i < sentences.length; i++) {
const sentence = sentences[i];
const audio = new SpeechSynthesisUtterance(sentence);
audio.onstart = () => console.log(audio.text);
speechSynthesis.speak(audio);
}
或稍短:
for (const sentence of sentences) {
const audio = new SpeechSynthesisUtterance(sentence);
audio.onstart = () => console.log(audio.text);
speechSynthesis.speak(audio);
}
PS 您可以修改代码的顶部以使用 const(或 let)代替 var,如下所示:
const all = "Oak is strong and also gives shade \n \
Cats and dogs each hate the other \n \
The pipe began to rust while new \n Bye.";
const sentences = all.split('\n');
我想 halt/wait for 循环直到 window.speechSynthesis.speak(audio)
完成阅读文本,然后转到下一次迭代。我有以下代码:
var all = "Oak is strong and also gives shade \n \
Cats and dogs each hate the other \n \
The pipe began to rust while new \n Bye."
sentences = all.split('\n')
for (i = 0; i < sentences.length; i++) {
sentence = sentences[i]
console.log(sentences[i]);
audio = new SpeechSynthesisUtterance(sentence)
window.speechSynthesis.speak(audio)
}
现在我想要的是,每个 sentences[i]
打印一次。在window.speechSynthesis.speak(audio)
完成之前不会打印下一个sentences[i]
,一旦演讲结束,将在下一次迭代中打印sentences[i]
。
那么我怎样才能让循环等到一个函数没有完成呢?
注意:我可以让它等待一个恒定的时间,但我想要一个动态等待,即等待时间应该与window.speechSynthesis.speak(audio)
需要的时间一样长完成正文。
对于 SpeechSynthesisUtterance
API 有一个 onend
事件你可以玩 (SpeechSynthesisUtterance: end event)。
所以我想您可以在 onend
中添加一个事件侦听器,您需要在其中调用下一次迭代的代码。一种好的技术是在异步情况下使用 Promise
来等待回调完成。我根据你的问题为上述案例创建了一个工作示例:
(function() {
play();
async function play() {
let all = "Oak is strong and also gives shade \n \
Cats and dogs each hate the other \n \
The pipe began to rust while new \n Bye.";
sentences = all.split('\n');
for (i = 0; i < sentences.length; i++) {
await getNextAudio(sentences[i]);
}
async function getNextAudio(sentence) {
console.log(sentence);
let audio = new SpeechSynthesisUtterance(sentence);
window.speechSynthesis.speak(audio);
return new Promise(resolve => {
audio.onend = resolve;
});
}
}
})();
如果您对更多细节感兴趣,请访问以下链接进一步阅读:
该解决方案非常有效,希望对您有所帮助!
还有一个启动事件,您可以像这样使用它:
for (i = 0; i < sentences.length; i++) {
const sentence = sentences[i];
const audio = new SpeechSynthesisUtterance(sentence);
audio.onstart = () => console.log(audio.text);
speechSynthesis.speak(audio);
}
或稍短:
for (const sentence of sentences) {
const audio = new SpeechSynthesisUtterance(sentence);
audio.onstart = () => console.log(audio.text);
speechSynthesis.speak(audio);
}
PS 您可以修改代码的顶部以使用 const(或 let)代替 var,如下所示:
const all = "Oak is strong and also gives shade \n \
Cats and dogs each hate the other \n \
The pipe began to rust while new \n Bye.";
const sentences = all.split('\n');