3

TextToSpeech有时会播放一些长文本,我注意到Android 4.1.2如果文本超过 4000 个字符,它就不会播放。

我没有收到任何错误,但不会播放文本。到目前为止,我能够在Android 4.1.2(Samsung Galaxy Nexus,Nexus7)上重现这一点。

这是一个错误4.1.2还是正常的(尽管我没有找到有关此行为的任何文档)?

我还发现了一个帖子:如果收到的 TTS 太长,则 onUtteranceCompleted() 丢失,这表明超过 4000 个字符的文本存在不同的问题。

编辑:我试图将我的字符串拆分为 4k 长度的块,并将其发送给TTSusing QUEUE_ADD,但我遇到了另一个错误QUEUE_ADD不起作用,而是刷新现有队列,并且只播放最后一个块。

EDIT2:这是我的电话TTS

mTTS.speak(longText, TextToSpeech.QUEUE_FLUSH, null);
4

3 回答 3

8

TtsService.java 中的 MAX_SPEECH_ITEM_CHAR_LENGTH = 4000,在 4.1 上我在代码中看到警告:

    @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;
    }

看起来像 2.3 拆分了文本,所以理论上你的代码应该在 android < 4.1 上运行而不是更新(我不知道拆分何时被删除),相反你有相反的 :) 这有点奇怪

于 2012-11-20T22:53:00.213 回答
3

我的解决方案是用来onUtteranceCompleted(String utteranceId)知道第一个块何时完成,然后将下一个块提供给它们,TextToSpeech直到它们全部完成。

@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();
}
于 2012-11-21T13:30:59.017 回答
3

在 4.4.2 上没问题...我这样拆分字符串...

//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);
}
于 2015-02-11T11:18:34.400 回答