我正在构建 android 应用程序,它必须一直(不断地)听一个声音并抓住一个关键词,例如帮助。我现在正在使用 MediaRecorder 来获得幅度,然后如果声音很大(例如 20000),我将调用 pocketsphinx 语音识别器。问题是,当语音识别器捕获(或没有)我无法跳回 MediaRecorder 的关键字时,应用程序崩溃了。当然,我的应用程序必须在后台(每天 24 小时)运行,所以我的实现在服务中,所以我的 MediaRecorder 在单独的线程中。我知道 Pocketsphinx 也可以检查振幅(尖叫声),但如何做到呢?Pocketsphinx(获取振幅)是触发语音识别器的更好解决方案吗?在我的课下,我将非常感谢任何帮助。
@Override
public IBinder onBind(Intent intent) {
return null;
}
private final class ServiceHandler extends Handler{
public ServiceHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg){
outputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/record.3gp";
getVoiceRecord();
}
}
@Override
public void onCreate() {
thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
//change to START_STICKY
Log.d("tag", "on start command");
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
serviceHandler.sendMessage(msg);
return Service.START_NOT_STICKY;
}
private void getVoiceRecord() {
startRecorder();
start = System.currentTimeMillis();
Log.d("tag", "Time started at " + start);
while (true){
if(recorder!=null){
amplitude = recorder.getMaxAmplitude();
if(amplitude>20000){
Toast.makeText(getApplicationContext(), "Scream detected",
Toast.LENGTH_LONG).show();
Log.d("tag", "Scream detected " + 20 * Math.log10(amplitude) + " amplitude: " + amplitude);
stopRecorder();
Log.d("tag", "Finish recording");
getSpeech();
}
finish = System.currentTimeMillis();
if(finish-start>50000){
//loop = false;
stopRecorder();
Log.d("tag", "Finish recording");
if(recorder==null){
recorder.reset();
startRecorder();
start = System.currentTimeMillis();
}
}
}
}//end of while loop
}
private void getSpeech() {
try {
Assets assets = new Assets(ScreamService.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
//return e;
}
reset();
}
private void stopRecorder() {
try{
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
Log.d("tag", "Stop recording");
}catch (IllegalStateException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not stop " + e);
try {
Thread.sleep(2000);
recorder.stop();
recorder.release();
recorder = null;
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}catch (RuntimeException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not stop " + e);
}
}
private void startRecorder() {
Log.d("tag", "Start recording... ");
try {
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(outputFile);
recorder.prepare();
recorder.start();
} catch (IOException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not start IOExeption " + e);
} catch (IllegalStateException e) {
e.printStackTrace();
Log.d("tag", "Media Recorder did not start Ilegal State Trace" + e);
}
}
@Override
public void onDestroy() {
super.onDestroy();
recognizer.cancel();
recognizer.shutdown();
Toast.makeText(this, "Scream Service & recognizer Stopped.", Toast.LENGTH_SHORT).show();
}
@Override
public void onPartialResult(Hypothesis hypothesis) {
}
/**
* This callback is called when we stop the recognizer.
*/
@Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
//makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
Log.d("tag", "onResult " + text);
if(text.equals("help") || text.equals("help me")) {
recognizer.stop();
recognizer.cancel();
this.startService(new Intent(this, SendMessage.class));
getVoiceRecord();
}
}else {
Log.d("tag", "onResult is null");
}
}
@Override
public void onBeginningOfSpeech() {
//Log.d("tag", "onBeginningOfSpeech ");
}
@Override
public void onEndOfSpeech() {
counter++;
if(counter>5){
//recognizer.stop();
recognizer.cancel();
counter=0;
getVoiceRecord();
Log.d("tag", "Speech recognizer is killed");
}else {
//Log.d("tag", "onEndOfSpeech ");
reset();
}
}
private void reset() {
recognizer.stop();
recognizer.startListening("menu");
}
private void setupRecognizer(File assetsDir) throws IOException {
Log.d("tag", "default setup");
recognizer = defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
// To disable logging of raw audio comment out this call (takes a lot of space on the device)
.setRawLogDir(assetsDir)
// Threshold to tune for keyphrase to balance between false alarms and misses
.setKeywordThreshold(1e-45f)
// Use context-independent phonetic search, context-dependent is too slow for mobile
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(this);
// Create grammar-based search for selection between demos
File menuGrammar = new File(assetsDir, "menu.gram");
recognizer.addGrammarSearch("menu", menuGrammar);
}
@Override
public void onError(Exception error) {
Log.d("tag", "error "+error.getMessage());
}
@Override
public void onTimeout() {
Log.d("tag", "onTimeout");
}