web-dev-qa-db-ja.com

Android音声認識と音声録音を同時に行う

私のアプリケーションは、AsyncTaskのMediaRecorderクラスを使用して音声を録音し、Google APIを使用して音声をテキストに変換します-RecognizerIntent-この質問のコードを使用します: Android電話

スレッドでオーディオを録音しようとしましたが、これはもっと悪い解決策です。それはより多くの問題を引き起こします。私の問題は、私のアプリケーションがエミュレーターで正しく動作することです。ただし、音声認識サービスがないため、エミュレータは音声再認識をサポートしていません。また、デバイスで音声と音声の認識を記録し始めると、アプリケーションがクラッシュします。「予期せず停止しました」。ただし、wifiをオフにすると、アプリケーションはエミュレーターのように正しく動作します。

AndroidManifestでオーディオを録音するには:

<uses-permission Android:name="Android.permission.RECORD_AUDIO" />

および音声認識の要件:

<uses-permission Android:name="Android.permission.RECORD_AUDIO" />
<uses-permission Android:name="Android.permission.INTERNET" />

これは単一のオーディオ入力の問題だと思いますか?この問題を解決するにはどうすればよいですか? Google Speech RecognizerはメインUIスレッドで動作する必要があるため、たとえば非同期タスクでは動作できません。だから私は非同期タスクで録音しています。これがなぜ問題を引き起こすのか私にはわかりません。

デバイスをEclipseに接続し、USBデバッグを使用しました。そして、これは私が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)

そしてその後、別の例外:

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
24
woyaru

私は、音声認識と音声録音を行うためにうまく機能しているソリューションを手に入れました。これが リンク ソリューションの動作を示すために作成した単純なAndroidプロジェクトです。また、アプリを説明するためにプロジェクト内にいくつかの印刷画面を配置しました。

私が使用したアプローチについて簡単に説明しようと思います。そのプロジェクトでは、Google SpeechAPIとFlacレコーディングの2つの機能を組み合わせました。

Google Speech APIは、HTTP接続を介して呼び出されます。 Mike Pultz APIの詳細を示します:

"(...)新しい[Google] APIは全二重ストリーミングAPIです。これは、実際には2つのHTTP接続を使用することを意味します-1つはPOSTコンテンツを「ライブ」チャンクストリームとしてアップロードするリクエストと、結果にアクセスするための2番目のGETリクエスト。これは、長いオーディオサンプルやストリーミングオーディオの場合にはるかに意味があります。 "

ただし、このAPIが正しく機能するには、FLACサウンドファイルを受信する必要があります。それで2番目の部分に進みます:Flacレコーディング

私は、AudioBooと呼ばれるオープンソースアプリからコードとライブラリの一部を抽出して適応させることにより、そのプロジェクトにFlacレコーディングを実装しました。 AudioBooは、ネイティブコードを使用してflac形式を記録および再生します。

したがって、flacサウンドを録音し、それをGoogle Speech APIに送信し、テキストを取得して、録音したばかりのサウンドを再生することができます。

私が作成したプロジェクトには、それを機能させるための基本原則があり、特定の状況に合わせて改善することができます。別のシナリオで機能させるには、GoogleChromium-devグループに参加して取得したGoogleSpeechAPIキーを取得する必要があります。動作していることを示すために、そのプロジェクトに1つのキーを残しましたが、最終的には削除します。誰かがそれについてもっと情報を必要とするならば、私がこの投稿に2つ以上のリンクを置くことができない原因を私に知らせてください。

6
lsantsan

遅い回答ですが、最初の例外では、この後、たとえば(onStop()またはonDestroy()で、またはSpeechRecognizerが不要になった直後に)SpeechRecognizerを破棄する必要があります。

    if (YourSpeechRecognizer != null)
    {
        YourSpeechRecognizer.stopListening();
        YourSpeechRecognizer.cancel();
        YourSpeechRecognizer.destroy();
    }
3
Opiatefuchs

' google-speech 'および ' Android-opus '(opuslib)の最近のプロジェクトでは、Android内線ストレージ。

音声プロジェクトの VoiceRecorder を見ると、マイクバッファーを読み取った後、数行のコードが追加されているだけで、バッファーはfileSink(PCM16からOpus-codec)によっても消費されます。現在のスピーチオブザーバー。

上記の2つのプロジェクトの最小限のマージを Google-speech-opus-recorder で参照してください

2
Robert Rowntree

CLOUD SPEECH API の助けを借りてこれを成功裏に達成しました。あなたはそれのデモを グーグルスピーチ で見つけることができます。

APIは、グローバルユーザーベースをサポートするために、80を超える言語とバリアントを認識します。他の多くの使用例の中でも、アプリケーションのマイクに口述するユーザーのテキストを書き起こしたり、音声によるコマンドアンドコントロールを有効にしたり、音声ファイルを書き起こしたりすることができます。リクエストでアップロードされたオーディオを認識し、Googleが自社製品を強化するために使用するのと同じテクノロジーを使用して、Google CloudStorageのオーディオストレージと統合します。

オーディオバッファを使用して、Google SpeechAPIを使用してデータを書き起こします。 AudioRecorder を使用して、このバッファを使用してオーディオ録音を保存しました。

したがって、このデモでは、オーディオ録音と並行してユーザーのスピーチを書き写すことができます。

これでは、音声に基づく音声認識を開始および停止します。また、 VoiceRecorder.Java のSPEECH_TIMEOUT_MILLISの機能も提供します。これは、 RecognizerIntentEXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS と同じですが、ユーザーが制御します。

したがって、全体として、無音タイムアウトを指定できます。これに基づいて、ユーザー出力後に停止し、ユーザーが話し始めるとすぐに再開します。

1
Name is Nilay

私はまだこのソリューションをテストしていませんが、おそらく可能性があります。 http://developer.Android.com/reference/Android/speech/RecognitionService.Callback.html にメソッドvoid bufferReceived(byte[] buffer)があります。考えられる解決策は、この受信したバッファをAudioRecord Androidクラスに保存することです。read(byte[] audioData, int offsetInBytes, int sizeInBytes)のようなメソッドがあります。したがって、この2つのユーティリティを接続できる可能性がありますこの方法で?AudioRecordの設定、および記録後に結果をmp3またはwav形式に変換する際に問題が発生した可能性があります。

0
woyaru