无法在 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) {}
});
当我设置 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) {}
});