Bypassing Google TTS Engine initialization lag in Android

I'm the developer of the Android application Saiy. That isn't a shameless plug, it's to demonstrate that I use the design pattern you are considering and I've 'been through' what has prompted your question.

It's fresh in my mind, as I've spent the last year rewriting my code and had to give great consideration to the surrounding issue.

  • Can we somehow reduce or eliminate the initialization delay of Google TTS Engine, programmatically or otherwise?

I asked a similar question some time ago and initialising the Text to Speech object on a background thread where it is not competing with other tasks, can reduce the delay slightly (as I see you are already doing in your posted code).

You can also make sure that the request to speak is not being delayed further by selecting an embedded voice, rather than one dependent on a network:

In API 21+ check out the options on the Voice class. Particularly getFeatures() where you can examine the latency and requirement for a network.

In API <21 - Set the KEY_FEATURE_NETWORK_SYNTHESIS to false inside your parameters.

Regardless of the above, the Google TTS Engine has the longest initialisation time of any of the engines I've tested (all of them I think). I believe this is simply because they are using all available resources on the device to deliver the highest quality voice they can.

From my own personal testing, this delay is directly proportional to the hardware of the device. The more RAM and performant the processor, the less the initialisation time. The same came be said for the current state of the device - I think you'll find that after a reboot, where there is free memory and Android will not need to kill other processes, the initialisation time will be reduced.

In summary, other than the above mentioned, no, you cannot reduce the initialisation time.

  • Is there any way through which I can keep the TextToSpeech object alive and initialized at all times like say, through a service? Or would this be a bad, resource-consuming design?

  • Also is using a static TextToSpeech object the right way to go, for my requirements?

As you've noted, a way to avoid the initialisation time, is to remain bound to the engine. But, there are further problems that you may wish to consider before doing this.

If the device is in a state where it needs to free up resources, which is the same state that causes an extended initialisation delay, Android is well within its rights to garbage collect this binding. If you hold this binding in a background service, the service can be killed, putting you back to square one.

Additionally, if you remain bound to the engine, your users will see the collective memory usage in the Android running application settings. For the many, many users who incorrectly consider (dormant) memory usage directly proportional to battery drain, from my experience, this will cause uninstalls and poor app ratings.

At the time of writing, Google TTS is bound to my app at a cost of 70mb.

If you still want to proceed on this basis, you can attempt to get Android to prioritise your process and kill it last - You'd do this by using a Foreground Service. This opens another can of worms though, which I won't go into.

Effectively, binding to the engine in a service and checking that service is running when you want the engine to speak, is a 'singleton pattern'. Making the engine static within this service would serve no purpose that I can think of.

You can see here how I begin to handle TTS initialisation and the associated problems that can occur - lag included.

Finally, to share my experience as to how I've dealt with the above.

I have 'Google is slow to initialise' at the top of my 'known bugs' and 'FAQ' in the application.

I monitor the time it takes for the engine to call onInit. If it's taking too long, I raise a notification to the user and direct them to the FAQ, where they are gently advised to try another TTS engine.

I run a background timer, that releases the engine after a period of inactivity. This amount of time is configurable by the user and comes with initialisation delay warnings...

I know the above doesn't solve your problems, but perhaps my suggestions will pacify your users, which is a distant second to solving the problem, but hey...

I've no doubt Google will gradually increase the initialisation performance - Four years ago, I was having this problem with IVONA, who eventually did a good job on their initialisation time.