语音识别主要的功能就是在用户不方便输入的时候找一个替代输入的选择。
1.本地语音识别
下面的代码首先创建SpeechRecognizer对象,并设置回调函数监听器。当在点击监听器中调用doSpeechRecognition()方法时,会使用语言参数和一个指示要在处理过程中分发部分结果的标志参数初始化语音识别。
public class MainActivity extends Activity implements View.OnClickListener{ private Button speechBut; private TextView result; private SpeechRecognizer mSpeechRecognizer; @Override public void onClick(View v) { switch (v.getId()){ case R.id.speechBut: doSpeechRecognition(v); break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.speechBut=(Button)findViewById(R.id.speechBut); this.speechBut.setOnClickListener(this); this.result=(TextView)findViewById(R.id.result); this.mSpeechRecognizer=SpeechRecognizer.createSpeechRecognizer(this); this.mSpeechRecognizer.setRecognitionListener(new MyRecognitionListener()); } public void doSpeechRecognition(View view){ view.setEnabled(false); Intent recognitionIntent=new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); recognitionIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS,true); recognitionIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,"zh-CN"); this.mSpeechRecognizer.startListening(recognitionIntent); } private class MyRecognitionListener implements RecognitionListener{ @Override public void onReadyForSpeech(Bundle params) { } @Override public void onBeginningOfSpeech() { Log.i("llllllllllllllllllll","onBeginningOfSpeech"); result.setText(""); } @Override public void onRmsChanged(float rmsdB) { } @Override public void onBufferReceived(byte[] buffer) { } @Override public void onEndOfSpeech() { Log.i("llllllllllllllllllll","onEndOfSpeech"); speechBut.setEnabled(true); } @Override public void onError(int error) { Log.i("llllllllllllllllllll","onError"); speechBut.setEnabled(true); } @Override public void onResults(Bundle results) { Log.i("llllllllllllllllllll","onResults"); ArrayList<String> partialResults=results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); if(partialResults!=null && partialResults.size()>0){ String bestResult=partialResults.get(0); result.setText(bestResult+"."); } } @Override public void onPartialResults(Bundle bundle) { Log.i("llllllllllllllllllll","onPartialResults"); ArrayList<String> partialResults=bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); if(partialResults!=null && partialResults.size()>0){ String bestResult=partialResults.get(0); result.setText(bestResult); } } @Override public void onEvent(int eventType, Bundle params) { } } @Override protected void onDestroy() { super.onDestroy(); this.mSpeechRecognizer.destroy(); } }
现在监听器会按照顺序接受每个方法的调用。本例在onPartialResult()方法中展现部分识别的结果,直到在onResult()方法中得到最终的结果。
一个更高级的应用程序还可以拦截单词,并监听特定的命令。这样一来,应用程序可以一直进行语音识别,直到用户明确告诉它停止-----例如,一个听写应用允许用户说“停止”单词并暂停一会后在句子间添加句号。
2.第三方语音识别(以讯飞为例)
我们大家都知道,一般Android手机是不支持中文语音识别的,我们有时候连文字转语音都要下载第三方文字转语音(TTS)API,更何况语音转文字。所以一般时候必须利用第三方提供SDK来丰富我们自己的应用功能。
就目前国内而言,在语音方面做的最好的也就属讯飞语音了。下面的开发以讯飞为例。
首先我们得到讯飞开放平台http://www.xfyun.cn/注册一个帐号。
然后如上图所示创建一个新应用,创建完应用后我们会得到如图所示的Appid:
然后下载相关的SDK包放到指定的位置,本文以Android Studio为例:
下面就可以进入开发阶段了,首先本例语音识别必须借助网络,所以本例需要的权限如下:
<!--连接网络权限,用于执行云端语音能力 --> <uses-permission android:name="android.permission.INTERNET" /> <!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!--读取网络信息状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!--获取当前wifi状态 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!--允许程序改变网络连接状态 --> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <!--读取手机信息权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!--读取联系人权限,上传联系人需要用到此权限 --> <uses-permission android:name="android.permission.READ_CONTACTS" />
本来想讲解一下具体的代码突然觉得自己的代码已经注解够详细了,并不需要一句一句的讲解。相信大家都看的懂。
public class MainActivity extends Activity { private static String TAG = MainActivity.class.getSimpleName(); private Toast mToast; private Button showDialogs; private Button stop; private Button cancel; private TextView content; // 语音听写对象 private SpeechRecognizer mIat; // 语音听写UI private RecognizerDialog mIatDialog; // 用HashMap存储听写结果 private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>(); // 引擎类型 private String mEngineType = SpeechConstant.TYPE_CLOUD; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.showDialogs = (Button) findViewById(R.id.showDialogs); this.stop = (Button) findViewById(R.id.stopL); this.cancel=(Button)findViewById(R.id.cancel); this.content = (TextView) findViewById(R.id.content); SpeechUtility.createUtility(this, SpeechConstant.APPID + "=5566a1f6"); // 初始化识别无UI识别对象 // 使用SpeechRecognizer对象,可根据回调消息自定义界面; mIat = SpeechRecognizer.createRecognizer(this, mInitListener); // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer // 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源 mIatDialog = new RecognizerDialog(MainActivity.this, mInitListener); this.showDialogs.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { content.setText("");// 清空显示内容 mIatResults.clear(); myRecognize(); // 显示听写对话框 mIatDialog.show(); showTip(getString(R.string.text_begin)); } }); this.stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mIat.stopListening(); showTip("停止听写"); } }); this.cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mIat.cancel(); showTip("取消听写"); } }); } /** * 初始化监听器。 */ private InitListener mInitListener = new InitListener() { @Override public void onInit(int code) { Log.d(TAG, "SpeechRecognizer init() code = " + code); if (code != ErrorCode.SUCCESS) { showTip("初始化失败,错误码:" + code); } } }; private void showTip(final String str) { this.mToast.makeText(this,str,Toast.LENGTH_SHORT).show(); } private void myRecognize() { // 清空参数 mIat.setParameter(SpeechConstant.PARAMS, null); // 设置听写引擎 mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType); // 设置返回结果格式 mIat.setParameter(SpeechConstant.RESULT_TYPE, "json"); //设置引擎为转写 mIatDialog.setParameter(SpeechConstant.DOMAIN, "iat"); //设置识别语言为中文 mIatDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); //设置方言为普通话 mIatDialog.setParameter(SpeechConstant.ACCENT, "mandarin"); //设置录音采样率为 mIatDialog.setParameter(SpeechConstant.SAMPLE_RATE, "16000"); //设置监听对象 mIatDialog.setListener(recognizerDialogListener); // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理 mIat.setParameter(SpeechConstant.VAD_BOS, "4000"); // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音 mIat.setParameter(SpeechConstant.VAD_EOS, "4000"); // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点 mIat.setParameter(SpeechConstant.ASR_PTT, "1"); // 设置听写结果是否结果动态修正,为“1”则在听写过程中动态递增地返回结果,否则只在听写结束之后返回最终结果 // 注:该参数暂时只对在线听写有效 mIat.setParameter(SpeechConstant.ASR_DWA, "0"); } private RecognizerDialogListener recognizerDialogListener = new RecognizerDialogListener() { @Override public void onError(SpeechError error) { // TODO Auto-generated method stub } //当说话说完后,会回调该方法,JSON字符串在result @Override public void onResult(RecognizerResult result, boolean isLast) { Log.d(TAG, result.getResultString()); printResult(result); } }; private void printResult(RecognizerResult results) { String text = JsonParser.parseIatResult(results.getResultString()); String sn = null; // 读取json结果中的sn字段 try { JSONObject resultJson = new JSONObject(results.getResultString()); sn = resultJson.optString("sn"); } catch (JSONException e) { e.printStackTrace(); } mIatResults.put(sn, text); StringBuffer resultBuffer = new StringBuffer(); for (String key : mIatResults.keySet()) { resultBuffer.append(mIatResults.get(key)); } content.setText(resultBuffer.toString()); } @Override protected void onDestroy() { super.onDestroy(); // 退出时释放连接 mIat.cancel(); mIat.destroy(); } }
当然里面有一个JSON解析,你可以自己写,也可以用SDK里面包装好的JsonParser类。
JSON解析不会的可以参考http://blog.csdn.net/liyuanjinglyj/article/details/45890825该网址
最后运行结果如下图所示: