android 语音转换文字(科大讯飞SDK简易封装)

简介:本地讲解的是 科大讯飞开发平台的语音转换功能的集成方法和封装


准备工作:


1、首先申请平台账号,创建我的应用,新增语音服务,获取Appid


2、下载创建的应用的对应SDK,这条很重要,每一个应用会对应一个SDK,用于做区分。

构建项目:


1、首先将需要的组件.jar包和.so文件引入工程,(注:由于CPU型号限制,speechDemo下的libs下的 arm64-v8a文件夹不要粘贴到我的工程,否则会报CPU型号异常而打不开APP,记得将你的其他组件的.so文件分别复制粘贴到 armeabi和armeabi-v7a文件下,否则会报错)


2、其次将下载的SDK的speechDemo中的 assets目录下的所有文件拷贝到我的项目中。注:必须是对应的SDK下的SpeechDemo中的assets文件夹,这个文件夹的内部文件其实也可以说是,区别于其他APP的SDK,内部包括录音Dialog的图片素材等文件


3、复制speechDemo中的相关Util组件到我的项目


下面贴几张图:("设置"界面我将它放在外部了,因为是SDK中提供好的Activity我就不贴代码了)

android 语音转换文字(科大讯飞SDK简易封装)_第1张图片     android 语音转换文字(科大讯飞SDK简易封装)_第2张图片     android 语音转换文字(科大讯飞SDK简易封装)_第3张图片     android 语音转换文字(科大讯飞SDK简易封装)_第4张图片


下面是我封装的speechDemo的方法:

package com.android.action.app.iflytek.util;

/**
 * 录音转译功能封装类,用于语音识别和转换文字
 * 
 * @version 1
 * @param 2016.10.31 由Sherdon构建
 * */
public class SpeechService {
	private Context context;
	private SpeechRecognizer speechRecognizer;//
	private String mEngineType;// 转译类型
	private static String TAG = "SpeechService_";

	public SpeechService() {
	};

	/**
	 * 录音转译功能封装类
	 * 
	 * @param mEngineType
	 *            转译模式类型((云端)在线,本地,混合)
	 * */
	public SpeechService(Context context, String mEngineType) {
		this.context = context;
		this.mEngineType = mEngineType;
	};

	private RecognizerDialog speechRecognizerDialog;
	private SharedPreferences mSharedPreferences;

	/**
	 * 返回语音转换对象,
	 * @return SpeechRecognizer
	 *            返回语音识别器对象,在当前Activity的生命周期中需要用到,进行销毁暂停等操作
	 * */
	public SpeechRecognizer initIflytek() {
		// 注册
		// SpeechUtility.createUtility(context,SpeechConstant.APPID +
		// "=ab123456");这里替换为你自己的Appid
		SpeechUtility.createUtility(context, SpeechConstant.APPID
				+ StringConstants.VoiceAppid);
		// 使用SpeechRecognizer对象,可根据回调消息自定义界面;
		speechRecognizer = SpeechRecognizer.createRecognizer(context,
				mInitListener);
		// 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer
		// 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源
		speechRecognizerDialog = new RecognizerDialog(context, mInitListener);

		mSharedPreferences = context.getSharedPreferences(
				IatSettings.PREFER_NAME, Activity.MODE_PRIVATE);
		// mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
		// et_remark = ((EditText) findViewById(R.id.iat_text));
		// mInstaller = new ApkInstaller(context);
		// Activity activity = (Activity) context;

		return speechRecognizer;
	}

