Parece que Google ha hecho que el reconocimiento de voz sin conexión esté disponible en Google Now para aplicaciones de terceros. Está siendo utilizado por la aplicación llamada Utter .
¿Alguien ha visto alguna implementación de cómo hacer comandos de voz simples con esta grabación de voz sin conexión? ¿Utiliza la API SpeechRecognizer normal y funciona automáticamente?
Respuestas:
Google habilitó silenciosamente el reconocimiento fuera de línea en esa actualización de búsqueda, pero (hasta ahora) no hay API o parámetros adicionales disponibles dentro de la clase SpeechRecognizer . {Ver Editar en la parte inferior de esta publicación} La funcionalidad está disponible sin codificación adicional, sin embargo, el dispositivo del usuario deberá configurarse correctamente para que comience a funcionar y aquí es donde radica el problema y me imagino por qué muchos desarrolladores suponga que "les falta algo".
Además, Google ha restringido el uso del reconocimiento fuera de línea para ciertos dispositivos Jelly Bean debido a limitaciones de hardware. No se documenta a qué dispositivos se aplica esto, de hecho, no se documenta nada, por lo que configurar las capacidades para el usuario ha demostrado ser una cuestión de prueba y error (para ellos). Funciona para algunos de inmediato - Para aquellos que no lo hace, esta es la 'guía' que les proporciono.
EDITAR: Cambiar temporalmente la configuración regional del dispositivo a inglés del Reino Unido también parece impulsar esto para que funcione para algunos.
Algunos usuarios informaron que todavía tenían que reiniciar varias veces antes de que comenzara a funcionar, pero todos llegan allí eventualmente, a menudo inexplicablemente a cuál fue el disparador, cuya clave está dentro del APK de búsqueda de Google , por lo que no es de dominio público. o parte de AOSP .
Por lo que puedo establecer, Google prueba la disponibilidad de una conexión antes de decidir si usar el reconocimiento en línea o fuera de línea. Si una conexión está disponible inicialmente pero se pierde antes de la respuesta, Google proporcionará un error de conexión, no volverá a estar fuera de línea. Como nota al margen, si se ha realizado una solicitud para la voz sintetizada de red, no se proporciona ningún error si falla: se obtiene silencio.
La actualización de la Búsqueda de Google no habilitó funciones adicionales en Google Now y, de hecho, si intenta usarlo sin conexión a Internet, se producirá un error. Menciono esto mientras me preguntaba si la habilidad se retiraría tan silenciosamente como parecía y, por lo tanto, no debería confiarse en la producción.
Si tiene la intención de comenzar a usar la clase SpeechRecognizer, tenga en cuenta que hay un error bastante importante asociado, que requiere su propia implementación para manejarlo.
No poder solicitar específicamente offline = true , hace que controlar esta función sea imposible sin manipular la conexión de datos. Basura. Recibirá cientos de correos electrónicos de usuarios preguntándole por qué no ha habilitado algo tan simple.EDITAR: Desde el nivel de API 23, se ha agregado un nuevo parámetro EXTRA_PREFER_OFFLINE al que parece adherirse el servicio de reconocimiento de Google.
Espero que lo anterior ayude.
fuente
Me gustaría mejorar la guía que la respuesta https://stackoverflow.com/a/17674655/2987828 envía a sus usuarios, con imágenes. Es la frase "Para aquellos que no lo hacen, esta es la 'guía' que les proporciono". que quiero mejorar.
El usuario debe hacer clic en los cuatro botones resaltados en azul en estas imágenes:
Luego, el usuario puede seleccionar los idiomas que desee. Cuando finalice la descarga, debe desconectarse de la red y luego hacer clic en el botón "micrófono" del teclado.
Me funcionó (Android 4.1.2), luego el reconocimiento de idioma funcionó de inmediato, sin reiniciar. ¡Ahora puedo dictar instrucciones al shell de Terminal Emulator! Y es dos veces más rápido sin conexión que en línea, en un padfone 2 de ASUS.
Estas imágenes tienen licencia cc by-sa 3.0 y se requiere atribución a stackoverflow.com/a/21329845/2987828; por lo tanto, puede agregar estas imágenes en cualquier lugar junto con esta atribución.
(Esta es la política estándar de todas las imágenes y textos en stackoverflow.com)
fuente
CMUSphinx, un conjunto de herramientas de reconocimiento de voz de código abierto, implementa un reconocimiento fuera de línea simple y flexible en Android. Funciona puramente fuera de línea, rápido y configurable. Puede escuchar continuamente palabras clave, por ejemplo.
Puede encontrar el último código y tutorial aquí .
Actualización en 2019 : el tiempo pasa rápido, CMUSphinx ya no es tan preciso. Recomiendo probar el kit de herramientas Kaldi en su lugar. La demostración está aquí .
fuente
En resumen, no tengo la implementación, sino la explicación.
Google no puso el reconocimiento de voz sin conexión a disposición de las aplicaciones de terceros. Solo se puede acceder al reconocimiento sin conexión a través del teclado. Ben Randall (¡el desarrollador de utter!) Explica su solución en un artículo en Android Police:
¡De Utter! Afirma ser la primera aplicación sin IME en utilizar el reconocimiento de voz sin conexión en Jelly Bean
fuente
Implementé con éxito mi Speech-Service con capacidades fuera de línea usando onPartialResults cuando estaba fuera de línea y onResults cuando estaba en línea.
fuente
Estaba lidiando con esto y me di cuenta de que necesita instalar el paquete sin conexión para su idioma. Mi configuración de idioma era "Español (Estados Unidos)", pero no hay un paquete sin conexión para ese idioma, por lo que cuando desactivé toda la conectividad de red recibí una alerta de RecognizerIntent que decía que no se puede comunicar con Google, luego cambio el idioma a "English (US)" (porque ya tengo el paquete sin conexión) y lancé RecognizerIntent, simplemente funcionó.
Teclas: Configuración de idioma == Paquete de reconocimiento de voz sin conexión
fuente
Aparentemente, es posible instalar manualmente el reconocimiento de voz sin conexión descargando los archivos directamente e instalándolos en las ubicaciones correctas manualmente. Supongo que esta es solo una forma de eludir los requisitos de hardware de Google. Sin embargo, personalmente no tuve que reiniciar ni nada, simplemente cambiar a Reino Unido y viceversa lo hice.
fuente
A continuación se da un ejemplo de trabajo,
MyService.class
public class MyService extends Service implements SpeechDelegate, Speech.stopDueToDelay { public static SpeechDelegate delegate; @Override public int onStartCommand(Intent intent, int flags, int startId) { //TODO do something useful try { if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { ((AudioManager) Objects.requireNonNull( getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true); } } catch (Exception e) { e.printStackTrace(); } Speech.init(this); delegate = this; Speech.getInstance().setListener(this); if (Speech.getInstance().isListening()) { Speech.getInstance().stopListening(); } else { System.setProperty("rx.unsafe-disable", "True"); RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> { if (granted) { // Always true pre-M try { Speech.getInstance().stopTextToSpeech(); Speech.getInstance().startListening(null, this); } catch (SpeechRecognitionNotAvailable exc) { //showSpeechNotSupportedDialog(); } catch (GoogleVoiceTypingDisabledException exc) { //showEnableGoogleVoiceTyping(); } } else { Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show(); } }); } return Service.START_STICKY; } @Override public IBinder onBind(Intent intent) { //TODO for communication return IBinder implementation return null; } @Override public void onStartOfSpeech() { } @Override public void onSpeechRmsChanged(float value) { } @Override public void onSpeechPartialResults(List<String> results) { for (String partial : results) { Log.d("Result", partial+""); } } @Override public void onSpeechResult(String result) { Log.d("Result", result+""); if (!TextUtils.isEmpty(result)) { Toast.makeText(this, result, Toast.LENGTH_SHORT).show(); } } @Override public void onSpecifiedCommandPronounced(String event) { try { if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { ((AudioManager) Objects.requireNonNull( getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true); } } catch (Exception e) { e.printStackTrace(); } if (Speech.getInstance().isListening()) { Speech.getInstance().stopListening(); } else { RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> { if (granted) { // Always true pre-M try { Speech.getInstance().stopTextToSpeech(); Speech.getInstance().startListening(null, this); } catch (SpeechRecognitionNotAvailable exc) { //showSpeechNotSupportedDialog(); } catch (GoogleVoiceTypingDisabledException exc) { //showEnableGoogleVoiceTyping(); } } else { Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show(); } }); } } @Override public void onTaskRemoved(Intent rootIntent) { //Restarting the service if it is removed. PendingIntent service = PendingIntent.getService(getApplicationContext(), new Random().nextInt(), new Intent(getApplicationContext(), MyService.class), PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); assert alarmManager != null; alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service); super.onTaskRemoved(rootIntent); } }
Para más detalles,
Espero que esto ayude a alguien en el futuro.
fuente