Google语音识别超时

我正在开发基于语音识别的Android应用程序。

直到今天,一切工作都很顺利,例如,我会开始说话,然后在1秒或2秒内收到结果。

这是一个非常可以接受的用户体验。

那么今天我必须等待十秒或更长时间才能得到识别结果。

我试图设置下面的EXTRAS,其中没有任何明显的差异

RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS 

我一直在不断地改变我的应用,但是这些改变都没有涉及到语音识别器。

有什么方法可以用来减less语音识别器从onBeginningOfSpeech()切换到onBeginningOfSpeech()之间的时间?

下面是需要多长时间的例子

 07-01 17:50:20.839 24877-24877/com.voice I/Voice: onReadyForSpeech() 07-01 17:50:21.614 24877-24877/com.voice I/Voice: onBeginningOfSpeech() 07-01 17:50:38.163 24877-24877/com.voice I/Voice: onEndOfSpeech() 

编辑显然已经在2016年8月即将发布的固定您可以testingtesting确认。

这是Google“Now”V6.0.23。*发布的一个错误,并保留在最新的V6.1.28中。*

自V5.11.34发布以来* Google的SpeechRecognizer实现一直受到bug的困扰。

你可以使用这个要点复制其中的很多。

您可以使用此BugRecognitionListener来解决其中的一些问题。

我已经直接向Now队报告了这些,所以他们知道,但是到目前为止还没有什么固定的。 Google Now没有外部错误跟踪器,因为它不是AOSP的一部分,所以没有什么可以担任主angular的。

最近发现的细节几乎使得它们的实现不可用,正如您正确指出的那样,控制语音input时序的参数将被忽略。 根据文档 :

另外,根据识别器的实现,这些值可能不起作用。

是我们应该期望的东西……

如果您不说话或发出任何可察觉的声音,则识别将无限期地继续。

我目前正在创build一个项目来复制这个新的错误以及所有其他的错误,我将稍后介绍并链接到这里。

编辑 – 我希望我可以创build一个解决方法,使用部分或不稳定的结果检测作为触发器,知道用户仍在讲话。 一旦停止,我可以在一段时间后手动调用recognizer.stopListening()

不幸的是, stopListening()被打破,实际上并没有停止识别,因此没有解决方法。

试图绕上述,毁坏识别器,只依赖于部分结果直到这一点(当销毁识别器onResults()没有被调用)没有产生一个可靠的实现,除非你只是关键字发现 。

在Google解决这个问题之前,我们无能为力。 您唯一的出路是通过电子邮件apps-help@google.com报告问题,并希望他们收到的数量给他们一个轻推…..

注意! 这只适用于在线模式。 启用听写模式并禁用部分结果:

 intent.putExtra("android.speech.extra.DICTATION_MODE", true); intent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, false); 

在听写模式下,speechRecognizer仍然会调用onPartialResults()但是您应该将部分视为最终结果。

更新:

如果有人在设置语音识别时遇到麻烦,可以使用我为了克服android语音超时问题而build立的Droid Speech库 。


我的应用程序完全依赖于语音识别function,Google已经放弃了一个炸弹。 从目光看,我相信至less在不久的将来这是不可能的。

目前,我确实find了解决scheme,让谷歌的语音识别提供了预期的语音结果。

注意:这种方法与上述解决scheme略有不同。

此方法的主要目的是确保用户发出的所有单词在onPartialResults()中被捕获。

在正常情况下,如果用户在一个给定的实例中说一个以上的单词,那么响应时间太快,部分结果往往比只得到第一个单词而不是全部结果。

