如何使用 Web Speech API 来听文本区域的每行单词,每行都有延迟?
How does one use the Web Speech API in a way that one can listen to the words of a textarea's lines, each line in a delayed way?
我正在尝试按行拆分文本区域,并使用文本到语音转换,以便每行都被朗读出来。
我想最终在每行之间添加 5 秒的延迟。
但是 for 循环没有按预期工作,我得到的是第一行的值,然后是最后一行中重复数组长度的值。
例如。
输入:
一种
乙
C
D
输出:
A, D, D, D
预计:
A、B、C、D
document.querySelector("#start").addEventListener("click", () => {
// Set the text property with the value of the textarea
textInput = document.getElementById("textarea");
textArray = textInput.value.split(/\n/g);
for (var i = 0; i<textArray.length; i++) {
textInput = document.getElementById("textarea");
textArray = textInput.value.split(/\n/g);
speech.text = textArray[i];
window.speechSynthesis.speak(speech);
}
});
如果 OP 的 speech
对象是 SpeechSynthesisUtterance
instance there is the possibility to listen to such an object's events like start
and end
。
因此,已经解决了通过 for 循环将数组的文本行立即提供给 speech.text
的问题,这主要是导致 read/spoken 只是第一行并重复最后一行的结果值。
通过引入事件处理程序,还可以通过 setTimeout
延迟事件处理,正如 OP 所希望的那样。
并且为了创建一个 cycle/loop 的延迟语音台词,人们可能会考虑使用一个 generator created by a generator function 来产生仍然可用/尚未使用的语音台词。
function* createLinePool(value) {
const listOfLines = String(value)
.split(/\n/g)
.map(line => line.trim())
.filter(line => line !== '');
let line;
while (line = listOfLines.shift()) {
yield line;
}
}
function readTextAreaLineWise() {
const recitation = new SpeechSynthesisUtterance();
const textInput = document.querySelector('#textarea');
const linePool = createLinePool(textInput.value);
function readLine() {
const nextLineItem = linePool.next();
if (!nextLineItem.done) {
console.log({ nextLineItem });
recitation.text = nextLineItem.value;
window.speechSynthesis.speak(recitation);
}
}
recitation.addEventListener('end', () => {
setTimeout(readLine, 2000);
});
// trigger first line getting read.
readLine();
}
document
.querySelector('#start')
.addEventListener('click', readTextAreaLineWise);
* { margin: 0; }
.as-console-wrapper {
min-height: 100%!important;
width: 50%;
left: auto!important;
right: 0;
}
#textarea { width: 48%; }
#start { display: block }
<textarea id="textarea" cols="26" rows="9">
Hallo world.
The quick brown fox,
jumps over the lazy dog.
</textarea>
<button id="start">Start</button>
我正在尝试按行拆分文本区域,并使用文本到语音转换,以便每行都被朗读出来。 我想最终在每行之间添加 5 秒的延迟。
但是 for 循环没有按预期工作,我得到的是第一行的值,然后是最后一行中重复数组长度的值。
例如。 输入: 一种 乙 C D
输出: A, D, D, D
预计: A、B、C、D
document.querySelector("#start").addEventListener("click", () => {
// Set the text property with the value of the textarea
textInput = document.getElementById("textarea");
textArray = textInput.value.split(/\n/g);
for (var i = 0; i<textArray.length; i++) {
textInput = document.getElementById("textarea");
textArray = textInput.value.split(/\n/g);
speech.text = textArray[i];
window.speechSynthesis.speak(speech);
}
});
如果 OP 的 speech
对象是 SpeechSynthesisUtterance
instance there is the possibility to listen to such an object's events like start
and end
。
因此,已经解决了通过 for 循环将数组的文本行立即提供给 speech.text
的问题,这主要是导致 read/spoken 只是第一行并重复最后一行的结果值。
通过引入事件处理程序,还可以通过 setTimeout
延迟事件处理,正如 OP 所希望的那样。
并且为了创建一个 cycle/loop 的延迟语音台词,人们可能会考虑使用一个 generator created by a generator function 来产生仍然可用/尚未使用的语音台词。
function* createLinePool(value) {
const listOfLines = String(value)
.split(/\n/g)
.map(line => line.trim())
.filter(line => line !== '');
let line;
while (line = listOfLines.shift()) {
yield line;
}
}
function readTextAreaLineWise() {
const recitation = new SpeechSynthesisUtterance();
const textInput = document.querySelector('#textarea');
const linePool = createLinePool(textInput.value);
function readLine() {
const nextLineItem = linePool.next();
if (!nextLineItem.done) {
console.log({ nextLineItem });
recitation.text = nextLineItem.value;
window.speechSynthesis.speak(recitation);
}
}
recitation.addEventListener('end', () => {
setTimeout(readLine, 2000);
});
// trigger first line getting read.
readLine();
}
document
.querySelector('#start')
.addEventListener('click', readTextAreaLineWise);
* { margin: 0; }
.as-console-wrapper {
min-height: 100%!important;
width: 50%;
left: auto!important;
right: 0;
}
#textarea { width: 48%; }
#start { display: block }
<textarea id="textarea" cols="26" rows="9">
Hallo world.
The quick brown fox,
jumps over the lazy dog.
</textarea>
<button id="start">Start</button>