Skip to main content

Showing a stop speech button only when a webpage is speaking

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,

<body>
    <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>
</body>
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);
    window.speechSynthesis.speak(utterance);
    document.getElementById("speak").disabled = true;
    document.getElementById("stop").style.display = "block";
    function checkSpeaking(){
        if(window.speechSynthesis.speaking){
            setTimeout(checkSpeaking, 50);
        } else {
            document.getElementById("speak").disabled = false;
            document.getElementById("stop").style.display = "none";
        }
    }
    setTimeout(checkSpeaking,50);
}
function stopSpeech(){
    document.getElementById("speak").disabled = false;
    document.getElementById("stop").style.display = "none";
    window.speechSynthesis.cancel();
}
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.

Conclusion

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.



Comments

Popular posts from this blog

Upload to AWS S3 from Java API

In this post, you will see code samples for how to upload a file to AWS S3 bucket from a Java Spring Boot app. The code you will see here is from one of my open-source repositories on Github, called document-sharing. Problem Let’s say you are building a document sharing app where you allow your users to upload the file to a public cloud solution. Now, let’s say you are building the API for your app with Spring Boot and you are using AWS S3 as your public cloud solution. How would you do that? This blog post contains the code that can help you achieve that. Read more below,  Upload to AWS S3 bucket from Java Spring Boot app - My Day To-Do (mydaytodo.com)

Addressing app review rejections for auto-renewing subscription in-app purchase (iOS)

The ability to know what the weather is like while planning your day is a feature of  My Day To-Do  Pro and as of the last update it’s also a part of the  Lite version . Unlike the Pro version it’s an auto-renewing subscription based  in-app purchase (IAP)  in the Lite version. What means is that when a user purchases it, the user only pays for the subscription duration after which the user will be automatically charged for the next period. Adding an  auto-renewing  subscription based IAP proved to be somewhat challenging in terms of the app store review i.e. the app update was rejected by the App Review team thrice because of missing information about the IAP. Therefore in this post I will share my experiences and knowledge of adding auto-renewing IAP in hopes to save someone else the time that I had to spend on this problem. In-App purchase This year I started adding IAPs to My Day To-Do Lite which lead to learning about different types of IAP...

Getting started with iOS programming using Swift (Part 1)

I have not been too fond of Objective-C, which was the primary reason for me to stay away from making iOS apps till now. So what changed? Well Apple has done something very interesting recently and that is the introduction of a new programming language i.e. Swift. Swift is awesome, it almost feels like Python, C++ and Objective-C had a baby with some of their good parts in them. So I have been getting to know Swift and it is an awesome language to program in. What I am going to share with this and a series of blog posts are solutions to some problems that i have encounter while i am trying to finish my first iOS app. The one hurdle that I have encountered while getting started on developing an iOS app is that a majority of the solutions for iOS specific problems provide solutions to them using Objective-C. Which is fair, because Swift has not been around for that long. Anyway let us get started with a few basics, A few basics I would highly recommend having a read of this book...