与天地兮比寿,与日月兮齐光。这篇文章主要讲述Android讯飞语音云语音听写学习相关的知识,希望能为你提供帮助。
讯飞语音云语音听写学习
这几天两个舍友都买了iPhone 6S,玩起了“Hey, Siri”,我依旧对我的Nexus 5喊着“OK,Google”。但种种原因,国内的“OK,Google”并不能展示出他的全部威力,于是上网搜索国内Android平台的语音助手,个人觉得评价最好的是讯飞的——灵犀语音助手。其实讯飞语音云平台早就注册过了,并下载了相应的SDK,只是没仔细研究。今天突然想好好学习一下,以方便以后集成到自己开发的APP中,也可以方便大家参考。开发工具:Android Studio。
好了,废话就说这些。先来看效果图:
文章图片
【Android讯飞语音云语音听写学习】
文章图片
文章图片
下面是具体的步骤。
1,首先在讯飞开放平台注册开发者账号,注册流程很简单,就不详细介绍。网址:http://www.xfyun.cn/。然后就是像各大平台一样的步骤:新建Android应用获取APPID—〉下载语音听写SDK。此处需要注意的是一定要新建自己的应用,别人的工程虽然能用,但不方便后续开发。
2,解压下载的SDK目录,里面有详细的教程,可自行参考。然后新建工程,将MSC.jar(放入到libs文件夹下)和libmsc.so(放入到新建的jniLibs文件夹下)导入到自己的工程中(只有在线的所有功能,没有提供离线服务。)另外,讯飞提供了两种语音识别接口,一种是后台进行语音检测,没有界面UI提示;另一种是带UI的接口,在录音、播放音频的时候,会有dialog弹出,并伴有相应的动画,相对来说用户交互体验很不错。如果使用带UI接口时,请将assets下文件拷贝到项目中。这里注意的是每个SDK下载的assets可能不一样(没有亲自测试过,因为recognize.xml打开乱码),一定要将自己下载的SDK里的assets目录拷贝到XXX/src/main文件夹下。工程目录如下:
文章图片
3,在AndroidManifest.xml文件中添加权限:
< !-- 在工程 androidManifest.xml 文件中添加如下权限 --> < !-- 连接网络权限,用于执行云端语音能力 --> < 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" /> < !-- 外存储写入权限, 构建语法需要用到此权限 --> < uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
4,布局文件activity_main.xml
< RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > < EditText android:id="@+id/content_rec" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="识别内容" /> < Button android:id="@+id/bt_start" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:onClick="startRec" android:text="开始" /> < Button android:id="@+id/btn_read" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/bt_start" android:layout_alignLeft="@+id/bt_start" android:layout_alignParentRight="true" android:onClick="read" android:text="朗读" /> < /RelativeLayout>
5,Java代码:JsonParser.java 和 MainActivity.java
(1),JsonParser.Java
package com.xiaobailong24.xunfeiyun; import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONTokener; /** * Json结果解析类 */ public class JsonParser {public static String parseIatResult(String json) { StringBuffer ret = new StringBuffer(); try { JSONTokener tokener = new JSONTokener(json); JSONObject joResult = new JSONObject(tokener); JSONArray words = joResult.getJSONArray("ws"); for (int i = 0; i < words.length(); i++) { // 转写结果词,默认使用第一个结果 JSONArray items = words.getJSONObject(i).getJSONArray("cw"); JSONObject obj = items.getJSONObject(0); ret.append(obj.getString("w")); //如果需要多候选结果,解析数组其他字段 //for(int j = 0; j < items.length(); j++) //{ //JSONObject obj = items.getJSONObject(j); //ret.append(obj.getString("w")); //} } } catch (Exception e) { e.printStackTrace(); } return ret.toString(); }public static String parseGrammarResult(String json) { StringBuffer ret = new StringBuffer(); try { JSONTokener tokener = new JSONTokener(json); JSONObject joResult = new JSONObject(tokener); JSONArray words = joResult.getJSONArray("ws"); for (int i = 0; i < words.length(); i++) { JSONArray items = words.getJSONObject(i).getJSONArray("cw"); for(int j = 0; j < items.length(); j++) { JSONObject obj = items.getJSONObject(j); if(obj.getString("w").contains("nomatch")) { ret.append("没有匹配结果."); return ret.toString(); } ret.append("【结果】" + obj.getString("w")); ret.append("【置信度】" + obj.getInt("sc")); ret.append("\n"); } } } catch (Exception e) { e.printStackTrace(); ret.append("没有匹配结果."); } return ret.toString(); }public static String parseLocalGrammarResult(String json) { StringBuffer ret = new StringBuffer(); try { JSONTokener tokener = new JSONTokener(json); JSONObject joResult = new JSONObject(tokener); JSONArray words = joResult.getJSONArray("ws"); for (int i = 0; i < words.length(); i++) { JSONArray items = words.getJSONObject(i).getJSONArray("cw"); for(int j = 0; j < items.length(); j++) { JSONObject obj = items.getJSONObject(j); if(obj.getString("w").contains("nomatch")) { ret.append("没有匹配结果."); return ret.toString(); } ret.append("【结果】" + obj.getString("w")); ret.append("\n"); } } ret.append("【置信度】" + joResult.optInt("sc")); } catch (Exception e) { e.printStackTrace(); ret.append("没有匹配结果."); } return ret.toString(); } }
(2),MainActivity.java
package com.xiaobailong24.xunfeiyun; import android.app.Activity; import android.os.Environment; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.Toast; import com.iflytek.cloud.ErrorCode; import com.iflytek.cloud.InitListener; import com.iflytek.cloud.RecognizerListener; import com.iflytek.cloud.RecognizerResult; import com.iflytek.cloud.SpeechConstant; import com.iflytek.cloud.SpeechError; import com.iflytek.cloud.SpeechRecognizer; import com.iflytek.cloud.SpeechSynthesizer; import com.iflytek.cloud.SpeechUtility; import com.iflytek.cloud.SynthesizerListener; import com.iflytek.cloud.ui.RecognizerDialog; import com.iflytek.cloud.ui.RecognizerDialogListener; public class MainActivity extends Activity {private static String TAG = "MainActivity"; // 函数调用返回值 int ret = 0; // 语音听写对象 private SpeechRecognizer mIat; // 语音听写UI private RecognizerDialog iatDialog; // 听写结果内容 private EditText mResultText; // 语音合成对象 private SpeechSynthesizer mTts; // 默认发音人 private String voicer = "xiaoyan"; // 缓冲进度 private int mPercentForBuffering = 0; // 播放进度 private int mPercentForPlaying = 0; private Toast mToast; @Override public void onCreate(Bundle savedInstanceState) { Log.e(TAG, "onCreate"); super.onCreate(savedInstanceState); //this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); // 用于验证应用的key,将XXXXXXXX改为你申请的APPID SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=XXXXXXXX"); // 创建语音听写对象 mIat = SpeechRecognizer.createRecognizer(this, mInitListener); // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer // 创建语音听写UI iatDialog = new RecognizerDialog(MainActivity.this, mInitListener); // 创建语音合成对象 mTts = SpeechSynthesizer.createSynthesizer(this, mInitListener); mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT); content_rec)); }public void startRec(View view) { mResultText.setText(null); setParam(); boolean isShowDialog = true; if (isShowDialog) { // 显示听写对话框 iatDialog.setListener(recognizerDialogListener); iatDialog.show(); // showTip("begin"); } else { // 不显示听写对话框 ret = mIat.startListening(recognizerListener); if (ret != ErrorCode.SUCCESS) { // showTip("听写失败,错误码:" + ret); } else { // showTip("begin"); } } }public void read(View view) { String text = mResultText.getText().toString(); // 设置参数 setParam2(); //朗读 int code = mTts.startSpeaking(text, mTtsListener); if (code != ErrorCode.SUCCESS) { if (code == ErrorCode.ERROR_COMPONENT_NOT_INSTALLED) { // 未安装则跳转到提示安装页面 } else { showTip("语音合成失败,错误码: " + code); } } }/** * 参数设置 * * @param * @return */ private void setParam2() { Log.e(TAG, "setParam2"); // 设置合成 mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 设置发音人 mTts.setParameter(SpeechConstant.VOICE_NAME, voicer); // 设置语速 mTts.setParameter(SpeechConstant.SPEED, "50"); // 设置音调 mTts.setParameter(SpeechConstant.PITCH, "50"); // 设置音量 mTts.setParameter(SpeechConstant.VOLUME, "50"); // 设置播放器音频流类型 mTts.setParameter(SpeechConstant.STREAM_TYPE, "3"); }public void setParam() { Log.e(TAG, "setParam"); // 清空参数 mIat.setParameter(SpeechConstant.PARAMS, null); // 设置听写引擎 mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 设置语言 mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); // 设置语言区域 mIat.setParameter(SpeechConstant.ACCENT, "mandarin"); // 设置语音前端点 mIat.setParameter(SpeechConstant.VAD_BOS, "4000"); // 设置语音后端点 mIat.setParameter(SpeechConstant.VAD_EOS, "1000"); // 设置标点符号 1为有标点 0为没标点 mIat.setParameter(SpeechConstant.ASR_PTT, "0"); // 设置音频保存路径 mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/xiaobailong24/xunfeiyun"); }/** * 合成回调监听。 */ private SynthesizerListener mTtsListener = new SynthesizerListener() { @Override public void onSpeakBegin() { Log.e(TAG, "mTtsListener--> onSpeakBegin"); showTip("开始播放"); }@Override public void onSpeakPaused() { Log.e(TAG, "mTtsListener--> onSpeakPaused"); showTip("暂停播放"); }@Override public void onSpeakResumed() { Log.e(TAG, "mTtsListener--> onSpeakResumed"); showTip("继续播放"); }@Override public void onBufferProgress(int percent, int beginPos, int endPos, String info) { Log.e(TAG, "mTtsListener--> onBufferProgress"); mPercentForBuffering = percent; showTip(String.format(getString(R.string.tts_toast_format), mPercentForBuffering, mPercentForPlaying)); }@Override public void onSpeakProgress(int percent, int beginPos, int endPos) { Log.e(TAG, "mTtsListener--> onSpeakProgress"); mPercentForPlaying = percent; showTip(String.format(getString(R.string.tts_toast_format), mPercentForBuffering, mPercentForPlaying)); }@Override public void onCompleted(SpeechError error) { Log.e(TAG, "mTtsListener--> onCompleted"); if (error == null) { showTip("播放完成"); } else if (error != null) { showTip(error.getPlainDescription(true)); } }@Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { Log.e(TAG, "mTtsListener--> onEvent"); } }; /** * 听写监听器。 */ private RecognizerListener recognizerListener = new RecognizerListener() {@Override public void onVolumeChanged(int i, byte[] bytes) { Log.e(TAG, "recognizerListener--> onVolumeChanged"); showTip("当前正在说话,音量大小:" + i); }@Override public void onBeginOfSpeech() { Log.e(TAG, "recognizerListener--> onBeginOfSpeech"); showTip("开始说话"); }@Override public void onEndOfSpeech() { Log.e(TAG, "recognizerListener--> onEndOfSpeech"); showTip("结束说话"); }@Override public void onResult(RecognizerResult results, boolean isLast) { Log.e(TAG, "recognizerListener--> onResult"); String text = JsonParser.parseIatResult(results.getResultString()); mResultText.append(text); mResultText.setSelection(mResultText.length()); if (isLast) { // TODO 最后的结果 } }@Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { Log.e(TAG, "recognizerListener--> onEvent"); }@Override public void onError(SpeechError arg0) { Log.e(TAG, "recognizerListener--> onError"); // TODO Auto-generated method stub } }; /** * 听写UI监听器 */ private RecognizerDialogListener recognizerDialogListener = new RecognizerDialogListener() {public void onResult(RecognizerResult results, boolean isLast) { Log.e(TAG, "recognizerDialogListener--> onResult"); String text = JsonParser.parseIatResult(results.getResultString()); mResultText.append(text); mResultText.setSelection(mResultText.length()); }/** * 识别回调错误. */ public void onError(SpeechError error) { Log.e(TAG, "recognizerDialogListener--> onError"); showTip(error.getPlainDescription(true)); } }; private InitListener mInitListener = new InitListener() { @Override public void onInit(int code) { Log.e(TAG, "mInitListener--> onInit"); Log.d(TAG, "SpeechRecognizer init() code = " + code); if (code != ErrorCode.SUCCESS) { showTip("初始化失败,错误码:" + code); } } }; private void showTip(final String str) { Log.e(TAG, "showTip--> " + str); mToast.setText(str); mToast.show(); }@Override protected void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); // 退出时释放连接 mIat.cancel(); mIat.destroy(); }@Override protected void onResume() { Log.e(TAG, "onResume"); super.onResume(); }@Override protected void onPause() { Log.e(TAG, "onPause"); super.onPause(); }}
推荐阅读
- Android之动画2
- Android 延时执行任务的三种简单方法
- CSS高级布局(Flexbox布局完全指南)
- Python如何使用Collections.UserDict(代码示例)
- 算法设计(将第一个元素加倍,然后将零移动到结尾)
- Python程序如何实现在列表中查找第二大数字()
- PHP如何使用Ds\Sequence apply()函数(示例)
- PHP如何使用DS\Map clear()函数(用法示例)
- 算法设计(如何实现CamelCase模式匹配(代码示例))