如何在 Android 中从 pocketsphynx 释放麦克风
How to release microphone from pocketsphynx in Android
我在 Android 上使用 pocketsphynx 库来查找关键字,它非常适合它的目的。但是,当我试图释放麦克风以在应用程序的另一个组件中使用它时,我无法这样做。我在 logcat 中收到以下错误:
12-11 10:19:55.827 255-30344/? I/AudioFlinger_Threads: AudioFlinger's thread 0xa6cc0000 ready to run
12-11 10:19:55.849 255-31292/? W/APM::AudioPolicyManager: startInput(17675) preempting low-priority input 17671
12-11 10:19:55.859 255-29587/? W/AudioALSAStreamManager: -routingInputDevice(), input_device == AUDIO_DEVICE_NONE(0x0), return
12-11 10:19:55.924 27054-1900/? W/AudioRecord: dead IAudioRecord, creating a new one from obtainBuffer()
12-11 10:19:55.925 255-30344/? W/AudioALSAStreamManager: -routingInputDevice(), input_device == current_input_device(0x80000004), return
12-11 10:19:55.927 255-30346/? I/AudioFlinger_Threads: AudioFlinger's thread 0xaa880000 ready to run
12-11 10:19:55.930 255-31292/? W/APM::AudioPolicyManager: stopInput() unknown input 17671
12-11 10:19:55.930 255-31292/? W/APM::AudioPolicyManager: releaseInput() releasing unknown input 17671
12-11 10:19:55.931 255-953/? W/APM::AudioPolicyManager: startInput(AUDIO_SOURCE_HOTWORD) invalid, already started high-priority input 17675
12-11 10:19:55.931 27054-1900/? W/AudioRecord: restoreRecord_l() failed status -38
12-11 10:19:55.934 27054-1900/? E/AudioRecord-JNI: Error -38 during AudioRecord native read
12-11 10:19:55.951 27054-1900/? E/AudioProvider: audioRecord read failed
com.google.android.apps.gsa.shared.exception.GsaIOException: Error code: 393221 | not open
at com.google.android.libraries.assistant.hotword.a.a(SourceFile:67)
at com.google.android.libraries.assistant.hotword.b.run(SourceFile:30)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
当我尝试使用 WebView
中的 getUserMedia
时会发生这种情况。在这样做之前,我打电话给
recognizer.cancel();
来自我的 Activity,但这似乎没有帮助。
我也试过用.stop()
、.removeListener(...)
、APIs,问题依旧。请建议是否有办法释放 pocketsphinx 正在制作的麦克风,以便应用程序的其他组件可以再次使用麦克风。
感谢任何帮助。
更新 1: 添加了更多日志并查看了 AudioPolicyManager 的 Android 代码。似乎有两个进程(31292
和 953
)试图通过调用 startInput
进行竞争,一个进程(31292
)关闭了另一个进程(953
) .显然,我可能误解了日志。
更新 2: 我查看了 pocketsphynx SpeechRecognizer.shutdown
方法,发现这是 方法,它实际上释放了 AudioRecord
对象。通过试验结束错误,我设法弄清楚如何调用 shutdown
而不会使应用程序崩溃(它必须在 onResult 中发生,在所有侦听器被删除之后)。之后,我的另一个组件开始工作。我还没有机会确认我是否可以在 shutdown
之后重新开始关键字识别。如果在那之后需要重新初始化(这需要很多时间),那将不是一个可接受的解决方法。
更新 3: 我确认 shutdown
不是释放麦克风的必要条件。在调用 stop
API 之后,我设法制作了我的其他组件。关键似乎是停止 pocketsphinx 需要一些时间,而其他组件应该等待它。我使用的对我有用的事件是 onResult
。那时另一个组件已经能够获取新的 AudioRecord
。在那之后我仍然没有尝试重新启动 pocketsphinx。
好的,我让它工作了。调用 SpeechRecognizer.shutdown
确实是不必要的。我能够使用 SpeechRecognizer.stop
API,同时确保等待最后一个结果进入我的 RecognitionListener
实现的 onResult
回调。之后我可以调用 getUserMedia
浏览器 API 并且它成功获得了麦克风。
onResult
我的 RecognitionListener
实现中的代码:
recognizer.removeListener(listener);
我也确认了重新启动识别很容易,我只需要执行以下操作:
recognizer.addListener(listener);
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
recognizer.startListening(KWS_SEARCH);
注意:我在一个单独的线程中停止识别器,类似于实例化识别器的方式,但我还没有确认是否有必要。
我在 Android 上使用 pocketsphynx 库来查找关键字,它非常适合它的目的。但是,当我试图释放麦克风以在应用程序的另一个组件中使用它时,我无法这样做。我在 logcat 中收到以下错误:
12-11 10:19:55.827 255-30344/? I/AudioFlinger_Threads: AudioFlinger's thread 0xa6cc0000 ready to run
12-11 10:19:55.849 255-31292/? W/APM::AudioPolicyManager: startInput(17675) preempting low-priority input 17671
12-11 10:19:55.859 255-29587/? W/AudioALSAStreamManager: -routingInputDevice(), input_device == AUDIO_DEVICE_NONE(0x0), return
12-11 10:19:55.924 27054-1900/? W/AudioRecord: dead IAudioRecord, creating a new one from obtainBuffer()
12-11 10:19:55.925 255-30344/? W/AudioALSAStreamManager: -routingInputDevice(), input_device == current_input_device(0x80000004), return
12-11 10:19:55.927 255-30346/? I/AudioFlinger_Threads: AudioFlinger's thread 0xaa880000 ready to run
12-11 10:19:55.930 255-31292/? W/APM::AudioPolicyManager: stopInput() unknown input 17671
12-11 10:19:55.930 255-31292/? W/APM::AudioPolicyManager: releaseInput() releasing unknown input 17671
12-11 10:19:55.931 255-953/? W/APM::AudioPolicyManager: startInput(AUDIO_SOURCE_HOTWORD) invalid, already started high-priority input 17675
12-11 10:19:55.931 27054-1900/? W/AudioRecord: restoreRecord_l() failed status -38
12-11 10:19:55.934 27054-1900/? E/AudioRecord-JNI: Error -38 during AudioRecord native read
12-11 10:19:55.951 27054-1900/? E/AudioProvider: audioRecord read failed
com.google.android.apps.gsa.shared.exception.GsaIOException: Error code: 393221 | not open
at com.google.android.libraries.assistant.hotword.a.a(SourceFile:67)
at com.google.android.libraries.assistant.hotword.b.run(SourceFile:30)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
当我尝试使用 WebView
中的 getUserMedia
时会发生这种情况。在这样做之前,我打电话给
recognizer.cancel();
来自我的 Activity,但这似乎没有帮助。
我也试过用.stop()
、.removeListener(...)
、APIs,问题依旧。请建议是否有办法释放 pocketsphinx 正在制作的麦克风,以便应用程序的其他组件可以再次使用麦克风。
感谢任何帮助。
更新 1: 添加了更多日志并查看了 AudioPolicyManager 的 Android 代码。似乎有两个进程(31292
和 953
)试图通过调用 startInput
进行竞争,一个进程(31292
)关闭了另一个进程(953
) .显然,我可能误解了日志。
更新 2: 我查看了 pocketsphynx SpeechRecognizer.shutdown
方法,发现这是 方法,它实际上释放了 AudioRecord
对象。通过试验结束错误,我设法弄清楚如何调用 shutdown
而不会使应用程序崩溃(它必须在 onResult 中发生,在所有侦听器被删除之后)。之后,我的另一个组件开始工作。我还没有机会确认我是否可以在 shutdown
之后重新开始关键字识别。如果在那之后需要重新初始化(这需要很多时间),那将不是一个可接受的解决方法。
更新 3: 我确认 shutdown
不是释放麦克风的必要条件。在调用 stop
API 之后,我设法制作了我的其他组件。关键似乎是停止 pocketsphinx 需要一些时间,而其他组件应该等待它。我使用的对我有用的事件是 onResult
。那时另一个组件已经能够获取新的 AudioRecord
。在那之后我仍然没有尝试重新启动 pocketsphinx。
好的,我让它工作了。调用 SpeechRecognizer.shutdown
确实是不必要的。我能够使用 SpeechRecognizer.stop
API,同时确保等待最后一个结果进入我的 RecognitionListener
实现的 onResult
回调。之后我可以调用 getUserMedia
浏览器 API 并且它成功获得了麦克风。
onResult
我的 RecognitionListener
实现中的代码:
recognizer.removeListener(listener);
我也确认了重新启动识别很容易,我只需要执行以下操作:
recognizer.addListener(listener);
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
recognizer.startListening(KWS_SEARCH);
注意:我在一个单独的线程中停止识别器,类似于实例化识别器的方式,但我还没有确认是否有必要。