转载:https://blog.csdn.net/chenli_001/article/details/73603917
一、语音识别
1.下载SDK(地址:http://www.xfyun.cn/sdk/dispatcher),选择语音听写SDK(如下图) ,下载前会让你先创建应用,创建应用后会得到一个appid。然后点“立即开通”去开通“语音识别”功能,之后就会跳出“SDK下载”的页面,然后就可以下载了(未注册账号的要先注册一个账号)。
2.将下载好的SDK中 libs 目录下的 Msc.jar包引入到工程中(参见http://blog.csdn.net/highboys/article/details/51549679,此外,因为本Demo中会用到json的东西,所以还得自己去网上下一个Gson的jar包,一并引进去)。之后在main目录下新建一个jniLibs目录,将 SDK中 libs 目录下的armeabi 拷进去,如下图所示(第④个先不用管):
3.科大讯飞为我们提供了一套语音听写时的UI,即听写的时候会有一个动画效果(如下图),这个时候我们需要 先将 SDK 资源包 assets 路径下的资源文件拷贝至 android 工程asstes 目录下(没有的话自己新建),参照第2步图的④。
4.接下来就是代码的实现了。首先在Manifest中添加一下权限
- <!--连接网络权限,用于执行云端语音能力 -->
- <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" />
- <!--SD卡读写的权限(如果需要保存音频文件到本地的话)-->
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
其次是java代码(逻辑上是点击了某个Button之后,才执行下面的代码)。
- //有动画效果
- private RecognizerDialog iatDialog;
- // ①语音配置对象初始化
- SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=578f1af7");//将这里的578f1af7替换成自己申请得到的8位appid
- // ②初始化有交互动画的语音识别器
- 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();
其中的mInitListener定义如下:
- public static final String TAG = "MainActivity";
- 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();
- }
- }
- };
上面的代码用到了一个DictationResult类(一个用来接收转换 语音听写结果的类),需要自己新建,定义如下
- /**
- * 解析 语音听写返回结果Json格式字符串 的模板类(多重嵌套Json)
- *
- * 语音识别结果Json数据格式(单条数据):
- * {"sn":1,"ls":true,"bg":0,"ed":0,"ws":[
- * {"bg":0,"cw":[{"w":"今天","sc":0}]},
- * {"bg":0,"cw":[{"w":"的","sc":0}]},
- * {"bg":0,"cw":[{"w":"天气","sc":0}]},
- * {"bg":0,"cw":[{"w":"怎么样","sc":0}]},
- * {"bg":0,"cw":[{"w":"。","sc":0}]}
- * ]}
- *
- * sn number :第几句
- * ls boolean: 是否最后一句
- * bg number :开始
- * ed number :结束
- * ws array :词
- * cw array :中文分词
- * w string :单字
- * sc number :分数
- */
- 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;
- }
- }
如此,便可实现语音听写了。这个过程可能会遇到各种各样的问题,具体错误码参见 http://www.xfyun.cn/doccenter/faq
5.说完了有动画效果的,下面就来说说没有动画效果的(也比较简单)。
- //1.创建SpeechRecognizer对象,第二个参数:本地识别时传InitListener
- SpeechRecognizer mIat = SpeechRecognizer.createRecognizer(context, null);
- //2.设置听写参数,详见SDK中《MSC Reference Manual》文件夹下的SpeechConstant类
- mIat.setParameter(SpeechConstant.DOMAIN,"iat");
- mIat.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
- mIat.setParameter(SpeechConstant.ACCENT,"mandarin ");
- //保存音频文件到本地(有需要的话) 仅支持pcm和wav,且需要自行添加读写SD卡权限
- mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/mIat.wav");
- // 3.开始听写
- mIat.startListening(mRecoListener);
- //听写监听器
- private RecognizerListener mRecoListener = new RecognizerListener() {
- //听写结果回调接口(返回Json格式结果,用户可参见附录13.1);
- // 一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;
- // 关于解析Json的代码可参见Demo中JsonParser类;
- // isLast等于true时会话结束。
- public void onResult(RecognizerResult results, boolean isLast) {
- Log.d(TAG, "result:" + results.getResultString());
- }
- //会话发生错误回调接口
- public void onError(SpeechError error) {
- //打印错误码描述
- Log.d(TAG, "error:" + error.getPlainDescription(true))
- }
- //开始录音
- public void onBeginOfSpeech() {
- }
- // volume音量值0~30,data音频数据
- public void onVolumeChanged(int volume, byte[] data) {
- }
- //结束录音
- public void onEndOfSpeech() {
- }
- //扩展用接口
- public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
- }
- };
可以看到上面的onResult回调方法跟有动画效果时的onResult回调方法是一样的,所以主要的处理还是在这个方法中,将有动画的那个onResult回调中的代码拷过来就行了。如此,简单的语音听写功能就实现了。(
//在最后必须重新设置一下,不是json格式就会报错 resultJson="[";
)