您的位置:首页 > 其它

讯飞语音的语音听写功能实现的总结以及新手如何着手第三方SDK

2017-08-08 00:38 645 查看

讯飞语音的语音听写功能实现的总结以及新手如何着手第三方SDK

前言 {才知道前言和序言的区别,写文章的好处,吱吱}
由于本人最近有点小忙,所以没有更新博客。其实呢!我想说的是我的草稿箱都快要堆满了,只是感觉没有技术含量就不献丑了(内心独白:让一个语文几乎只有小学及格过的人写这种真的好让人揪心,我写的东西自己都不想看第二遍,此刻,如果可以,相信你会看到成千上万的表情包---表达我此刻的内心世界),好吧!我承认,写文章以及向别人表达自己的思路和想法一直都是我的软肋。说真的,写文章和总结,真的能锻炼人,还能让你理解的更深入和思路更清晰。然并软,自己并没有做到。。。感谢老师又激起了,我向上的心!!!有那么一种说法,当你向别人解释你的理解,而你的解释对方并不能形象的理解的时候,说明其实这个知识点,还是不够了解它。只能说自己尚需努力了。(排版有点丑,第一次使用
Markdown 做笔记,相信帅气的你,看哪都会顺眼的) 尾言 提示:因为最近比较喜欢简书的平台,所以
CSDN 很少看,不回复请谅解

一、首先我们要下载相应的sdk,这里就不多说了,毕竟我的目的只是起到抛砖引玉的效果

刚开始看官方的Demo的时候,我也是一头雾水,因为他考虑的比较周全,所以就感觉很复杂,其实不然,冷静下来,把分体细化了就难了,刚开始的时候先不要究死在细节的东西,先看整体的思路和实现方式,而不是一头的就扎进去了,就好像无头苍蝇一样,如果你都不知道自己在干嘛,后面还有什么事。不要搞得自己很忙,自己却感觉丝毫没有做出什么东西来,要明白一个道理努力并不恒等于效率,科学的办事很重要。自己就经常犯这样的错误。

二、官方的新手指南一定要看,不想看也要粗略看一下,至少后面遇见问题了,你会想起可能有那么一回事。灵光一闪,曙光照亮,瞬间感觉到自己之前是有多么的蒙蒙哒,好气啊,怎么现在才知道,鄙人深有体会啊!!****

三、你可以能会遇见的错误:

讯飞集成的时候遇到“组件未安装.(错误码:21002)

原因1:-
so文件与自己的SDK不匹配 当我们复制别人的so包的时候那你的定应用名和 appid 要也和别人的一致,否则so文件和应用名 appid都要自己的

原因2:so包找不到 哆啦A梦传送门:blog.csdn.net/rodulf/article/details/71246612

Genymotion安装apk的时候安装不了报错 其它模拟器也有这种情况:出现INSTALLFAILEDCPUABIINCOMPATIBLE错误 Intent传送门:http://blog.csdn.net/zhuwentao2150/article/details/51087911

没有初始化即创建语音配置对象: 建议将初始化放在程序入口处(如Application、Activity的onCreate方法),初始化代码如下:

//
将“12345678”替换成您申请的APPID,申请地址:http://www.xfyun.cn // 请勿在“=”与appid之间添加任何空字符或者转义符 SpeechUtility.createUtility(context, SpeechConstant.APPID +"=12345678");


整体步骤

大体:两种实现方式,1.SpeechRecognizer 对象进行监听,2.RecognizerDialog 对象进行监听,这个官方的Demo采用了两种结合的方式实现,默认第二种方式(即弹出窗口的设置),用户可以设置时用第二种方式进行监听

初始化即创建语音配置对象

创建结果集合存储听写结果 实现类似讯同步语音听写功能,而要进行翻译的话就不走这步了因为翻译的话要监听用户的整个过程来实现的,翻译好了再一次性输出

创建
监听对象 1.创建SpeechRecognizer 对象 用于在不显示听写对话框的方式时监听用户语音, 2.创建RecognizerDialog 对象 用于在显示听写对话框的方式时监听用户语音

