Tiempo de espera de reconocimiento de voz de Google

Estoy desarrollando una aplicación de Android que se basa en el reconocimiento de voz.

Hasta hoy todo ha funcionado bien y de manera oportuna, por ejemplo, comenzaría mi reconocimiento de voz, hablaría, y dentro de 1 o 2 segundos como máximo la aplicación recibió los resultados.

Fue una experiencia de usuario MUY aceptable.

Entonces hoy, ahora tengo que esperar diez o más segundos antes de que los resultados de reconocimiento estén disponibles.

He intentado configurar los siguientes EXTRAS, ninguno de los cuales hace una diferencia discernible

RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS 

He estado cambiando continuamente mi aplicación, sin embargo, ninguno de estos cambios estaba relacionado con el reconocedor de voz.

¿Hay algún método que pueda emplear para reducir el tiempo entre el reconocimiento de voz cambiar de onBeginningOfSpeech() a onResults() ?

Aquí hay un ejemplo de cuánto tiempo lleva

 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() 

EDITAR : al parecer se ha solucionado en la próxima versión de agosto de 2016. Puede probar la versión beta para confirmarla.

Este es un error con el lanzamiento de Google ‘Now’ V6.0.23. * Y persiste en el último V6.1.28. *

Desde el lanzamiento de V5.11.34. * La implementación de Google del SpeechRecognizer ha estado plagada de errores.

Puedes usar esta esencia para replicar muchos de ellos.

Puede usar este BugRecognitionListener para solucionar algunos de ellos.

He informado esto directamente al equipo de Now, por lo que están al tanto, pero hasta el momento, nada se ha solucionado. No hay un rastreador externo de errores para Google Now, ya que no forma parte de AOSP, por lo que no me temo que nada que pueda destacar.

El error más reciente que detalle prácticamente inutiliza su implementación, ya que correctamente señala que los parámetros para controlar los tiempos de entrada de voz se ignoran. Que según la documentación :

Además, dependiendo de la implementación del reconocedor, estos valores pueden no tener ningún efecto.

es algo que deberíamos esperar ……

El reconocimiento continuará indefinidamente si no hablas ni haces ningún sonido detectable.

Actualmente estoy creando un proyecto para replicar este nuevo error y todos los demás, que voy a reenviar y vincular aquí en breve.

EDITAR : esperaba poder crear una solución que utilizara la detección de resultados parciales o inestables como desencadenante para saber que el usuario todavía estaba hablando. Una vez que se detuvieron, pude llamar manualmente a recognizer.stopListening() después de un período de tiempo establecido.

Desafortunadamente, stopListening() se rompe y no detiene el reconocimiento, por lo tanto, no hay ninguna solución a esto.

Los bashs en torno a lo anterior, de destruir el reconocedor y confiar solo en los resultados parciales hasta ese punto (cuando se destruye el reconocedor onResults() no se llama) no lograron producir una implementación confiable, a menos que sea simplemente detección de palabras clave .

No hay nada que podamos hacer hasta que Google solucione esto. Su único recurso es enviar un correo electrónico a apps-help@google.com informando el problema y esperar que el volumen que reciben les dé un empujón …

¡NOTA! esto funciona solo en modo en línea. Habilite el modo de dictado y deshabilite los resultados parciales:

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

En el modo de dictado, speechRecognizer seguiría llamando onPartialResults() sin embargo, debería tratar los parciales como resultados finales.

ACTUALIZAR:

En caso de que alguien tenga problemas para configurar el reconocimiento de voz, puede usar la biblioteca Droid Speech que he creado para solucionar el problema del tiempo de espera del habla en Android.


Mi aplicación depende completamente de la función de reconocimiento de voz y Google ha lanzado una bomba. A juzgar por las cosas, creo que esto no se solucionará al menos en el futuro cercano.

Por el momento, encontré una solución para que el reconocimiento de voz de Google entregue los resultados del discurso como estaba previsto.

Nota: Este enfoque varía ligeramente de las soluciones mencionadas anteriormente.

El objective principal de este método es asegurarse de que todas las palabras pronunciadas por el usuario se capturen en onPartialResults ().

En casos normales, si un usuario habla más de una palabra en una instancia determinada, el tiempo de respuesta es demasiado rápido y, en general, los resultados parciales obtendrán solo la primera palabra y no el resultado completo.

Por lo tanto, para asegurarse de que cada palabra sea capturada en onPartialResults (), se introduce un controlador para verificar la demora de pausa del usuario y luego filtrar los resultados. También tenga en cuenta que la matriz de resultados de onPartialResults () tendrá más de un solo elemento.

 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); 

La mejor solución alternativa que encontré (hasta que Google corrigió el error) fue ingresar a la información de la aplicación Google App y luego hacer clic en el botón “Desinstalar actualizaciones” . Esto eliminará todas las actualizaciones hechas a esta aplicación que tiene un efecto directo en el reconocedor de voz, básicamente devolviéndola a fábrica.

** Probablemente sea una buena idea detener las actualizaciones automáticas hasta que sepamos que son soluciones. *** Nota: esta es una solución solo para desarrolladores, obviamente si tienes una aplicación en la tienda esto no te ayudará. Lo siento…

ACTUALIZACIÓN: A partir de mi prueba de hoy, este error parece haberse resuelto finalmente y esto ya no es necesario. Dejándolo en caso de que se rompa nuevamente en el futuro. Según mis pruebas, el tiempo de espera de voz funciona normalmente.

Ok, sé que esto es MUY feo, pero parece funcionar usando onPartialResults (entiendo los errores con onPartialResults pero lo he intentado varias veces y ¡es algo hasta que Google solucione este ridículo error!) No lo he probado exhaustivamente aún (publicaré y publicaré los resultados ya que usaré esto en una aplicación) pero estaba desesperado por una solución. Básicamente, estoy usando onRmsChanged para desencadenar que el usuario termine de hablar, suponiendo que cuando RmsDb caiga por debajo del máximo y no en PartResults durante 2 segundos, hayamos terminado.

Lo único que no me gusta de esto es destruir SR hace un doble uh-oh beep. FWIW y YMMV. Por favor, publique cualquier mejora!

NOTA: Si va a utilizar esto repetidamente, no olvide restablecer bBegin y fPeak! También deberá volver a crear SR (ya sea en Start Command o parar e iniciar el servicio).

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

Solución solo para fuera de línea:

Me he encontrado con el mismo problema (el sistema Android tardó 25 segundos en producir la transcripción del discurso mediante onPartialResults() después de que se onEndOfSpeech() .

He intentado el siguiente código y funcionó:

 Intent.putExtra ( RecognizerIntent.EXTRA_PREFER_OFFLINE, true ); 

Esta solución funciona para mi aplicación y puede funcionar para usted si no usa el modo en línea (descargué el paquete de idioma a través de la configuración del teléfono).