之前说Baymax 的UI设计,现在UI设计好了,我们得开始讲一讲识别方面的事了。这里我们需要用到百度的语音识别技术,大家可以先上百度语音开放平台,上面有开发手册和demo帮助大家学习。贴上连接:http://yuyin.baidu.com/
前面注册百度开发者的那些步骤我就跳过了,基本上开发手册写的很详细了。这里我就不再多说。
首先是注册可能需要用到的权限
然后是填上自己在百度申请到的秘钥
导入所需资源包之后(在百度语音开发平台官网可以下载),就要开始调用了
首先是创建识别器及识别器监听事件
//创建识别器
speechRecognizer=SpeechRecognizer.createSpeechRecognizer(this,new ComponentName(this,VoiceRecognitionService.class));
//识别器监听事件
speechRecognizer.setRecognitionListener(this);
监听器需要重写的方法有如下这些,我加以详细说明,开发者根据开发需要重写内容即可
@Override
public void onReadyForSpeech(Bundle params) {
//准备监听时事件
}
@Override
public void onBeginningOfSpeech() {
//开始监听事件
}
@Override
public void onRmsChanged(float rmsdB) {
//声音级别更改时调用的方法
}
@Override
public void onBufferReceived(byte[] buffer) {
//反馈给用户捕获的音频
}
@Override
public void onEndOfSpeech() {
//结束说话时调用此方法
}
@Override
public void onError(int error) {
//错误时事件
}
@Override
public void onResults(Bundle results) {
//识别结果事件,识别结果为results,需要进行解析
}
@Override
public void onPartialResults(Bundle partialResults) {
//这个不太懂
}
@Override
public void onEvent(int eventType, Bundle params) {
//
}
以上是我个人的理解,不是很正确,建议大家看一下开发文档,里面有详细的解释,我这里只是做点简单的介绍。里面最重要的方法就是onResults(Bundle results)识别结果就是在这里面处理的,有了识别结果,我们就可以做出各种“动作”了,像什么开灯关灯,打开相机,拍照什么的都可以。只要你愿意,想让手机关机我想也是可以的。
关于识别监听器就讲完了,没什么好说的,接下来讲识别的参数问题。
百度语音识别SDK需要设置的参数不少,当然也可以全都默认,个人觉得挺好的,可以适应不同环境做识别,提高准确率。这里也是大概讲一下哪些参数可能要用到
①提示音(默认是静音)
intent.putExtra(Constant.EXTRA_SOUND_START, R.raw.bdspeech_recognition_start);
intent.putExtra(Constant.EXTRA_SOUND_END, R.raw.bdspeech_speech_end);
intent.putExtra(Constant.EXTRA_SOUND_SUCCESS, R.raw.bdspeech_recognition_success);
intent.putExtra(Constant.EXTRA_SOUND_ERROR, R.raw.bdspeech_recognition_error);
intent.putExtra(Constant.EXTRA_SOUND_CANCEL, R.raw.bdspeech_recognition_cancel);
②是否保存录音(默认无)
intent.putExtra(Constant.EXTRA_OUTFILE, "sdcard/outfile.pcm");
③设置采样率(8000为2g/3g网络适用,16000为3g/4g网络)
intent.putExtra(Constant.EXTRA_SAMPLE, 8000/16000);
④设置识别语言(可识别普通话/粤语/四川话/英语)
intent.putExtra(Constant.EXTRA_LANGUAGE, xxx);
⑤是否进行语义解析(默认否)
intent.putExtra(Constant.EXTRA_NLU, );
⑥VAD,选择输入关键字或输入长句(默认关键字)
intent.putExtra(Constant.EXTRA_VAD, );
其中有一个很重要的参数叫做“垂直领域”,当时我看了很久都没搞懂是什么,经过后来的实践,我觉得可能是优先识别领域吧。里面可以设置应用、联系人、音乐、输入、视频、地图、网页、电话、联系人……等等等等(好吧我到现在还是不太明白垂直领域的作用,还望哪位大神可以告知一下)。垂直领域的设置可以提高语言识别的准确率,设置的越详细越多就越准确。除此之外,垂直领域里面某些项是支持离线识别的。但据说离线识别不太妥(百度方面说是SDK包的一个BUG,说近期会出一个新的包出来,但是从去年9月份到现在一直有人反映这个问题,百度给出的回答还是这样,估计是bug没解决还是怎样。)总之大家想用离线识别的话就可以看看百度提供的demo,里面就可以。不过有些网友反映还是不可以23333333
还是那句话,大家要是怕麻烦,只是想试试百度语音识别的效果,那就不用去该参数,默认的就可以了。
设置了参数,可以有两种方式进行识别,一种是有API,一种是无API的,具体是什么区别呢?我说你就明白了,无API会调出“百度定制”的dialog(别想了,你改不了),有API就没有那个dialog了,而且识别是一个字一个字识别,当你结束说话时识别结束。论识别准确率嘛,个人觉得是无api比较准确,要好看一点嘛,不想看到百度dialog的话,那就是有api比较妥了。但是无所谓了,能识别出来就是好的。
两种识别调用方式分别如下:
有api:
speechRecognizer.startListening(intent);
无api:
intent.setAction("com.baidu.action.RECOGNIZE_SPEECH");
startActivityForResult(intent, REQUEST_UI);
有api识别结果的处理就是上面说到的onResult,具体要进行什么操作就看个位看官的了,然后无API的话要重写一下onActivityResult方法然后在里面调用onResult。这就是全部的识别流程了,贴出效果图
package chmel.android.baymax;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.speech.RecognitionListener;
import android.speech.SpeechRecognizer;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.widget.Toast;
import com.baidu.speech.VoiceRecognitionService;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by xuan on 2016/3/10 0010.
*/
public class Mainactivity extends Activity implements RecognitionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
context=this;
textResult=(TextView)findViewById(R.id.textResult );
textLog=(TextView)findViewById(R.id.textLog);
button=(ImageButton)findViewById(R.id.btn);
//创建识别器
speechRecognizer=SpeechRecognizer.createSpeechRecognizer(this,new ComponentName(this,VoiceRecognitionService.class));
//识别器监听事件
speechRecognizer.setRecognitionListener(this);
//点击“开始”按钮事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
start();
}
});
}
//start()调用百度语音识别技术进行语音识别
private void start() {
Intent intent = new Intent();
init(intent);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
{
String args = sp.getString("args", "");
if (null != args) {
intent.putExtra("args", args);
}
}
boolean api = sp.getBoolean("api", false);
if (api) {
speechEndTime = -1;
speechRecognizer.startListening(intent);
} else {
intent.setAction("com.baidu.action.RECOGNIZE_SPEECH");
startActivityForResult(intent, REQUEST_UI);
}
textResult.setText("");
textLog.setText("");
}
public void init(Intent intent){
intent.putExtra(Constant.EXTRA_SOUND_START, R.raw.bdspeech_recognition_start);
intent.putExtra(Constant.EXTRA_SOUND_END, R.raw.bdspeech_speech_end);
intent.putExtra(Constant.EXTRA_SOUND_SUCCESS, R.raw.bdspeech_recognition_success);
intent.putExtra(Constant.EXTRA_SOUND_ERROR, R.raw.bdspeech_recognition_error);
intent.putExtra(Constant.EXTRA_SOUND_CANCEL, R.raw.bdspeech_recognition_cancel);
intent.putExtra(Constant.EXTRA_OFFLINE_SLOT_DATA, buildTestSlotData());
}
//导入离线数据
private String buildTestSlotData() {
JSONObject slotData = new JSONObject();
JSONArray name = new JSONArray().put("张三").put("李四").put("王五");
JSONArray app = new JSONArray().put("QQ").put("地图").put("微信").put("支付宝").put("知乎").put("网易云音乐")
.put("美团").put("饿了么").put("京东").put("微博").put("去哪儿").put("贴吧");
JSONArray usercommand = new JSONArray().put("关灯").put("开灯").put("相机").put("拍照").put("联系人").put("通信录");
try {
slotData.put(Constant.EXTRA_OFFLINE_SLOT_NAME, name);
slotData.put(Constant.EXTRA_OFFLINE_SLOT_APP, app);
slotData.put(Constant.EXTRA_OFFLINE_SLOT_USERCOMMAND, usercommand);
} catch (JSONException e) {
}
return slotData.toString();
}
//识别结束结果返回
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
onResults(data.getExtras());
}
}
@Override
public void onReadyForSpeech(Bundle params) {
}
@Override
public void onBeginningOfSpeech() {
}
@Override
public void onRmsChanged(float rmsdB) {
}
@Override
public void onBufferReceived(byte[] buffer) {
}
@Override
public void onEndOfSpeech() {
print("说完了");
}
@Override
public void onError(int error) {
}
@Override
public void onResults(Bundle results) {
long end2finish = System.currentTimeMillis() - speechEndTime;
ArrayList nbest = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
// print("识别成功:" + Arrays.toString(nbest.toArray(new String[nbest.size()])));
String strEnd2Finish = "";
if (end2finish < 60 * 1000) {
strEnd2Finish = "(waited " + end2finish + "ms)";
}
textResult.setText(nbest.get(0) + strEnd2Finish);
//对识别结果进行分析
recognize(nbest);
}
@Override
public void onPartialResults(Bundle partialResults) {
}
@Override
public void onEvent(int eventType, Bundle params) {
}
@Override
protected void onDestroy() {
speechRecognizer.destroy();
super.onDestroy();
}
//对识别结果进行分析
public void recognize(ArrayList nbest) {
print("");
int bool=0;
for(int i=0;i