	/**
	 * 初始化监听器。
	 */
	private InitListener mInitListener = new InitListener() {

		@Override
		public void onInit(int code) {
			Log.d(TAG + "初始化监听器", "SpeechRecognizer init() code = " + code);
			if (code != ErrorCode.SUCCESS) {
				Toast.makeText(context, "初始化失败,错误码:" + code, Toast.LENGTH_SHORT)
						.show();
			}
		}
	};
	// 用HashMap存储听写结果
	private HashMap speechRecognizerResults = new LinkedHashMap();

	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();
		}

		speechRecognizerResults.put(sn, text);

		StringBuffer resultBuffer = new StringBuffer();
		for (String key : speechRecognizerResults.keySet()) {
			resultBuffer.append(speechRecognizerResults.get(key));
		}
		currentEditText.setText(resultBuffer.toString());
		currentEditText.setSelection(currentEditText.length());
		// switch (voiceType) {
		// case 1:// 今日小结
		// mEdResult.setText(resultBuffer.toString());
		// mEdResult.setSelection(mEdResult.length());
		// break;
		// case 2:// 补充说明
		// mEdSuppleExplan.setText(resultBuffer.toString());
		// mEdSuppleExplan.setSelection(mEdSuppleExplan.length());
		// break;
		// }
	}

	private EditText currentEditText;// 当前需要赋值的EditText

	/**
	 * 返回录音文件的路径用于播放
	 * 
	 * @param mEngineType
	 *            语音识别模式 云端(在线)、本地、混合,此处传该参数是用于,刷新可能被修改的语音识别模式
	 * @param editText 目标输入框,语音转译后生成文本的目标控件
	 * @return mAudioPath 返回录音文件路径,用于录音文件处理
	 * */
	public String doIflytek(EditText editText, String mEngineType) {
		this.mEngineType = mEngineType;
		this.currentEditText = editText;
		// 移动数据分析,收集开始听写事件
		FlowerCollector.onEvent(context, "iat_recognize");
		editText.setText(null);// 清空显示内容
		speechRecognizerResults.clear();
		// 设置参数
		setParam();
		boolean isShowDialog = mSharedPreferences.getBoolean(
				context.getString(R.string.pref_key_iat_show), true);
		if (isShowDialog) {
			// 显示听写对话框
			speechRecognizerDialog.setListener(mRecognizerDialogListener);
			speechRecognizerDialog.show();
			// showMessage(context.getString(R.string.text_begin));
			Toast.makeText(context, context.getString(R.string.text_begin),
					Toast.LENGTH_SHORT).show();
		} else {
			// 不显示听写对话框
			int ret = speechRecognizer.startListening(mRecognizerListener);
			if (ret != ErrorCode.SUCCESS) {
				Toast.makeText(context, "听写失败,错误码:" + ret, Toast.LENGTH_SHORT)
						.show();
			} else {
				Toast.makeText(context, context.getString(R.string.text_begin),
						Toast.LENGTH_SHORT).show();
			}
		}
		return mAudioPath;
	}

	private String mAudioPath; // 录音

	public void setParam() {
		// 清空参数
		speechRecognizer.setParameter(SpeechConstant.PARAMS, null);
		// 设置听写引擎
		speechRecognizer.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
		// 设置返回结果格式
		speechRecognizer.setParameter(SpeechConstant.RESULT_TYPE, "json");

		String lag = mSharedPreferences.getString("iat_language_preference",
				"mandarin");
		if (lag.equals("en_us")) {
			// 设置语言
			speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "en_us");
		} else {
			// 设置语言
			speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
			// 设置语言区域
			speechRecognizer.setParameter(SpeechConstant.ACCENT, lag);
		}

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

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

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

		// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
		// 注:AUDIO_FORMAT参数语记需要更新版本才能生效
		speechRecognizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
		// mAudioPath = Environment.getExternalStorageDirectory()
		// + "/ydsanbu/msc/" + DateUtil.getCurrentTime() + ".wav";
		mAudioPath = context.getExternalFilesDir(null) + File.separator
				+ "logReport.wav";
		speechRecognizer
				.setParameter(SpeechConstant.ASR_AUDIO_PATH, mAudioPath);
	}

	/**
	 * 听写监听器。
	 */
	private RecognizerListener mRecognizerListener = new RecognizerListener() {

		@Override
		public void onBeginOfSpeech() {
			// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
			Toast.makeText(context, "开始说话", Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onError(SpeechError error) {
			// Tips:
			// 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
			// 如果使用本地功能(语记)需要提示用户开启语记的录音权限。
			Toast.makeText(context, error.getPlainDescription(true),
					Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onEndOfSpeech() {
			// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
			Toast.makeText(context, "结束说话", Toast.LENGTH_SHORT).show();

		}

		@Override
		public void onResult(RecognizerResult results, boolean isLast) {
			Log.d(TAG + "onResult", results.getResultString());
			printResult(results);
			if (isLast) {
				// TODO 最后的结果
				// File file=new File(mAudioPath);
				// if(file!=null){
				// // mAudioPath = pVisitVO.getOpinionAudio();
				// int time = Util.getSeconds(mAudioPath);
				// rl_audio.setVisibility(View.VISIBLE);
				// tv_audio.setCompoundDrawablesWithIntrinsicBounds(
				// R.drawable.chatto_voice_playing, 0, 0, 0);
				// tv_audio.setCompoundDrawablePadding(5);
				// tv_audio.setText(String.valueOf(time));
				// tv_audio.setGravity(Gravity.CENTER_VERTICAL);
				// }
			}
		}

		@Override
		public void onVolumeChanged(int volume, byte[] data) {
			// showMessage("当前正在说话,音量大小:" + volume);
			Log.d(TAG + "onVolumeChanged", "返回音频数据:" + data.length);
		}

		@Override
		public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
			// 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
			// 若使用本地能力,会话id为null
			// if (SpeechEvent.EVENT_SESSION_ID == eventType) {
			// String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
			// Log.d(TAG, "session id =" + sid);
			// }
		}
	};

	/**
	 * 听写UI监听器
	 */
	private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
		public void onResult(RecognizerResult results, boolean isLast) {
			printResult(results);
			if (isLast) {
				// TODO 最后的结果
				// File file=new File(mAudioPath);
				// if(file!=null){
				// // mAudioPath = pVisitVO.getOpinionAudio();
				// int time = Util.getSeconds(mAudioPath);
				// rl_audio.setVisibility(View.VISIBLE);
				// tv_audio.setCompoundDrawablesWithIntrinsicBounds(
				// R.drawable.chatto_voice_playing, 0, 0, 0);
				// tv_audio.setCompoundDrawablePadding(5);
				// tv_audio.setText(String.valueOf(time));
				// tv_audio.setGravity(Gravity.CENTER_VERTICAL);
				// }
			}
		}

		/**
		 * 识别回调错误.
		 */
		public void onError(SpeechError error) {
			Toast.makeText(context, error.getPlainDescription(true),
					Toast.LENGTH_SHORT).show();
		}
	};
}

以下是Activity的调用:

package com.android.action.app.activity.page.vspharmacy;

@SuppressLint("NewApi")
public class SalesActiveActivity extends BaseActivity implements
		OnLongClickListener {

	private final String TAG = "SalesActiveActivity";
	/**
	
	private String mAbnormalAudio; // 录音
	
	private EditText et_remark;

	private TextView m_tv_word; // 剩余字数
	private TextView title; //

	private int m_total_count = 200; // 默认最长输入200个字符

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.abnormal_layout);
		// 获取上个界面传递过来的数据
		parseIntent();
		initViews();
		initListeners();
		initData();
		initIflytek();
	}

	private String mEngineType = SpeechConstant.TYPE_CLOUD;
	private SpeechRecognizer sRecognizer;
	// 语记安装助手类,用于语音模式切换,切换本地或者混合模式时,提示安装语记,来部署本地环境
	ApkInstaller mInstaller;

	private void initIflytek() {
		// TODO Auto-generated method stub
		mInstaller = new ApkInstaller(SalesActiveActivity.this);
		speechService = new SpeechService(SalesActiveActivity.this, mEngineType);//这就是我的语音转换初始化和事件的封装类
		sRecognizer = speechService.initIflytek();//语音识别器,OnDestroy(),和OnResume()事件中需要用到
	}

	// private String SignType;// 签到类型

	private void parseIntent() {
	}

	private RelativeLayout rl_audio_layout;

	private void initViews() {

		title = (TextView) findViewById(R.id.title);
		title.setText("促销活动");
		rl_audio_layout = (RelativeLayout) findViewById(R.id.rl_audio_layout);
//		 rl_audio_layout.setVisibility(View.GONE);//影藏布局

		mBtnBack = (ImageView) findViewById(R.id.iv_back);
		btn_submit = (Button) findViewById(R.id.btn_submit);
		
		et_remark = (EditText) findViewById(R.id.etxt_abnormal_remark);
		
		btn_audio = (Button) findViewById(R.id.btn_abnormal_audio);
		
		rl_audio = (RelativeLayout) findViewById(R.id.rl_abnormal_audio_del);
		
		m_tv_word = (TextView) findViewById(R.id.tv_rest_word);
		
	}

	private void initListeners() {
		mBtnBack.setOnClickListener(listener);
		
		btn_audio.setOnClickListener(listener);
		btn_audio.setOnLongClickListener(this);//长按按钮进入语音模式选择界面
		
		btn_submit.setOnClickListener(listener);
		
		et_remark.addTextChangedListener(new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence arg0, int arg1, int arg2,
					int arg3) {
			}

			@Override
			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {
			}

			@Override
			public void afterTextChanged(Editable editable) {
				m_tv_word.setText(String.valueOf(m_total_count
						- editable.toString().length()));
			}
		});
	}

	
	
	private SpeechService speechService;

	private void initData() {
		
	}
	
	private OnClickListener listener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			Intent intent;
			switch (v.getId()) {
			case R.id.btn_abnormal_audio:
				speechService.doIflytek(et_remark, mEngineType);//这里来触发语音识别事件
				break;//此方法我返回了录音文件路径,可作为扩展的语音播放功能的文件来源
			case R.id.iv_back:
				SalesActiveActivity.this.finish();
				break;
										
			}
		}

	};

	@SuppressLint("NewApi")
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			
			case REQUEST_CODE_VOICE_MODE:
				int datas = data.getIntExtra("VoiceMode", -1);
				switch (datas) {
				case 0:
					mEngineType = SpeechConstant.TYPE_CLOUD;//在线模式
					break;
				case 1:
					mEngineType = SpeechConstant.TYPE_LOCAL;//本地模式
					if (!SpeechUtility.getUtility().checkServiceInstalled()) {
						mInstaller.install();
					} else {
						String result = FucUtil.checkLocalResource();
						if (!TextUtils.isEmpty(result)) {
							showMessage(result);
						}
					}
					break;
				case 2:
					mEngineType = SpeechConstant.TYPE_MIX;//混合模式
					if (!SpeechUtility.getUtility().checkServiceInstalled()) {
						mInstaller.install();
					} else {
						String result = FucUtil.checkLocalResource();
						if (!TextUtils.isEmpty(result)) {
							showMessage(result);
						}
					}
					break;

				}
				break;
			}
		}
	}


	@Override
	public void finish() {
		// TODO Auto-generated method stub
		super.finishWithAnimation(R.anim.start_activity_out2,
				R.anim.finish_activity_out2);
	}
	

	@Override
	protected void onDestroy() {
		super.onDestroy();
		// 退出时释放连接
		sRecognizer.cancel();
		sRecognizer.destroy();
	}

	@Override
	protected void onResume() {
		// 开放统计 移动数据统计分析
		FlowerCollector.onResume(SalesActiveActivity.this);
		FlowerCollector.onPageStart(TAG);
		super.onResume();
	}

	@Override
	protected void onPause() {
		// 开放统计 移动数据统计分析
		FlowerCollector.onPageEnd(TAG);
		FlowerCollector.onPause(SalesActiveActivity.this);
		super.onPause();
	}

	@Override
	public boolean onLongClick(View v) {//我把设置语音识别模式放到外部,做了一个单独的activity
		// TODO Auto-generated method stub
		Intent intent = new Intent(SalesActiveActivity.this,
				VoiceModeActivity.class);
		int mode = -1;
		if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
			mode = 0;
		}
		if (mEngineType.equals(SpeechConstant.TYPE_LOCAL)) {
			mode = 1;
		}
		if (mEngineType.equals(SpeechConstant.TYPE_MIX)) {
			mode = 2;
		}
		intent.putExtra("VoiceMode", mode);
		startActivityForResult(intent, REQUEST_CODE_VOICE_MODE);
		return false;
	}

	private final int REQUEST_CODE_VOICE_MODE = 10;
}
再把语音模式设置activity代码贴上:

package com.android.action.app.iflytek.setting;

import android.content.Intent;

import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.android.ydsanbu.app.R;
import com.android.ydsanbu.app.activity.BaseActivity;
import com.android.ydsanbu.app.iflytek.setting.IatSettings;

public class VoiceModeActivity extends BaseActivity implements OnClickListener,
		OnCheckedChangeListener {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);

		setView();
		initView();
		initData();
		initListener();
	}

	private LinearLayout lltt;
	private ImageView iv_back;
	private TextView tv_tt;

	private void setView() {
		// TODO Auto-generated method stub
		setContentView(R.layout.activity_voice_mode);
		lltt = (LinearLayout) findViewById(R.id.ll_tittle);

		iv_back = (ImageView) lltt.findViewById(R.id.iv_tittle_back);
		tv_tt = (TextView) lltt.findViewById(R.id.tv_title_text);
		tv_tt.setText("语音模式选择");
	}

	private RadioGroup rd_group;

	private void initView() {
		// TODO Auto-generated method stub
		rd_group = (RadioGroup) findViewById(R.id.radioGroup);
		rd_cloud = (RadioButton) findViewById(R.id.iatRadioCloud);
		rd_local = (RadioButton) findViewById(R.id.iatRadioLocal);
		rd_mix = (RadioButton) findViewById(R.id.iatRadioMix);
	}

	private int mode;
	private RadioButton rd_cloud;
	private RadioButton rd_local;
	private RadioButton rd_mix;

	private void initData() {
		mode = getIntent().getIntExtra("VoiceMode", 0);
		switch (mode) {
		case 0:
			rd_cloud.setChecked(true);
			break;
		case 1:
			rd_local.setChecked(true);
			break;
		case 2:
			rd_mix.setChecked(true);
			break;

		default:
			break;
		}
	}

	private void initListener() {
		// TODO Auto-generated method stub
		iv_back.setOnClickListener(this);
		rd_group.setOnCheckedChangeListener(this);
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.iv_tittle_back:
			Intent intent = new Intent();
			intent.putExtra("VoiceMode", checkedId);
			setResult(RESULT_OK, intent);
			onBackPressed();
			break;

		default:
			break;
		}
	}

	private int checkedId;// 语音模式

	@Override
	public void onCheckedChanged(RadioGroup group, int checkedId) {
		// TODO Auto-generated method stub

		switch (checkedId) {
		case R.id.iatRadioCloud://在线模式
			this.checkedId = 0;
			break;
		case R.id.iatRadioLocal://本地模式
			this.checkedId = 1;
			break;
		case R.id.iatRadioMix://混合模式
			this.checkedId = 2;
			break;

		}
		Intent intent = new Intent();
		intent.putExtra("VoiceMode", this.checkedId);
		setResult(RESULT_OK, intent);
		onBackPressed();
	}
}



      

你可能感兴趣的:(关键代码,原创,图片)