简体   繁体   中英

Android text to speech voice distortion at the beginning

In Android app I have a text, which after the user press a button, it will be spoken by TTS:

import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;

                       final Button speech = findViewById(R.id.speech);
                        speech.setOnClickListener(speech1 -> {
    
                            if (!isPackageInstalled("com.google.android.tts")) {
                                showMsgSnack(getString(R.string.noTTS));
                            } else {
                                Boolean speak = checkSpeak();
    
                                if (!speak) {
                                    speech.setCompoundDrawablesWithIntrinsicBounds(R.drawable.stop, 0, 0, 0);
                                    if (history.length() > 3999) {
                                        String var = history.substring(0, 3999);
                                        ConvertTextToSpeech(var, "test");
                                        String var2 = history.substring(3999);
                                        ConvertTextToSpeech(var2, "test");
                                    } else {
                                        ConvertTextToSpeech(history, "test");
                                    }
                                    saveSpeak(true);
                                } else {
                                    speech.setCompoundDrawablesWithIntrinsicBounds(R.drawable.play, 0, 0, 0);
                                    tts.stop();
                                    saveSpeak(false);
                                }
                            }
                        });
    
    private void ConvertTextToSpeech(String history, String par) {
        String readableText = fromHtml(history).toString(); //remove HTML tags -> do not read <br>
        Bundle params = new Bundle();
        params.putString(KEY_PARAM_UTTERANCE_ID, "");
        tts.speak(readableText, TextToSpeech.QUEUE_ADD, params, par);
    }

The stuff about TTS:

if ((isPackageInstalled("com.google.android.tts"))) {
tts=new TextToSpeech(SingleitemView.this, status -> {
    if(status == TextToSpeech.SUCCESS){
        if (isLangAvailable(this,tts,locale)) {tts.setLanguage(locale);}
        else {tts.setLanguage(new Locale("en"));}

       tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
            @Override
            public void onDone(String utteranceId) {
                // Log.d("Speak", "TTS finished");
                if (utteranceId.equals("test")) {
                saveSpeak(false);
                runOnUiThread(() -> {
                    Button view2 = findViewById(R.id.speech);
                    view2.setCompoundDrawablesWithIntrinsicBounds(R.drawable.play, 0, 0, 0);
                });
                }
            }

            @Override
            public void onError(String utteranceId) {
            }

            @Override
            public void onStart(String utteranceId) {
            }
        });

    }
},"com.google.android.tts");}

This worked for years without problems, the TTS read the text even if it was short, or more than 3999 characters. Suddenly a few months ago (without any change from my side in application) when it starts to speak longer text, the first 3-4 words are distorted and hardly understandable in every text.

Looks like as it is doing something in the background while it is reading the text in the same time.

Not sure what happened, because I dod no change in my code and it worked till now.

So now I tried to update all libraries and dependencies, but it didn't help.

The problem is only with the text, which is longer than 3999 chars. The shorter text is working with no issues.

I also tried to put this condition outside of onClickListener, so the text is prepared first:

                if (history.length() > 3999) {
String var = fromHtml(history.substring(0, 3999)).toString(); 
String var2 = fromHtml(history.substring(3999)).toString();                                                                                } 

and then in onClickListener I just call the TTS twice:

ConvertTextToSpeech(var, "test");
ConvertTextToSpeech(var2, "test");

private void ConvertTextToSpeech(String history, String par) {
        Bundle params = new Bundle();
        params.putString(KEY_PARAM_UTTERANCE_ID, "");
        tts.speak(history, TextToSpeech.QUEUE_ADD, params, par);
    }

But I have the same issue, this solution didn't helped.

I thought the issue is that I call immediately two ConvertTextToSpeech after each other, but even if I remove the second one, the problem is there.

So definitely, the problem is with the longer text, but I can't find the solution why it started to happen. I checked this on many devices, same issue everywhere.

The only thing that helps is to create much smaller chunks of text:

for (int a=1; a <= history.length(); a+=100) {
if((history.length() - (a + 100)) > 0) {ConvertTextToSpeech(history.substring(a, a+100), "test");}
else {ConvertTextToSpeech(history.substring(a), "test");}

However, this causes a noticeable pause between speaking the chunks, often also inside the word, so this is not a good solution.

Ok, so even if the max limit for google TTS is 3999 characters, for some reason it started to have issues also with ca. 3000 characters. Not sure why it happened, but it just happened without any code change on my side. Seems an issue related to google TTS.

So, as in my case the text blocks are separated by a break line <br> , and I know each block has no more than 1000-2000 chars, I now splitted all my text like this:

String[] parts = history.split("<br>");
for(String part: parts) {ConvertTextToSpeech(part, "test");}

So now this is working for any text with any length. Problem solved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM