一、语音识别
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中添加一下权限
[html] view plain copy
print?
- <!--连接网络权限,用于执行云端语音能力 -->
- <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之后,才执行下面的代码)。
[java] view plain copy
print?


- //有动画效果
- 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定义如下:
[java] view plain copy
print?


- 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类(一个用来接收转换 语音听写结果的类),需要自己新建,定义如下
[java] view plain copy
print?


- /**
- * 解析 语音听写返回结果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.说完了有动画效果的,下面就来说说没有动画效果的(也比较简单)。
[java] view plain copy
print?
- //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回调中的代码拷过来就行了。如此,简单的语音听写功能就实现了。
二、语音合成
1.语音合成也需要创建语音配置对象:
[java] view plain copy
print?
- SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=578f1af7");
2.创建用于语音合成的对象并设置参数,进行语音合成
[java] view plain copy
print?
- //1.创建SpeechSynthesizer对象, 第二个参数:本地合成时传InitListener
- SpeechSynthesizer mTts = SpeechSynthesizer.createSynthesizer(MainActivity.this, null);
- /**
- 2.合成参数设置,详见《科大讯飞MSC API手册(Android)》SpeechSynthesizer 类
- *
- */
- // 清空参数
- mTts.setParameter(SpeechConstant.PARAMS, null);
- mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); //设置云端
- mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");//设置发音人
- mTts.setParameter(SpeechConstant.SPEED, "50");//设置语速
- //设置合成音调
- mTts.setParameter(SpeechConstant.PITCH, "50");
- mTts.setParameter(SpeechConstant.VOLUME, "80");//设置音量,范围0~100
- mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");
- // 设置播放合成音频打断音乐播放,默认为true
- mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
- // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
- // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
- // mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
- // boolean isSuccess = mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/tts2.wav");
- // Toast.makeText(MainActivity.this, "语音合成 保存音频到本地:\n" + isSuccess, Toast.LENGTH_LONG).show();
- //3.开始合成
- int code = mTts.startSpeaking("在这里放置需要进行合成的文本", mSynListener);
- if (code != ErrorCode.SUCCESS) {
- if (code == ErrorCode.ERROR_COMPONENT_NOT_INSTALLED) {
- //上面的语音配置对象为初始化时:
- Toast.makeText(MainActivity.this, "语音组件未安装", Toast.LENGTH_LONG).show();
- } else {
- Toast.makeText(MainActivity.this, "语音合成失败,错误码: " + code, Toast.LENGTH_LONG).show();
- }
- }
合成时需要一个SynthesizerListener类型的合成监听器作参数,定义如下
[java] view plain copy
print?
- //合成监听器
- private SynthesizerListener mSynListener = new SynthesizerListener() {
- //会话结束回调接口,没有错误时,error为null
- public void onCompleted(SpeechError error) {
- }
- //缓冲进度回调
- //percent为缓冲进度0~100,beginPos为缓冲音频在文本中开始位置,endPos表示缓冲音频在文本中结束位置,info为附加信息。
- public void onBufferProgress(int percent, int beginPos, int endPos, String info) {
- }
- //开始播放
- public void onSpeakBegin() {
- }
- //暂停播放
- public void onSpeakPaused() {
- }
- //播放进度回调
- //percent为播放进度0~100,beginPos为播放音频在文本中开始位置,endPos表示播放音频在文本中结束位置.
- public void onSpeakProgress(int percent, int beginPos, int endPos) {
- }
- //恢复播放回调接口
- public void onSpeakResumed() {
- }
- //会话事件回调接口
- public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {
- }
- };