It seems that speechSynthesis is not allowed to run without user interaction, on some devices, some of the time. My PC browser used to warn about it, but now it works (I don't know if I managed to accidentally change something about permissions in the meantime), while my Android-powered tablet seems to allow it from localhost
on http
, but disallows it from my production site on https
. Phones always disallow it.
I'm wondering if there is some method of determining whether it's allowed on the running device, so that I can show a notice, or hide the options that offer text-to-speech in my app?
It's browser-dependent. Chrome, at least, used to permit speech by default without user interaction, but that changed a bit ago. One hacky way of checking would be to queue an empty utterance, then look to see if either SpeechSynthesis.speaking
or SpeechSynthesis.pending
is true
:
// Allowed:
btn.onclick = () => {
speechSynthesis.speak(new SpeechSynthesisUtterance(''));
const worked = speechSynthesis.speaking || speechSynthesis.pending;
console.log(worked);
};
<button id="btn">click</button>
// Not allowed, silent failure:
speechSynthesis.speak(new SpeechSynthesisUtterance(''));
const worked = speechSynthesis.speaking || speechSynthesis.pending;
console.log(worked);
Unfortunately, speechSynthesis.speak
doesn't throw (even asynchronously) when speech is prevented due to no user interaction first, so checking the speaking
property looks to be the only other way.