android - que - detección ok google
Tiempo de espera de reconocimiento de voz de Google (6)
ACTUALIZACIÓN: A partir de mis pruebas de hoy, este error parece haberse resuelto finalmente y esto ya no es necesario. Dejarlo en caso de que se rompa nuevamente en el futuro. Según mis pruebas, el tiempo de espera del discurso funciona normalmente.
Ok, sé que esto es MUY feo, pero parece funcionar usando onPartialResults (¡Entiendo los problemas con onPartialResults pero lo he intentado varias veces y es algo hasta que Google soluciona este error ridículo!) ¡No lo he probado exhaustivamente! todavía (publicaré y volveré a publicar los resultados, ya que usaré esto en una aplicación) pero estaba desesperado por una solución. Básicamente, estoy usando onRmsChanged para activar que el usuario termine de hablar, suponiendo que cuando RmsDb cae por debajo del pico y no onPartialResults durante 2 segundos, terminamos.
Lo único que no me gusta de esto es que destruir SR emite un doble pitido. FWIW y YMMV. ¡Por favor publique cualquier mejora!
NOTA: Si va a usar esto repetidamente, ¡no olvide reiniciar bBegin y fPeak! También deberá recrear SR (ya sea en OnStartCommand o detener 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;
}
}
Estoy desarrollando una aplicación para Android que se basa en el reconocimiento de voz.
Hasta hoy, todo ha estado funcionando bien y de manera oportuna, por ejemplo, comenzaría mi reconocedor de voz, hablaría, y en 1 o 2 segundos como máximo la aplicación recibió los resultados.
Fue una experiencia de usuario MUY aceptable.
Entonces hoy tengo que esperar diez segundos o más antes de que los resultados del reconocimiento estén disponibles.
He intentado configurar los siguientes EXTRAS, ninguno de los cuales hace una diferencia perceptible
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 cambio de reconocimiento de voz de
onBeginningOfSpeech()
a
onResults()
?
He aquí 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()
La mejor solución que encontré (hasta que Google solucionó el error) fue ir 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 realizadas en 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 correcciones. *** Nota: esta es una solución solo para desarrolladores, obviamente si tienes una aplicación en la tienda, esto no te ayudará. Lo siento...
Solución solo fuera de línea:
Me he encontrado con el mismo problema (el sistema Android tardó 25 segundos en producir la transcripción del discurso a través de
onPartialResults()
después de que
onEndOfSpeech()
se activara.
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 utiliza el modo en línea (descargué el paquete de idioma a través de la configuración del teléfono).
¡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 aún
onPartialResults()
sin embargo, debe 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 construí para superar el problema del tiempo de espera en Android.
Mi aplicación dependía completamente de la función de reconocimiento de voz y Google lanzó una bomba. A juzgar por el aspecto de las cosas, creo que esto no se solucionará al menos en un futuro próximo.
Por el momento, encontré una solución para que el reconocimiento de voz de Google entregara los resultados del discurso según lo previsto.
Nota: Este enfoque varía ligeramente de las soluciones mencionadas anteriormente.
El objetivo 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 los resultados parciales con frecuencia obtendrán solo la primera palabra y no el resultado completo.
Entonces, para asegurarse de que cada palabra quede atrapada en onPartialResults (), se introduce un controlador para verificar el retraso de pausa del usuario y luego filtrar los resultados. También tenga en cuenta que la matriz de resultados de onPartialResults () con frecuencia tendrá 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);
EDITAR : aparentemente se ha solucionado en la próxima versión de agosto de 2016. Puede probar la versión beta para confirmar.
Este es un error con el lanzamiento de Google ''Now'' V6.0.23. * Y persiste en la última V6.1.28. *
Desde el lanzamiento de V5.11.34. * La implementación de Google del
SpeechRecognizer
ha estado plagada de errores.
Puede usar esta esencia para replicar muchos de ellos.
Puede usar este BugRecognitionListener para BugRecognitionListener algunos de ellos.
He informado esto directamente al equipo de Now, para que lo sepan, pero hasta ahora no se ha solucionado nada. No hay un rastreador de errores externo para Google Now, ya que no es parte de AOSP, por lo que nada que puedas destacar, me temo.
El error más reciente que detallas prácticamente hace que su implementación sea inutilizable, como señalas correctamente, 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 efecto.
es algo que deberíamos esperar ...
El reconocimiento continuará indefinidamente si no habla o hace ningún sonido detectable.
Actualmente estoy creando un proyecto para replicar este nuevo error y todos los demás, que reenviaré y vincularé aquí en breve.
EDITAR
: esperaba poder crear una solución alternativa 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 Recognizer.stopListening
recognizer.stopListening()
después de un período de tiempo establecido.
Desafortunadamente,
stopListening()
está roto y en realidad no detiene el reconocimiento, por lo tanto, no hay solución para esto.
Los intentos en torno a lo anterior, de destruir el reconocedor y confiar solo en los resultados parciales hasta ese momento (cuando no se llama a destruir el reconocedor en
onResults()
no lograron producir una implementación confiable, a menos que
simplemente se identifiquen las palabras clave
.
No hay nada que podamos hacer hasta que Google arregle esto. Su único medio es enviar un correo electrónico a [email protected] informando el problema y esperar que el volumen que reciben les dé un empujón .....