前不久项目中用到了语音识别技术,因此就研究了一下语音识别技术在项目中的集成。由于我是在公司的设备上运行的,所以没有截图,为了直观方便的看一下效果,所以就在网上找了两张和我的项目运行后差不多的图片。
市场上的语音技术应用最广泛的有两种,一种是百度的语音识别,一种是科大讯飞的语音识别。两者之间的不同之处在于,前者是完全免费的,后者在离线状态识别语音是收费的。今天先记录一下科大讯飞在线的语音识别,等有机会在记录一下百度的语音识别。
首先需要在科大讯飞的开放平台上申请一个账号,申请的过程就不再描述。申请成功以后,平台会发放一个APPID号。这个ID号留待使用。 然后平台会让你创建一个应用,这时候你把自己的应用信息填好以后,选择SDK下载。
当SDK下载完以后,会得到一个ZIP压缩包,解开这个压缩包,会看到如下的文件:
其中assets目录里是资源文件,主要是语音识别的弹出框图片,可以原封不动拷过来。如果只是单纯的识别,还需要拷贝两个文件,一个是libs下的armeabi文件夹,一个是libs下的Msc.jar。拷贝完以后,放到项目的libs文件夹下。
准备工作完成以后,就可以进行代码的编写了,一般是在点击某个按钮以后,进入语音识别的情景。在这里假设点击了某个按钮的场景
package com.szh.speechdemo.activity;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import com.szh.speechdemo.R;
import com.szh.speechdemo.model.DictationResult;
public class MainActivity extends Activity {
public static final String TAG = "MainActivity";
private EditText etText;
private Button btn_yysb;
private Button btn_save;
private RecognizerDialog iatDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 初始化即创建语音配置对象,只有初始化后才可以使用MSC的各项服务
// 此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请使用参数:SpeechConstant.APPID
// +"=12345678," + SpeechConstant.FORCE_LOGIN +"=true"。
setContentView(R.layout.activity_main);
btn_yysb = (Button) findViewById(R.id.btn_yysb);
etText = (EditText)findViewById(R.id.etText);
btn_save = (Button) findViewById(R.id.btn_save);
btn_save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SpeechUtility.getUtility().destroy();
}
});
btn_yysb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ①语音配置对象初始化
SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=5a587636");
// ②初始化有交互动画的语音识别器
iatDialog = new RecognizerDialog(MainActivity.this, mInitListener);
// ③设置监听,实现听写结果的回调
iatDialog.setListener(new RecognizerDialogListener() {
String resultJson = "[";// 放置在外边做类的变量则报错,会造成json格式不对(?)
@Override
public void onResult(RecognizerResult recognizerResult, boolean isLast) {
System.out .println("----------------- onResult -----------------");
if (!isLast) {
resultJson += recognizerResult.getResultString() + ",";
} else {
resultJson += recognizerResult.getResultString() + "]";
}
if (isLast) {
// 解析语音识别后返回的json格式的结果
Gson gson = new Gson();
List<DictationResult> resultList = gson.fromJson(
resultJson,
new TypeToken<List<DictationResult>>() {
}.getType());
String result = "";
for (int i = 0; i < resultList.size() - 1; i++) {
result += resultList.get(i).toString();
}
etText.setText(result);
// 获取焦点
etText.requestFocus();
// 将光标定位到文字最后,以便修改
etText.setSelection(result.length());
}
}
@Override
public void onError(SpeechError speechError) {
// 自动生成的方法存根
speechError.getPlainDescription(true);
}
});
// 开始听写,需将sdk中的assets文件下的文件夹拷入项目的assets文件夹下(没有的话自己新建)
iatDialog.show();
}
});
}
// 3.开始听写 mIat.startListening(mRecoListener);
// 听写监听器
private InitListener mInitListener = new InitListener() {
@Override
public void onInit(int code) {
Log.d(TAG, "SpeechRecognizer init() code = " + code);
if (code != ErrorCode.SUCCESS) {
Toast.makeText(MainActivity.this, "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();
}
}
};
}
当语音转化成文字的时候,我们还需要用到Gson进行转换成bean进行封装,bean结构如下:
package com.szh.speechdemo.model;
import java.util.List;
public class DictationResult {
private String sn;
private String ls;
private String bg;
private String ed;
private List<Words> ws;
public static class Words {
private String bg;
private List<Cw> cw;
public static class Cw {
private String w;
private String sc;
public String getW() {
return w;
}
public void setW(String w) {
this.w = w;
}
public String getSc() {
return sc;
}
public void setSc(String sc) {
this.sc = sc;
}
@Override
public String toString() {
return w;
}
}
public String getBg() {
return bg;
}
public void setBg(String bg) {
this.bg = bg;
}
public List<Cw> getCw() {
return cw;
}
public void setCw(List<Cw> cw) {
this.cw = cw;
}
@Override
public String toString() {
String result = "";
for (Cw cwTmp : cw) {
result += cwTmp.toString();
}
return result;
}
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getLs() {
return ls;
}
public void setLs(String ls) {
this.ls = ls;
}
public String getBg() {
return bg;
}
public void setBg(String bg) {
this.bg = bg;
}
public String getEd() {
return ed;
}
public void setEd(String ed) {
this.ed = ed;
}
public List<Words> getWs() {
return ws;
}
public void setWs(List<Words> ws) {
this.ws = ws;
}
@Override
public String toString() {
String result = "";
for (Words wsTmp : ws) {
result += wsTmp.toString();
}
return result;
}
}
在这里有些细节还需要注意:
第一点,SpeechUtility.getUtility().destroy();这句代码是注销语音的,如果语音已经被注销掉,但是在初始化的时候只初始化了一次,下次再注销的时候就会报错。
第二点,如果是在activity中,onCreate方法中如果不回调super.onCreate(savedInstanceState)方法,会出现闪退现象。
我把项目中用到的资源文件和jar包放上链接,有需要的可以自行下载。下载积分本来想设置成0积分,不过好像最少就是2,无法设置不要积分下载。如果嫌麻烦就从这下载,或者在网上搜别的也行。
链接如下:https://download.csdn.net/download/little_soybean/10354424