您的位置:首页 > 其它

科大讯飞的语音合成和语音识别

2015-01-19 16:09 381 查看
好久没有更新博客了,一个月又差不多过完了,公司的项目又被搁浅了,然后天天去客户公司无所事事,光看别人的代码最坑的是那套代码还没有注释,现在我是严重鄙视那些不写注释的程序狗,然后项目还跑不起来,以前也没有做过金融类的的项目,里面全都是一些报文格式,然后还没有需求文档,真的是醉了,刚好呢现在公司也不大管我们了,不注重研发的公司就是坑。。。。。。

今天呢随便来用下科大讯飞的语音功能,代码也非常的简单,然后就把它集成到一个查快递的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

下下来可以玩玩,呵呵,不要积分的额
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: