I am trying to create a website that scrapes a news website and reads it. For some reason, whenever I am trying to read the actual info of the article, it reads part of it and stops after a few seconds.
important to point out :
My function :
export async function textToSpeech(text) {
new Promise((resolve) => {
let msg = new SpeechSynthesisUtterance();
msg.voice = voices[6];
msg.lang = "en";
msg.text = text;
speechSynthesis.speak(msg);
msg.addEventListener("end", () => {
resolve();
});
});
}
calling the function :
ReadNews(data) {
textToSpeech(data.Title)
.then(textToSpeech(data.Info))
.then(textToSpeech("Would You like me to continue?"))
.then(
ContinueCON.addEventListener("click", () => {
textToSpeech(data.Content);
})
);
};
The first 3 instances (data.title, data.info, and the default message) are all spoken as expected. But on the 4th instance, stops after a few seconds.
Several things I have tried:
I used window.speechSynthesis.speaking right after the sound stopped working, and it printed true(which is very bizarre)
1st Edit (Yet to be solved)
Changed the code by the comments below
export function textToSpeech(text) {
return new Promise((resolve) => {
let msg = new SpeechSynthesisUtterance();
msg.voice = voices[6];
msg.lang = "en";
msg.text = text;
speechSynthesis.cancel(msg);
speechSynthesis.speak(msg);
msg.addEventListener("end", () => {
resolve();
});
});
}
Async was unnecessary and also "clean" the "Speak" queue (by using cancel)
ReadNews(data) {
textToSpeech(data.Title)
.then(() => textToSpeech(data.Info))
.then(() => textToSpeech("Would You like me to continue?"))
.then(() =>
ContinueCON.addEventListener("click", () => {
textToSpeech(data.Content);
})
);
},
};
I invoked the return value immediately instead of waiting for a resolve and then running the next line of text. Problem is yet to be solved.
I see a couple issues with your code, which are causing the speech to all get queued up right away, without waiting. But speechSynthesis is supposed to handle that automatically, so it's not clear to me how they would cause what you're seeing. Still, i'll point them out in case they're causing your problem in a subtle way that i can't identify.
The first issue is that your textToSpeech function doesn't return the promise it creates. A promise is implicitly returned since it's an async function, but that promise will not wait for the speech to finish. The fix for this is to add a return in (and you can also remove async if you wish, since you're not awaiting anything)
export function textToSpeech(text) {
return new Promise((resolve) => {
let msg = new SpeechSynthesisUtterance();
msg.voice = voices[6];
msg.lang = "en";
msg.text = text;
speechSynthesis.speak(msg);
msg.addEventListener("end", () => {
resolve();
});
});
}
Secondly, ReadNews is not waiting for the promises to finish. .then(textToSpeech(data.Info)) means "immediately call textToSpeech, passing in data.Info, and then whatever it returns pass that into .then". Instead, you want to pass a function into .then, so that the function will be called once the previous promise has resolved:
ReadNews(data) {
textToSpeech(data.Title)
.then(() => textToSpeech(data.Info))
.then(() => textToSpeech("Would You like me to continue?"))
.then(
() => ContinueCON.addEventListener("click", () => {
textToSpeech(data.Content);
})
);
}
Or with async/await:
async ReadNews(data) {
await textToSpeech(data.Title);
await textToSpeech(data.Info);
await textToSpeech("Would you like me to continue?");
ContinueCON.addEventListener("click", () => {
textToSpeech(data.Content);
})
}