$科大讯飞开放平台——语音听写接口的使用
最近在做毕设项目中,要用到一个语音识别的功能,主要目的是把用户说的话转换成文字,然后再做其他处理。找了多个语音识别的第三方SDK,比如百度语音识别、微信语音识别、科大讯飞语音识别,发现科大讯飞的比较好用。做了一个Demo程序,有详细的注释,在这里整理一下。
(一)准备工作
0、创建一个空的Android项目,比如项目名叫:SpeechRecognitionDemoJYJ。
1、首先要在科大讯飞开放平台(http://www.xfyun.cn/)上注册,或者用QQ等第三方登录也行。
2、点击网站首页右上角的“控制台”,进入控制台。
3、按照说明创建一个应用,该应用名就叫SpeechRecognitionDemoJYJ,创建成功后会有一个AppID,记下来,编程的时候要用到。
4、点击SpeechRecognitionDemoJYJ后面的“开通服务”按钮,开通服务—>语音听写,进入语音听写—>下载当前应用对应的SDK。
5、下载Android版的SDK,将SDK包中libs目录下的Msc.jar和armeabi复制到Android工程的libs目录(如果工程无libs目录,请自行创建)中,并且因为还要用到语音听写Dialog,所以还要把SDK包中assets目录下的iflytek文件夹复制到工程的assets目录下,如下图所示。还要注意,每个不同的应用都要申请不同的AppID,并且要分别下载不同AppID对应的SDK,否则会出错。
6、其他更详细的说明和资料可以参看讯飞开放平台的资料库(http://www.xfyun.cn/doccenter)。
(二)开发
Demo实现的功能很简单,就是点击一个按钮,弹出语音识别Dialog窗口,说话,说完了点击Dialog窗口后会把自动识别的文字结果显示在下方的EditText中。服务器返回的语音听写的结果是Json格式数据,最后还要对Json数据进行解析(具体解析方法参看我的这篇文章:用GSON解析Json格式数据),解析出语音字符串。
1、XML代码:
界面中有一个按钮,一个TextView和一个EditText,EditText用于显示语音识别的结果。
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:orientation="vertical" > 5 6 <Button 7 android:id="@+id/listen_btn" 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:text="开始说话" /> 11 12 <TextView 13 android:id="@+id/task_tv" 14 android:layout_width="match_parent" 15 android:layout_height="wrap_content" 16 android:layout_margin="20dp" 17 android:text="日程安排:" /> 18 19 <EditText 20 android:id="@+id/content_et" 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:background="@android:drawable/editbox_dropdown_light_frame" 24 android:cursorVisible="true" 25 android:enabled="true" 26 android:gravity="top" 27 android:visibility="visible" /> 28 29 </LinearLayout>
2、MainActivity
1 import java.lang.reflect.Type; 2 import java.util.List; 3 4 import com.example.speechrecognition.DictationResult; 5 import com.google.gson.Gson; 6 import com.google.gson.reflect.TypeToken; 7 import com.iflytek.cloud.RecognizerListener; 8 import com.iflytek.cloud.RecognizerResult; 9 import com.iflytek.cloud.SpeechConstant; 10 import com.iflytek.cloud.SpeechError; 11 import com.iflytek.cloud.SpeechRecognizer; 12 import com.iflytek.cloud.SpeechUtility; 13 import com.iflytek.cloud.ui.RecognizerDialog; 14 import com.iflytek.cloud.ui.RecognizerDialogListener; 15 16 import android.app.Activity; 17 import android.content.Context; 18 import android.os.Bundle; 19 import android.os.Handler; 20 import android.os.Message; 21 import android.util.Log; 22 import android.view.Menu; 23 import android.view.MenuItem; 24 import android.view.View; 25 import android.view.View.OnClickListener; 26 import android.view.inputmethod.InputMethodManager; 27 import android.widget.Button; 28 import android.widget.EditText; 29 import android.widget.TextView; 30 31 public class MainActivity extends Activity implements OnClickListener { 32 private static String APPID = "569e39a1"; 33 34 private Button listenBtn; 35 private EditText contentEt; 36 37 // 听写结果字符串(多个Json的列表字符串) 38 private String dictationResultStr = "["; 39 40 @Override 41 protected void onCreate(Bundle savedInstanceState) { 42 super.onCreate(savedInstanceState); 43 setContentView(R.layout.activity_main); 44 45 listenBtn = (Button) findViewById(R.id.listen_btn); 46 contentEt = (EditText) findViewById(R.id.content_et); 47 48 listenBtn.setOnClickListener(this); 49 50 } 51 52 @Override 53 public void onClick(View v) { 54 switch (v.getId()) { 55 case R.id.listen_btn: 56 57 dictationResultStr = "["; 58 // 语音配置对象初始化 59 SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID 60 + "=" + APPID); 61 62 // 1.创建SpeechRecognizer对象,第2个参数:本地听写时传InitListener 63 SpeechRecognizer mIat = SpeechRecognizer.createRecognizer( 64 MainActivity.this, null); 65 // 交互动画 66 RecognizerDialog iatDialog = new RecognizerDialog( 67 MainActivity.this, null); 68 // 2.设置听写参数,详见《科大讯飞MSC API手册(Android)》SpeechConstant类 69 mIat.setParameter(SpeechConstant.DOMAIN, "iat"); // domain:域名 70 mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); 71 mIat.setParameter(SpeechConstant.ACCENT, "mandarin"); // mandarin:普通话 72 73 //3.开始听写 74 iatDialog.setListener(new RecognizerDialogListener() { 75 76 @Override 77 public void onResult(RecognizerResult results, boolean isLast) { 78 // TODO 自动生成的方法存根 79 // Log.d("Result", results.getResultString()); 80 // contentTv.setText(results.getResultString()); 81 if (!isLast) { 82 dictationResultStr += results.getResultString() + ","; 83 } else { 84 dictationResultStr += results.getResultString() + "]"; 85 } 86 if (isLast) { 87 // 解析Json列表字符串 88 Gson gson = new Gson(); 89 List<DictationResult> dictationResultList = gson 90 .fromJson(dictationResultStr, 91 new TypeToken<List<DictationResult>>() { 92 }.getType()); 93 String finalResult = ""; 94 for (int i = 0; i < dictationResultList.size() - 1; i++) { 95 finalResult += dictationResultList.get(i) 96 .toString(); 97 } 98 contentEt.setText(finalResult); 99 100 //获取焦点 101 contentEt.requestFocus(); 102 103 //将光标定位到文字最后,以便修改 104 contentEt.setSelection(finalResult.length()); 105 106 Log.d("From reall phone", finalResult); 107 } 108 } 109 110 @Override 111 public void onError(SpeechError error) { 112 // TODO 自动生成的方法存根 113 error.getPlainDescription(true); 114 } 115 }); 116 117 // 开始听写 118 iatDialog.show(); 119 120 break; 121 default: 122 break; 123 } 124 } 125 }
3、自定义的com.example.speechrecognition.DictationResult类的代码:
1 import java.util.List; 2 3 /** 4 * 解析语音听写返回结果Json格式字符串的模板类(多重嵌套Json) 5 * 6 * 语音识别结果Json数据格式(单条数据): 7 * {"sn":1,"ls":true,"bg":0,"ed":0,"ws":[{"bg":0,"cw":[{"w":"今天","sc":0}]}, 8 * {"bg":0,"cw":{"w":"的","sc":0}]},{"bg":0,"cw":[{"w":"天气","sc":0}]}, 9 * {"bg":0,"cw":[{"w":"怎么样","sc":0}]},{"bg":0,"cw":[{"w":"。","sc":0}]}]} 10 */ 11 public class DictationResult { 12 private String sn; 13 private String ls; 14 private String bg; 15 private String ed; 16 17 private List<Words> ws; 18 19 public static class Words { 20 private String bg; 21 private List<Cw> cw; 22 23 public static class Cw { 24 private String w; 25 private String sc; 26 27 public String getW() { 28 return w; 29 } 30 31 public void setW(String w) { 32 this.w = w; 33 } 34 35 public String getSc() { 36 return sc; 37 } 38 39 public void setSc(String sc) { 40 this.sc = sc; 41 } 42 43 @Override 44 public String toString() { 45 return w; 46 } 47 } 48 49 public String getBg() { 50 return bg; 51 } 52 53 public void setBg(String bg) { 54 this.bg = bg; 55 } 56 57 public List<Cw> getCw() { 58 return cw; 59 } 60 61 public void setCw(List<Cw> cw) { 62 this.cw = cw; 63 } 64 65 @Override 66 public String toString() { 67 String result = ""; 68 for (Cw cwTmp : cw) { 69 result += cwTmp.toString(); 70 } 71 return result; 72 } 73 } 74 75 public String getSn() { 76 return sn; 77 } 78 79 public void setSn(String sn) { 80 this.sn = sn; 81 } 82 83 public String getLs() { 84 return ls; 85 } 86 87 public void setLs(String ls) { 88 this.ls = ls; 89 } 90 91 public String getBg() { 92 return bg; 93 } 94 95 public void setBg(String bg) { 96 this.bg = bg; 97 } 98 99 public String getEd() { 100 return ed; 101 } 102 103 public void setEd(String ed) { 104 this.ed = ed; 105 } 106 107 public List<Words> getWs() { 108 return ws; 109 } 110 111 public void setWs(List<Words> ws) { 112 this.ws = ws; 113 } 114 115 @Override 116 public String toString() { 117 String result = ""; 118 for (Words wsTmp : ws) { 119 result += wsTmp.toString(); 120 } 121 return result; 122 } 123 }
4、AndroidManifest.xml中申请权限:
1 <!-- 连接网络权限,用于执行云端语音能力 --> 2 <uses-permission android:name="android.permission.INTERNET"/> 3 <!-- 获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 --> 4 <uses-permission android:name="android.permission.RECORD_AUDIO"/> 5 <!--读取网络信息状态 --> 6 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 7 <!--获取当前wifi状态 --> 8 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> 9 <!--允许程序改变网络连接状态 --> 10 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> 11 <!--读取手机信息权限 --> 12 <uses-permission android:name="android.permission.READ_PHONE_STATE"/> 13 <!--读取联系人权限,上传联系人需要用到此权限 --> 14 <uses-permission android:name="android.permission.READ_CONTACTS"/>
5、测试:模拟器无法打开录音机,是不能在上面测试的,要用真机测试。测试结果如下图: