Android TTS text longer than 4k non-reproducing characters

I use TextToSpeech to play some long texts, and I noticed that with Android 4.1.2 , if the text is longer than 4000 characters, it will not play.

I do not get any errors, but the text will not play. So far, I have been able to reproduce this only on Android 4.1.2 (Samsung Galaxy Nexus, Nexus7).

Is this a bug only in 4.1.2 or is it normal (although I have not found any documentation regarding this behavior)?

I also found a message: onUtteranceCompleted () is lost if the TTS is received too long , which indicates various problems with texts longer than 4000 characters.

EDIT: I tried to split my line in chunks of 4k length and send it to TTS using QUEUE_ADD , and I came across another error: QUEUE_ADD does not work, instead it deletes the existing queue and only the last fragment is played back.

EDIT2 : this is my TTS call

 mTTS.speak(longText, TextToSpeech.QUEUE_FLUSH, null); 
+3
source share
3 answers

MAX_SPEECH_ITEM_CHAR_LENGTH = 4000 in TtsService.java, on 4.1 I see a warning in the code:

  @Override public boolean isValid() { if (mText == null) { Log.wtf(TAG, "Got null text"); return false; } if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) { Log.w(TAG, "Text too long: " + mText.length() + " chars"); return false; } return true; } 

looks like 2.3, it breaks the text instead, so theoretically your code should work on android <4.1, and not on newer ones (I donโ€™t know when the split was deleted), instead you have the opposite :), which is a bit strange

+8
source

No problem with 4.4.2 ... I broke my lines like this:

 //textToSpeech can only cope with Strings with < 4000 characters int dividerLimit = 3900; if(textForReading.length() >= dividerLimit) { int textLength = textForReading.length(); ArrayList<String> texts = new ArrayList<String>(); int count = textLength / dividerLimit + ((textLength % dividerLimit == 0) ? 0 : 1); int start = 0; int end = textForReading.indexOf(" ", dividerLimit); for(int i = 1; i<=count; i++) { texts.add(textForReading.substring(start, end)); start = end; if((start + dividerLimit) < textLength) { end = textForReading.indexOf(" ", start + dividerLimit); } else { end = textLength; } } for(int i=0; i<texts.size(); i++) { textToSpeech.speak(texts.get(i), TextToSpeech.QUEUE_ADD, null); } } else { textToSpeech.speak(textForReading, TextToSpeech.QUEUE_FLUSH, null); } 
+3
source

My solution was to use onUtteranceCompleted(String utteranceId) to find out when the first piece will end, and then feed the next snippet to TextToSpeech until they end.

 @Override public void onInit(int status) { //On TTS init //guava Splitter mChunks=Lists.newLinkedList(Splitter.fixedLength(3999).split(mExtractedText)); mTTS.setOnUtteranceCompletedListener(this); playNextChunk(); } private void playNextChunk(){ HashMap<String, String> params = new HashMap<String, String>(); params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, ""+mChunks.size()); mTTS.speak(mChunks.poll(), TextToSpeech.QUEUE_FLUSH, params); } @Override public void onUtteranceCompleted(String utteranceId) { playNextChunk(); } 
+2
source

Source: https://habr.com/ru/post/1215303/


All Articles