设置SpeechRecognizer监听对象的参数 (如果采用了SpeechRecognizer
对象 的方式语音监听,那么这一步,绝不能少)1.选择引擎类型 这里我只考虑了一种引擎类型 :云端的方式;2.设置返回结果格式

创建SharedPreferences
对象 用于保存用户的设置,当用户有设置时,就按用户的方式进行(比如用户是否要翻译啊,是否使用使用UI听写功能等等,自己脑补去吧)为什么要使用这种方式呢,因为这种方式 get 数据时,第二个参数有一个默认值,get 不到数据时,也得到一个默认值,这种给数据一个默认值的设计技巧可以用到开当中去例如
this.mTranslateEnable
= mSharedPreferences.getBoolean( this.getString(R.string.pref_key_translate), false );
当用户没有设置是否要翻译成某种语言翻译时,就采取默认 false 的方式 不翻译

把语音显示成文字 我们都知道讯飞大量采用了回调的机制给我们返回
json类型数据,所以在监听的接口的成功时回调数据的方法解析 json 数据更新 UI 即可

Talking is easy, let me show the code!

一.初始化即创建语音配置对象:初始化即创建语音配置对象:
建议将初始化放在程序入口处(如Application、Activity的onCreate方法),官方Demo是在如 Application 中的
public class SpeechApp extends Application {
@Override
public void onCreate() {
// 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null
// 如在Application中调用初始化,需要在Mainifest中注册该Applicaiton
// 注意:此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请增加参数:SpeechConstant.FORCE_LOGIN+"=true"
// 参数间使用半角“,”分隔。
// 设置你申请的应用appid,请勿在'='与appid之间添加空格及空转义符
// 注意: appid 必须和下载的SDK保持一致,否则会出现10407错误
//当我们复制别人的so包的时候那你的定应用名和 appid 要也和别人的一致,否则so文件和应用名 appid都要自己的

SpeechUtility.createUtility(SpeechApp.this, "appid=" + getString(R.string.app_id));

// 以下语句用于设置日志开关(默认开启),设置成false时关闭语音云SDK日志打印
// Setting.setShowLog(false);
super.onCreate();
}


二.创建结果集合存储听写结果

//这里为什么使用 LinkedHashMap,就不用我多说了吧 private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();

三.创建监听对象

3.1
创建RecognizerDialog 对象 该方式相对于下面的另外一种比较简单
`//第二个参数为初始化监器(后面细说在 3.2中)mIatDialog = new RecognizerDialog(this, mInitListener);`


使用RecognizerDialog
对象 UI听写功能,不要忘了在创建 assets 目录放置显示RecognizerDialog需要的布局文件和图片资源

3.2
创建SpeechRecognizer 对象 如果只使用RecognizerDialogUI听写功能,无需创建SpeechRecognizer
mIat = SpeechRecognizer.createRecognizer(this, mInitListener);


这种方式比较麻烦,毕竟没有了类似 RecognizerDialog方式的Xml的配置参数,都是自己在代码里设置的参数,例如:
public void setParam() {
// 清空参数
mIat.setParameter(SpeechConstant.PARAMS, null);

// 设置听写引擎  注意:这里我只设置云端的方式!后面再考虑本地和混合的类型
mIat.setParameter(SpeechConstant.ENGINE_TYPE, mCLOUDType);
// 设置返回结果格式
mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");

this.mTranslateEnable = mSharedPreferences.getBoolean( this.getString(R.string.pref_key_translate), false );
if( mTranslateEnable ){
Log.i( TAG, "translate enable" );
mIat.setParameter( SpeechConstant.ASR_SCH, "1" );
mIat.setParameter( SpeechConstant.ADD_CAP, "translate" );
mIat.setParameter( SpeechConstant.TRS_SRC, "its" );
}

String lag = mSharedPreferences.getString("iat_language_preference", "mandarin");
if (lag.equals("en_us")) {
// 设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");
mIat.setParameter(SpeechConstant.ACCENT, null);

if( mTranslateEnable ){
mIat.setParameter( SpeechConstant.ORI_LANG, "en" );
mIat.setParameter( SpeechConstant.TRANS_LANG, "cn" );
}
} else {
// 设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
// 设置语言区域
mIat.setParameter(SpeechConstant.ACCENT, lag);

if( mTranslateEnable ){
mIat.setParameter( SpeechConstant.ORI_LANG, "cn" );
mIat.setParameter( SpeechConstant.TRANS_LANG, "en" );
}
}

// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString("iat_vadbos_preference", "4000"));

// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString("iat_vadeos_preference", "1000"));

// 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString("iat_punc_preference", "1"));

// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
// 注:AUDIO_FORMAT参数语记需要更新版本才能生效
mIat.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/iat.wav");
}


3.2
初始化监听器 作用:我的理解是刚开始时就要监听讯飞给我们返回的 code 值,如若初始化就失败了,就应该Toast 提示用户停止操作了,而不应该让用户一直满腔热火的在呐喊着,结果却没有输出文字,“我的天,这什么鬼,垃圾软件,老子。。。。。”
private InitListener mInitListener = new InitListener() {

@Override
public void onInit(int code) {
Log.d(TAG, "SpeechRecognizer init() code = " + code);
if (code != ErrorCode.SUCCESS) {
showTip("初始化失败,错误码:" + code);
}
}
};


四.创建SharedPreferences
对象 用于保存用户的设置,具体看 Demo的源码 当用户有设置时,就按用户的方式进行(比如用户是否要翻译啊,是否使用使用UI听写功能等等,自己脑补去吧)为什么要使用这种方式呢,因为这种方式 get 数据时,第二个参数有一个默认值,get 不到数据时,也得到一个默认值,这种给数据一个默认值的设计技巧可以用到开当中去例如
this.mTranslateEnable
= mSharedPreferences.getBoolean( this.getString(R.string.pref_key_translate), false );
当用户没有设置是否要翻译成某种语言翻译时,就采取默认 false 的方式 不翻译

五.把语音显示成文字

因为显示数据使用RecognizerDialog 对象 以及使用SpeechRecognizer 对象的两种方式都要吧返回的Json数据进行解析所以写在了外边,做了简单的疯转,分别调用即可

五.把语音显示成文字 要进行翻译的话
就放进结果集合当中去了,因为要等说完后,才翻译输出
//要进行翻译的话 就放进结果集合当中去了,因为要等说完后,才翻译输出
private void printTransResult (RecognizerResult results) {
String trans  = JsonParser.parseTransResult(results.getResultString(),"dst");
String oris = JsonParser.parseTransResult(results.getResultString(),"src");

if( TextUtils.isEmpty(trans)||TextUtils.isEmpty(oris) ){
showTip( "解析结果失败,请确认是否已开通翻译功能。" );
}else{
tv_show.setText( "原始语言:\n"+oris+"\n目标语言:\n"+trans );
}

}

/**
* 成功时显示说话的文字
* @param results
*/
private void printResult(RecognizerResult results) {
String text = JsonParser.parseIatResult(results.getResultString());

String sn = null;
// 读取json结果中的sn字段
try {
JSONObject resultJson = new JSONObject(results.getResultString());
sn = resultJson.optString("sn");
} catch (JSONException e) {
e.printStackTrace();
}

mIatResults.put(sn, text);

StringBuffer resultBuffer = new StringBuffer();
for (String key : mIatResults.keySet()) {
resultBuffer.append(mIatResults.get(key));
}

tv_show.setText(resultBuffer.toString());
//考虑到TextView只能显示文字 ,后面还要测试文字转语音,所以换EditText控件
tv_show.setSelection(tv_show.length());

}


好了,如果我的文章对你有帮助的话,请点赞,您的支持是我持续输出的动力,Demo的代码在我的 GitHub上
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