As evident from the evolution of my first iOS app: My Day Todos; it started off as being a pure Html5 app until it turned into a native iOS app with Html5 powered UI. The app has a very significant text to speech component and before using native iOS API for it i.e. AvSpeechSynthesizer, the text to speech component was powered by the Web Speech API. I will not be talking  about why I switched the AvSpeechSynthesizer but rather a little problem that I had to solve while working with the web speech API.

Problem: Show a stop button only when an utterance is being spoken

So firstly, I think the Web Speech API is a lot of fun to play with and if you like to know more about it, you can either have a read of the spec or do this tutorial to get a feel of how it all works. Also when I talk about the web speech API, I am only talking about speech synthesis.
All right, so what I wanted in my app was to show a stop button when the app is speaking i.e. reading out something and only when it is speaking and not when it’s not. I did not want the stop button to be visible at all times. 

Solution: A boolean and a timeout

The speech synthesis API has a boolean which would tell us if the speech is currently being spoken. You can have a look at the speaking attribute in the spec or typing window.speechSynthesis.speaking in Chrome developer tools console should return a boolean. So my solution was to combine the speaking attribute with setTimeout. Ok, I am not sure if this is the best solution to this problem, but it is a solution none the less, if you know of a better solution then please let me know by leaving a comment for this post.

Solution implementation

So the goal is to check at specified time intervals if an utterance is being spoken as soon we trigger the speech i.e. as soon as we make our web page start speaking. I have created a little demo of my solution that you can download from Github.

All right, let’s have a look at the source for my solution on Github,
Firstly we have our webpage,
<p> Speak an arbitrary long string of text</p>
<button id="speak" onclick="speak()" style="float:left;margin-right:2px;"> Speak </button>
<button id="stop" style="display:none;" onclick="stopSpeech()" > Stop </button>
It tells us that some arbitrary text will be spoken, when we click the button to speak and then we have a stop button which is not visible by default. 
FYI, I wanted to make a simple example to demonstrate my solution about so I did not bother adding CSS classes in a separate CSS file to style the contents. 
Ok, now let’s look at the code (Javascript) that’s invoked when Start and Stop buttons are clicked.
function speak(){
var speechText ="This is a long, a very long string of text that I need to speak";
var utterance = new SpeechSynthesisUtterance(speechText);
document.getElementById("speak").disabled = true;
document.getElementById("stop").style.display = "block";
function checkSpeaking(){
setTimeout(checkSpeaking, 50);
} else {
document.getElementById("speak").disabled = false;
document.getElementById("stop").style.display = "none";
function stopSpeech(){
document.getElementById("speak").disabled = false;
document.getElementById("stop").style.display = "none";
The code is pretty self-explanatory but should you have any questions, then feel free to ask. The only thing to note is, just see how we toggle the enabled state of the speak button and the visibility of the stop button? Now let’s think of this in terms of states, so our little web page has 2 states,
  1. Not speaking: Speak button enabled and stop button invisible
  2. Speaking: Speak button disabled and Stop button visible
the states are controlled by the Speak and Stop buttons. However, what I wanted out of this was to ensure that the Stop button is only visible when something is being spoken so I added the timeout, which checks at periodic intervals if an utterance is being spoken. That is what the checkSpeaking method is for i.e. if an utterance is being spoken then leave the state to Speaking and if it is not then change the state to Not speaking.


This is yet another problem that I had to solve while building my iOS app My Day Todos, which I wanted to share with everyone. If you have had to solve this problem and you have a different solution, then I would love to hear about it, so please leave a comment.

Finally, I am working on my app full-time right now so if you find my blog posts useful and want to support me you can 

  • Or one of the cheaper versions, L or W

Any feedback on my apps or the way I write my post, would be great.

Leave a Reply

Your email address will not be published. Required fields are marked *