为了确保在onPartialResults()中捕获每个单词,引入了一个处理程序来检查用户的暂停延迟,然后过滤结果。 另请注意,onPartialResults()中的结果数组通常不会只有一个项目。

 SpeechRecognizer userSpeech = SpeechRecognizer.createSpeechRecognizer(this); Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); speechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName()); speechIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true); speechIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, ModelData.MAX_VOICE_RESULTS); Handler checkForUserPauseAndSpeak = new Handler(); Boolean speechResultsFound = false; userSpeech.setRecognitionListener(new RecognitionListener(){ @Override public void onRmsChanged(float rmsdB) { // NA } @Override public void onResults(Bundle results) { if(speechResultsFound) return; speechResultsFound = true; // Speech engine full results (Do whatever you would want with the full results) } @Override public void onReadyForSpeech(Bundle params) { // NA } @Override public void onPartialResults(Bundle partialResults) { if(partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).size() > 0 && partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).get(0) != null && !partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).get(0).trim().isEmpty()) { checkForUserPauseAndSpeak.removeCallbacksAndMessages(null); checkForUserPauseAndSpeak.postDelayed(new Runnable() { @Override public void run() { if(speechResultsFound) return; speechResultsFound = true; // Stop the speech operations userSpeech.destroy(); // Speech engine partial results (Do whatever you would want with the partial results) } }, 1000); } } @Override public void onEvent(int eventType, Bundle params) { // NA } @Override public void onError(int error) { // Error related code } @Override public void onEndOfSpeech() { // NA } @Override public void onBufferReceived(byte[] buffer) { // NA } @Override public void onBeginningOfSpeech() { // NA } }); userSpeech.startListening(speechIntent); 

我发现解决scheme的最佳解决scheme(直到谷歌修复该错误)是进入谷歌应用程序的信息,然后点击“卸载更新”button。 这将删除所有更新完成这个应用程序,直接影响到语音识别器,基本上返回到工厂。

**可能是一个好主意,停止自动更新,直到我们知道它的修复。 ***注意:这是一个只针对开发者的解决scheme,显然如果你在商店有一个应用程序,这不会帮助你。 抱歉…

更新:就我今天的testing而言,这个bug似乎已经被最终解决了,这已经不再需要了。 留下来以防将来再次爆发。 从我的testing中,语音暂停正常运行。

好吧,我知道这是非常可惜的,但它似乎工作onPartialResults(我了解onPartialResults的陷阱,但我已经尝试了几次,这是谷歌修复这个荒谬的错误之前的东西!)我没有详尽testing它然而(我会和后期的结果,因为我会在应用程序中使用这个),但我绝望的解决scheme。 基本上,我使用onRmsChanged来触发该用户完成说话,假设当RmsDb低于峰值并且没有onPartialResults 2秒钟,我们就完成了。

我不喜欢这件事的一件事是破坏SR使双噢,噢噢。 FWIW和YMMV。 请发布任何改进!

注意:如果您要反复使用,请不要忘记重置bBegin和fPeak! 此外,您将需要重新创buildSR(onStartCommand或停止并启动服务)。

 import android.app.Service; import android.content.Intent; import android.os.Bundle; import android.os.IBinder; import android.speech.RecognitionListener; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import android.support.annotation.Nullable; import android.util.Log; import java.util.ArrayList; public class SpeechToTextService extends Service { private String TAG = "STT"; float fPeak; boolean bBegin; long lCheckTime; long lTimeout = 2000; @Override public void onCreate() { super.onCreate(); bBegin = false; fPeak = -999; //Only to be sure it's under ambient RmsDb. final SpeechRecognizer sr = SpeechRecognizer.createSpeechRecognizer(getApplicationContext()); sr.setRecognitionListener(new RecognitionListener() { @Override public void onReadyForSpeech(Bundle bundle) { Log.i(TAG, "onReadyForSpeech"); } @Override public void onBeginningOfSpeech() { bBegin = true; Log.i(TAG, "onBeginningOfSpeech"); } @Override public void onRmsChanged(float rmsDb) { if(bBegin) { if (rmsDb > fPeak) { fPeak = rmsDb; lCheckTime = System.currentTimeMillis(); } if (System.currentTimeMillis() > lCheckTime + lTimeout) { Log.i(TAG, "DONE"); sr.destroy(); } } //Log.i(TAG, "rmsDB:"+rmsDb); } @Override public void onBufferReceived(byte[] buffer) { Log.i(TAG, "onBufferReceived"); } @Override public void onEndOfSpeech() { Log.i(TAG, "onEndOfSpeech"); } @Override public void onError(int error) { Log.i(TAG, "onError:" + error); } @Override public void onResults(Bundle results) { ArrayList data = results.getStringArrayList( SpeechRecognizer.RESULTS_RECOGNITION); String sTextFromSpeech; if (data != null) { sTextFromSpeech = data.get(0).toString(); } else { sTextFromSpeech = ""; } Log.i(TAG, "onResults:" + sTextFromSpeech); } @Override public void onPartialResults(Bundle bundle) { lCheckTime = System.currentTimeMillis(); ArrayList data = bundle.getStringArrayList( SpeechRecognizer.RESULTS_RECOGNITION); String sTextFromSpeech; if (data != null) { sTextFromSpeech = data.get(0).toString(); } else { sTextFromSpeech = ""; } Log.i(TAG, "onPartialResults:" + sTextFromSpeech); } @Override public void onEvent(int eventType, Bundle params) { Log.i(TAG, "onEvent:" + eventType); } }); Intent iSRIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); iSRIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); iSRIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true); iSRIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getPackageName()); iSRIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US"); iSRIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en-US"); sr.startListening(iSRIntent); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }