5

Currently, I have implemented text to speech (TTS) to read Books. Since TTS only allows up to 4000 chars (and a book is wayyyy more than that) I split the book up and add each part to the TTS queue. I wanna be able to click a button and pause the TTS and then later resume the TTS from where the user left off.

I have tried using synthesizeToFile and pausing the media file object but again you can only synthesize one file at a time which is less then 4000 chars. I don't want to have hundreds of media files stored on the users device just for TTS.

I can make the TTS read the book, I just can't pause without stopping it and then having to start the TTS from the beginning of the book.

In the code below, I have the entire book stored in a string bookText. The TTS engine is the tts variable.

This is how I load the TTS queue:

int position = 0;
int pos = 0;

int sizeOfChar = bookText.length();
String testString = bookText.substring(position,sizeOfChar);

int next = 500;

while(true) {
    String temp = "";

    try {
        temp = testString.substring(pos, next);
        HashMap<String, String> params = new HashMap<String, String>();
        params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, temp);
        tts.speak(temp, TextToSpeech.QUEUE_ADD, params);

        pos = pos + 500;
        next = next + 500;

    }
    catch (Exception e) {
       temp = testString.substring(pos, testString.length());
       tts.speak(temp, TextToSpeech.QUEUE_ADD, null);
       break;
    }
}

This is how I "stop" the TTS:

tts.speak("Pausing!", TextToSpeech.QUEUE_FLUSH, null);
Justin Braham
  • 133
  • 4
  • 12
  • Take a look at my question here for help splitting the strings at natural language 'pauses' https://stackoverflow.com/q/23353671/1256219 – brandall Apr 03 '18 at 08:21

1 Answers1

7

Since the TextToSpeech class doesn't have pause/resume methods, I would suggest doing the following:

1) Divide the book into sentences instead of 500 character blocks. (You could parse using "." as the delimiter).

2) Introduce a "master index" counter, X, that tracks progress as: we are at sentence # X / total sentences.

3) When user clicks pause, just use the stop() method.

4) When the user clicks resume, resume speech at the beginning of the sentence that was interrupted.

This will lead to better user comprehension (of the book) than literally pausing and resuming mid-sentence, anyway.

Nerdy Bunz
  • 6,040
  • 10
  • 41
  • 100
  • Since the `speak()` method is asynchronous, how will we get the current index? – Nipun Sep 26 '19 at 04:02
  • You could use an utterance progress listener and increment the index in the onDone() callback method. – Nerdy Bunz Sep 26 '19 at 19:20
  • Thanks.. Instead of incrementing the index directly in the `onDone()`, I created a function to play the speech and increment the index, then called that function in the `onDone()`. That worked. – Nipun Sep 27 '19 at 04:43