无法在 Android 中执行文本到语音转换

Can not perform text to speech conversion in Android

当我设置 tts.speak 时,使用 s 字符串变量它工作得很好。但是,当我使用通过函数调用传入的文本时,它不起作用。两个字符串变量完全相同

private void speek(final String text){
    tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {
            if(status == TextToSpeech.SUCCESS){
                int isTTs = tts.setLanguage(Locale.ENGLISH);
                if(isTTs == TextToSpeech.LANG_MISSING_DATA || isTTs == TextToSpeech.LANG_NOT_SUPPORTED){
                    System.out.println("-----------------------------       ++   not working    " + isTTs);
                    System.out.println("-----------------------------       ++   " + TextToSpeech.LANG_MISSING_DATA + "     " + TextToSpeech.LANG_NOT_SUPPORTED);
                }else{
                    System.out.println("-----------------------------       ++   working yay    " + text);
                    tts.setPitch(0.9f);
                    tts.setSpeechRate(0.8f);
                    // if i use the variable s it works
                    String t = "Chapter 1 ...";
                    tts.speak(t, TextToSpeech.QUEUE_ADD, null);
                    // howevet this does not
                    tts.speak(text, TextToSpeech.QUEUE_ADD, null);
                }
            }
        }
    });

}

TextToSpeech tts;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_read_novel);
    // call async task
    new getPage().execute(b.getString("link"));

}


private class getPage extends AsyncTask<String, String, String> {
    @Override
    protected String doInBackground(String... urls) {}

    @Override
    protected void onPostExecute(String result) {
        // call speak function and pass string to be spoken
        speek(result);
    }
}

没有您的日志或对您函数的调用,我们无法真正找出问题所在。

我的第一个猜测是 text 可能为空(如果您在日志中没有看到 NPE,则为空),它们会在 speak 方法中触发异常或生成空白语音.添加一个空检查,一个空检查并查看调用是否具有您的 speek 函数的正确签名。

在这种情况下,onPostExecute中的参数可能为空。

您可能还想检查 this documentation 看看是否还有其他限制。

首先,您可以尝试在调用 speak() 方法之前打印 text 以检查传递给该方法的值。

我们不知道您的 doInBackground() 方法的内容,但也许您在这里传递了错误的值?在您的 doInBackground() 方法中,您应该 return 将传递给 onPostExecute() 的值。

doInBackground 中的

urls 是 Java 可变参数机制,因此 urls[0] 是传递给 execute().

的第一个参数

当你执行:

new getPage().execute("aaa", "bbb", "ccc");

doInBackground中:

  • urls[0] => "aaa"
  • urls[1] => "bbb"
  • urls[2] => "ccc"

你可以试试return第一个参数(所以urls[0]):

@Override
protected String doInBackground(String... urls) {
    // return value from parmeters
    return urls[0];
}

问题原来是可以传递给文本到语音引擎的最大字符大小约为 4000,如果您的字符串包含超过 4000 个字符,它将不起作用

// this will not work 
tts.speak(text, TextToSpeech.QUEUE_ADD, null);

为了使其正常工作,请添加一个 setOnUtteranceProgressListener 并使用 onDone()

遍历您的字符串
// working code
int char_count = 3000;
int start = 0;
int end = char_count;
HashMap<String, String> map = new HashMap<String, String>();
map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "UniqueID");
tts.speak(text.substring(start, end), TextToSpeech.QUEUE_ADD, map);

tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                        @Override
                        public void onStart(String s) {}

                        @Override
                        public void onDone(String s) {
                            start = end;
                            end+= char_count;
                            end = text.indexOf(" ", end);

                            if(end >= text.length() || end == -1){
                                end = text.length();
                            }if(start >= text.length()){
                                System.out.println("end of text");
                            }else {
                                speek();
                            }

                        }

                        @Override
                        public void onError(String s) {}
                    });