好久没有更新博客了,一个月又差不多过完了,公司的项目又被搁浅了,然后天天去客户公司无所事事,光看别人的代码最坑的是那套代码还没有注释,现在我是严重鄙视那些不写注释的程序狗,然后项目还跑不起来,以前也没有做过金融类的的项目,里面全都是一些报文格式,然后还没有需求文档,真的是醉了,刚好呢现在公司也不大管我们了,不注重研发的公司就是坑。。。。。。
今天呢随便来用下科大讯飞的语音功能,代码也非常的简单,然后就把它集成到一个查快递的app里,也是懒得改东西了。
首先就先来说下科大讯飞:语音技术实现了人机语音交互,使人与机器之间沟通变得像人与人沟通一样简单。语音技术主要包括语音合成和语音识别两项关键技术。让机器说话,用的是语音合成技术;让机器听懂人说话,用的是语音识别技术。此外,语音技术还包括语音编码、音色转换、口语评测、语音消噪和增强等技术,有着广阔应用空间。
讯飞的语音sdk是需要申请的,地址是:http://www.voicecloud.cn/。申请一个讯飞的开发者账号,然后申请一个appid,申请的时候需要填写开发者信息和你的应用的信息。记住这个appid是开发中必须用到的,所以搞那么麻烦就是为了这个appid和下载开发的sdk。这appid与你开启的服务有关,一般就基础服务就好了,有些是增值服务,然后每一个项目的appid都是不一样的。
由于科大讯飞的sdk的版本有所不同,然后调用的方法也有所不同,特别是Msc.jar里面的内容是不断更新的,开发的时候你可以先导入他的sample看看,去感受一下它的强大。然后我们就把libs文件夹拷贝到自己 的项目工程里,接着就是编写代码了,也不多说了。
这个文章是根据sdk写的,也参考了别人的代码,毕竟也是纯属好玩搞了一下,能够把声音转化为文字,再把文字转为声音,就能满足一些基本的功能了,里面的注释写的很详细,只要随便改改就能直接用到你的项目里面。
从图里可以看到这是运用的几个功能,但是好像Msc.jar的版本不一样所以调用的方法有所出入,然后我自己的好像就没有SpeechUtilty这个类,文中主要用到了RecognizerDialog,SpeechRecognizer,RecognizerDialogListener,SpeechListener,SynthesizerListener,SpeechSynthesizer。然后功能只能把语音转换为文字,再把文本信息本地合成语音,还有很多的地方需要完善。
简单效果:
先看布局
main_activity.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="match_parent" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@drawable/icon_microphone" android:layout_alignParentRight="true" android:id="@+id/button1" /> <EditText android:id="@+id/content" android:layout_width="fill_parent" android:layout_marginRight="50dp" android:layout_height="30dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" /> </RelativeLayout>
mainActivity.java
package com.example.voicetoword; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import com.coderqi.publicutil.voice.VoiceToWord; import com.example.voicetoword.R; public class MainActivity extends Activity implements OnClickListener{ Button but = null; private EditText content; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); but = (Button) findViewById(R.id.button1); content=(EditText) findViewById(R.id.content); but.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View v) { switch (v.getId()) { //听写按钮 case R.id.button1: VoiceToWord voice = new VoiceToWord(MainActivity.this,"54ae8c54");//你申请的appid voice.GetWordFromVoice(); break; } } @Override protected void onResume() { super.onResume(); //content.setText(((MyApplicaton)getApplication()).getText()); } }
接下来的就是数据解析类:
package zy.voice; import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONTokener; import android.text.TextUtils; //import com.iflytek.speech.ErrorCode; //import com.iflytek.speech.SpeechError; /** * 对云端返回的Json结果进行解析 * @author iFlytek * @since 20131211 */ public class JsonParser { /** * 听写结果的Json格式解析 * @param json * @return */ public static String parseIatResult(String json) { if(TextUtils.isEmpty(json)) return ""; 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(); } /** * 识别结果的Json格式解析 * @param json * @return */ 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(); } /** * 语义结果的Json格式解析 * @param json * @return */ public static String parseUnderstandResult(String json) { StringBuffer ret = new StringBuffer(); try { JSONTokener tokener = new JSONTokener(json); JSONObject joResult = new JSONObject(tokener); ret.append("【应答码】" + joResult.getString("rc") + "\n"); ret.append("【转写结果】" + joResult.getString("text") + "\n"); ret.append("【服务名称】" + joResult.getString("service") + "\n"); ret.append("【操作名称】" + joResult.getString("operation") + "\n"); ret.append("【完整结果】" + json); } catch (Exception e) { e.printStackTrace(); ret.append("没有匹配结果."); } return ret.toString(); } }
这个是弹出的说话的dialog
package zy.voice; import android.content.Context; import android.text.TextUtils; import android.widget.Toast; import com.iflytek.cloud.speech.RecognizerResult; import com.iflytek.cloud.speech.SpeechConstant; import com.iflytek.cloud.speech.SpeechError; import com.iflytek.cloud.speech.SpeechSynthesizer; import com.iflytek.cloud.speech.SynthesizerListener; import com.iflytek.cloud.ui.RecognizerDialogListener; /** * 识别回调监听器 */ public class MyRecognizerDialogLister implements RecognizerDialogListener,SynthesizerListener{ private Context context; //本地合成对象 private SpeechSynthesizer speechSynthesizer; public MyRecognizerDialogLister(Context context) { this.context = context; setParam(); } // 自定义的结果回调函数,成功执行第一个方法,失败执行第二个方法 @Override public void onResult(RecognizerResult results, boolean isLast) { String text = JsonParser.parseIatResult(results.getResultString()); Toast.makeText(context, text, Toast.LENGTH_LONG).show(); //app.setText(text); if(!TextUtils.isEmpty(text)){//如果返回的内容不为空 //开始把文本信息合成语音 speechSynthesizer.startSpeaking(text, this); } } /** * 识别回调错误. */ @Override public void onError(SpeechError error) {//错误码请访问http://open.voicecloud.cn/index.php/default/doccenter/doccenterInner?itemTitle=ZmFx&anchor=Y29udGl0bGU2Ng== // TODO Auto-generated method stub int errorCoder = error.getErrorCode(); switch (errorCoder) { case 10118://用户没有说话,没有数据 System.out.println("user don't speak anything"); break; case 10200://网络一般错误 System.out.println("can't connect to internet"); break; default: break; } } public void setParam() { //创建SpeechSynthesizer 对象 speechSynthesizer = SpeechSynthesizer.createSynthesizer(context); speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");//默认的,发音人为小燕(青年女声),小梅为新引擎参数,效果好点 speechSynthesizer.setParameter(SpeechConstant.SPEED, "50");//语速 speechSynthesizer.setParameter(SpeechConstant.VOLUME, "50");//音量,范围是0---100 speechSynthesizer.setParameter(SpeechConstant.PITCH, "50"); } /** * percent 缓冲进度 0-100 * beginPos 缓冲音频在文中的开始位置 * endPos 缓冲音频在文中的末位置 * info 附加信息 * */ @Override public void onBufferProgress(int percent, int beginPos, int endPos, String info) { } //会话结束回调接口,无错误时err为null @Override public void onCompleted(SpeechError err) { } //开始播放 @Override public void onSpeakBegin() { } //暂停播放 @Override public void onSpeakPaused() { } /** * percent 播放进度 0-100 * beginPos 播放音频在文中的开始位置 * endPos 播放音频在文中的末位置 * */ @Override public void onSpeakProgress(int percent, int beginPos, int endPos) { } //恢复 播放 @Override public void onSpeakResumed() { }}最后的是把你的话转为文字
package zy.voice; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Environment; import android.text.TextUtils; import android.widget.Toast; import com.iflytek.cloud.speech.SpeechConstant; import com.iflytek.cloud.speech.SpeechError; import com.iflytek.cloud.speech.SpeechListener; import com.iflytek.cloud.speech.SpeechRecognizer; import com.iflytek.cloud.speech.SpeechUser; import com.iflytek.cloud.ui.RecognizerDialog; import com.iflytek.cloud.ui.RecognizerDialogListener; import com.iflytek.sunflower.FlowerCollector; public class VoiceToWord extends Activity { private Context context; private Toast mToast; // 识别窗口 private RecognizerDialog iatDialog; // 识别对象 private SpeechRecognizer iatRecognizer; // 缓存,保存当前的引擎参数到下一次启动应用程序使用. private SharedPreferences mSharedPreferences; private RecognizerDialogListener recognizerDialogListener = null; public VoiceToWord(Context context, String APP_ID) { // TODO Auto-generated constructor stub // 用户登录 this.context = context; // 初始化缓存对象. mSharedPreferences = context.getSharedPreferences( context.getPackageName(), MODE_PRIVATE); SpeechUser.getUser().login(context, null, null, "appid=" + APP_ID, listener); // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer iatDialog = new RecognizerDialog(context); mToast = Toast.makeText(context, "", Toast.LENGTH_LONG); // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer iatDialog = new RecognizerDialog(context); iatDialog.setCanceledOnTouchOutside(false); } public VoiceToWord(Context context, String APP_ID, RecognizerDialogListener recognizerDialogListener) { this.context = context; SpeechUser.getUser().login(context, null, null, "appid=" + APP_ID, listener); // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer iatDialog = new RecognizerDialog(context); mToast = Toast.makeText(context, "", Toast.LENGTH_LONG); // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer iatDialog = new RecognizerDialog(context); // 在dialog外面不能取消 iatDialog.setCanceledOnTouchOutside(false); // 初始化缓存对象. mSharedPreferences = context.getSharedPreferences( context.getPackageName(), MODE_PRIVATE); this.recognizerDialogListener = recognizerDialogListener; } public void GetWordFromVoice() { boolean isShowDialog = mSharedPreferences.getBoolean("iat_show", true); if (isShowDialog) { // 显示语音听写Dialog. showIatDialog(); } else { if (null == iatRecognizer) { iatRecognizer = SpeechRecognizer.createRecognizer(this); // 设置返回结果格式 // iatRecognizer.setParameter(SpeechConstant.RESULT_TYPE, "json"); // // String lag = mSharedPreferences.getString( // "iat_language_preference", "mandarin"); // if (lag.equals("en_us")) { // // 设置语言 // iatRecognizer // .setParameter(SpeechConstant.LANGUAGE, "en_us"); // } else { // // 设置语言 // iatRecognizer // .setParameter(SpeechConstant.LANGUAGE, "zh_cn"); // // 设置语言区域 // iatRecognizer.setParameter(SpeechConstant.ACCENT, lag); // } // // 设置语音前端点 // iatRecognizer.setParameter(SpeechConstant.VAD_BOS, // mSharedPreferences.getString("iat_vadbos_preference", // "4000")); // // 设置语音后端点 // iatRecognizer.setParameter(SpeechConstant.VAD_EOS, // mSharedPreferences.getString("iat_vadeos_preference", // "1000")); // // 设置标点符号 // iatRecognizer.setParameter(SpeechConstant.ASR_PTT, // mSharedPreferences // .getString("iat_punc_preference", "1")); // // 设置音频保存路径 // iatRecognizer.setParameter(SpeechConstant.ASR_AUDIO_PATH, // Environment.getExternalStorageDirectory() // + "/iflytek/wavaudio.pcm");//需在清单文件里添加sd卡的权限 } if (iatRecognizer.isListening()) { iatRecognizer.stopListening(); // ((Button) // findViewById(android.R.id.button1)).setEnabled(false); } else { } } } /** * 显示听写对话框. * * @param */ public void showIatDialog() { if (null == iatDialog) { // 初始化听写Dialog iatDialog = new RecognizerDialog(this); } // 获取引擎参数 String engine = mSharedPreferences.getString("iat_engine", "iat"); // 清空Grammar_ID,防止识别后进行听写时Grammar_ID的干扰 iatDialog.setParameter(SpeechConstant.CLOUD_GRAMMAR, null); // 设置听写Dialog的引擎 iatDialog.setParameter(SpeechConstant.DOMAIN, engine); // 设置采样率参数,支持8K和16K String rate = mSharedPreferences.getString("sf", "sf"); if (rate.equals("rate8k")) { iatDialog.setParameter(SpeechConstant.SAMPLE_RATE, "8000"); } else { iatDialog.setParameter(SpeechConstant.SAMPLE_RATE, "16000"); } if (recognizerDialogListener == null) { getRecognizerDialogListener(); } // 显示听写对话框 iatDialog.setListener(recognizerDialogListener); iatDialog.show(); } private void getRecognizerDialogListener() { /** * 识别回调监听器 */ recognizerDialogListener = new MyRecognizerDialogLister(context); } /** * 用户登录回调监听器. */ private SpeechListener listener = new SpeechListener() { @Override public void onData(byte[] arg0) { } @Override public void onCompleted(SpeechError error) { if (error != null) { System.out.println("user login success"); } } @Override public void onEvent(int arg0, Bundle arg1) { } }; protected void onDestroy() { // 退出时释放连接 iatRecognizer.cancel(); iatRecognizer.destroy(); }; @Override protected void onResume() { // 移动数据统计分析 FlowerCollector.onResume(this); FlowerCollector.onPageStart("VoiceToWord"); super.onResume(); } @Override protected void onPause() { // 移动数据统计分析 FlowerCollector.onPageEnd("VoiceToWord"); FlowerCollector.onPause(this); super.onPause(); } }
最后别忘了添加权限
写博客真的是一个辛苦的过程,以后要多努力,更希望技术会有所提高
源码的下载地:》》》》》》》》》》》》》》》》》》》》》》http://download.csdn.net/detail/u013278099/8377787
下下来可以玩玩,呵呵,不要积分的额