una - Reconocimiento de voz en Android y grabación de audio al mismo tiempo.
escuchar grabación de voz (5)
Mi aplicación graba audio usando la clase MediaRecorder en AsyncTask y también usa la transformación de voz a texto de la API de Google - Intensificador del reconocedor - usando el código de esta pregunta: ¿Cómo puedo usar el reconocimiento de voz sin el molesto diálogo en los teléfonos Android
También he intentado grabar audio en Thread, pero esta es una solución peor. Causa más problemas. Mi problema es que mi aplicación funciona correctamente en el emulador. Pero el emulador no admite el reconocimiento de voz debido a la falta de servicios de reconocimiento de voz. Y en mi dispositivo, mi aplicación se bloquea cuando comienzo a grabar el reconocimiento de audio y voz: "se detuvo inesperadamente". Sin embargo, cuando tengo wifi desactivado, la aplicación funciona correctamente como en el emulador.
La grabación de audio requiere en AndroidManifest:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
y requisitos de reconocimiento de voz:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
Supongo que esto es un problema con la entrada de audio individual ¿Como puedo resolver este problema? Google Speech Recognizer requiere trabajar en el hilo principal de la IU, por lo que no puedo, por ejemplo, hacerlo en Async Task. Así que tengo grabación de audio en Async Task. No tengo idea de por qué esto causa problemas.
He conectado mi dispositivo a Eclipse y he utilizado la depuración USB. Y esta es la exección que tengo en LogCat:
08-23 14:50:03.528: ERROR/ActivityThread(12403): Activity go.android.Activity has leaked ServiceConnection android.speech.SpeechRecognizer$Connection@48181340 that was originally bound here
08-23 14:50:03.528: ERROR/ActivityThread(12403): android.app.ServiceConnectionLeaked: Activity go.android.Activity has leaked ServiceConnection android.speech.SpeechRecognizer$Connection@48181340 that was originally bound here
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:1121)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:1016)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ContextImpl.bindService(ContextImpl.java:951)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.content.ContextWrapper.bindService(ContextWrapper.java:347)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.speech.SpeechRecognizer.startListening(SpeechRecognizer.java:267)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at go.android.Activity.startRecordingAndAnimation(Activity.java:285)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at go.android.Activity.onResume(Activity.java:86)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1151)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.Activity.performResume(Activity.java:3823)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3118)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3143)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2684)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.os.Handler.dispatchMessage(Handler.java:99)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.os.Looper.loop(Looper.java:123)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at android.app.ActivityThread.main(ActivityThread.java:4627)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at java.lang.reflect.Method.invokeNative(Native Method)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at java.lang.reflect.Method.invoke(Method.java:521)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
08-23 14:50:03.528: ERROR/ActivityThread(12403): at dalvik.system.NativeStart.main(Native Method)
Y después de eso otra excepción:
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): Failed to create session
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): com.google.android.voicesearch.speechservice.ConnectionException: POST failed
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.SpeechServiceHttpClient.post(SpeechServiceHttpClient.java:176)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.SpeechServiceHttpClient.post(SpeechServiceHttpClient.java:88)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.ServerConnectorImpl.createTcpSession(ServerConnectorImpl.java:118)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.ServerConnectorImpl.createSession(ServerConnectorImpl.java:98)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.RecognitionController.runRecognitionMainLoop(RecognitionController.java:679)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.RecognitionController.startRecognition(RecognitionController.java:463)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.RecognitionController.access$200(RecognitionController.java:75)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.RecognitionController$1.handleMessage(RecognitionController.java:300)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at android.os.Handler.dispatchMessage(Handler.java:99)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at android.os.Looper.loop(Looper.java:123)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at android.os.HandlerThread.run(HandlerThread.java:60)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): Caused by: java.net.SocketTimeoutException
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:564)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:88)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:191)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:82)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:174)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:179)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:235)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:259)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:279)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:410)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at android.net.http.AndroidHttpClient.execute(AndroidHttpClient.java:243)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): at com.google.android.voicesearch.speechservice.SpeechServiceHttpClient.post(SpeechServiceHttpClient.java:167)
08-23 14:50:08.000: ERROR/ServerConnectorImpl(12412): ... 10 more
08-23 14:50:08.000: ERROR/RecognitionController(12412): Ignoring error 2
Lo he logrado con éxito con la ayuda de CLOUD SPEECH API . Puedes encontrar su demo a través de google speech .
La API reconoce más de 80 idiomas y variantes para admitir su base de usuarios global. Puede transcribir el texto de los usuarios que dictan al micrófono de una aplicación, habilitar el comando y control por voz o transcribir archivos de audio, entre muchos otros casos de uso. Reconozca el audio cargado en la solicitud e intégrelo con su almacenamiento de audio en Google Cloud Storage, utilizando la misma tecnología que usa Google para impulsar sus propios productos.
Utiliza el búfer de audio para transcribir datos con la ayuda de Google Speech API. He utilizado este búfer para almacenar la grabación de audio con la ayuda de AudioRecorder .
Así que con esta demostración podemos transcribir el habla del usuario paralelamente con la grabación de audio.
En este, se inicia y detiene el reconocimiento de voz basado en la voz. También proporciona una facilidad de SPEECH_TIMEOUT_MILLIS en VoiceRecorder.java que es exactamente igual a EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS de RecognizerIntent , pero controlado por el usuario.
En resumen, puede especificar el tiempo de espera de silencio y, según eso, se detendrá después de la salida del usuario y comenzará de nuevo tan pronto como el usuario comience a hablar.
Los proyectos recientes en '' google-speech '' y en '' android-opus '' (opuslib) permiten el reconocimiento simple y simultáneo junto con el registro de audio a un archivo de opus en la extensión de Android. almacenamiento.
Al mirar el VoiceRecorder en el proyecto de voz, con solo unas pocas líneas adicionales de código después de leer el búfer del micrófono, el búfer también puede ser consumido por un fileSink (PCM16 a Opus-codec) además del observador de voz actual.
vea la combinación mínima de los 2 proyectos anteriores en Google-speech-opus-recorder
No he probado esta solución todavía, pero tal vez hay una posibilidad. En developer.android.com/reference/android/speech/… hay un método void bufferReceived(byte[] buffer)
. La posible solución es guardar este búfer AudioRecord
en la clase de AudioRecord
Android. Tiene un método como read(byte[] audioData, int offsetInBytes, int sizeInBytes)
. ¿Entonces tal vez es posible conectar estas dos utilidades de esta manera? Pueden haberse producido problemas con la configuración de AudioRecord
y con la conversión del resultado a formato mp3 o wav después de la grabación.
Respuesta tardía, pero para la primera excepción, tienes que destruir tu SpeechRecognizer después de lo que quieres que haya hecho, por ejemplo (en onStop () u onDestroy () o directamente después de que ya no necesites el SpeechRecognizer):
if (YourSpeechRecognizer != null)
{
YourSpeechRecognizer.stopListening();
YourSpeechRecognizer.cancel();
YourSpeechRecognizer.destroy();
}
Tengo una solución que funciona bien para tener reconocimiento de voz y grabación de audio. Aquí está el link a un proyecto de Android simple que creé para mostrar el funcionamiento de la solución. Además, coloco algunas pantallas de impresión dentro del proyecto para ilustrar la aplicación.
Voy a tratar de explicar brevemente el enfoque que utilicé. Combiné dos características en ese proyecto: Google Speech API y la grabación de Flac.
La API de Google Speech se llama a través de conexiones HTTP. Mike Pultz da más detalles sobre la API:
" (...) la nueva API [Google] es una API de transmisión dúplex completa. Lo que esto significa es que en realidad utiliza dos conexiones HTTP: una solicitud POST para cargar el contenido como una secuencia fragmentada" en vivo "y una "La segunda solicitud GET para acceder a los resultados, lo que tiene mucho más sentido para muestras de audio más largas o para transmitir audio".
Sin embargo, esta API necesita recibir un archivo de sonido FLAC para funcionar correctamente. Eso nos hace pasar a la segunda parte: la grabación de Flac.
Implementé la grabación de Flac en ese proyecto extrayendo y adaptando algunos fragmentos de código y bibliotecas de una aplicación de código abierto llamada AudioBoo. AudioBoo usa código nativo para grabar y reproducir en formato flac.
Por lo tanto, es posible grabar un sonido flac, enviarlo a Google Speech API, obtener el texto y reproducir el sonido que se acaba de grabar.
El proyecto que creé tiene los principios básicos para que funcione y se puede mejorar para situaciones específicas. Para que funcione en un escenario diferente, es necesario obtener una clave de API de Google Speech, que se obtiene al formar parte del grupo Google Chromium-dev. Dejé una clave en ese proyecto solo para mostrar que está funcionando, pero la eliminaré eventualmente. Si alguien necesita más información al respecto, avíseme porque no puedo poner más de 2 enlaces en esta publicación.