蓝牙 讯飞语音识别_语音识别加蓝牙控制 - CSDN
  • 语音识别,肯定是用讯飞的 ,但是项目的的声音来源不是手机 ,是蓝牙耳机 ,也是第一次接手这样的项目,有点蒙蔽了,去网上找了一圈 这个仁兄的代码,给了很大的帮助  原文地址:...

    最近在做一个翻译戒指的项目 ,里面有语音识别,然后拿到识别的文字去翻译内容

    语音识别,肯定是用讯飞的 ,但是项目的的声音来源不是手机 ,是蓝牙耳机 ,也是第一次接手这样的项目,有点蒙蔽了,去网上找了一圈

    这个仁兄的代码,给了很大的帮助

     原文地址:http://blog.csdn.net/ec_boy_hl/article/details/45112493

    按照他的方向 ,我写了一个demo,来测试,妥妥的 能采集到声音,实现语音识别 ,分享给大家 


    重点的代码 :

      在识别的时候,设置声音来源从蓝牙

     mAudioManager.setBluetoothScoOn(true);
    mAudioManager.startBluetoothSco();


    识别完之后关闭(经测试,不关也可以)

    mAudioManager.setBluetoothScoOn(false);
    mAudioManager.stopBluetoothSco();



    整体代码就不全部贴了 ,下面就是讯飞的官方demo, 加上上面的两段话就OK 了,是不是很简单 ,

    相关的权限,注意权限,不然没法使用

     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
        <uses-permission android:name="android.permission.BROADCAST_STICKY" />
        <uses-permission android:name="android.permission.BLUETOOTH" />
        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <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.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.READ_CONTACTS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    

    主题的代码

    package com.iflytek.voicedemo;
    
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.SharedPreferences;
    import android.media.AudioManager;
    import android.os.Bundle;
    import android.os.Environment;
    import android.text.TextUtils;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.Window;
    import android.widget.EditText;
    import android.widget.RadioGroup;
    import android.widget.RadioGroup.OnCheckedChangeListener;
    import android.widget.Toast;
    
    import com.iflytek.cloud.ErrorCode;
    import com.iflytek.cloud.InitListener;
    import com.iflytek.cloud.LexiconListener;
    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.SpeechUtility;
    import com.iflytek.cloud.ui.RecognizerDialog;
    import com.iflytek.cloud.ui.RecognizerDialogListener;
    import com.iflytek.cloud.util.ContactManager;
    import com.iflytek.cloud.util.ContactManager.ContactListener;
    import com.iflytek.speech.setting.IatSettings;
    import com.iflytek.speech.util.ApkInstaller;
    import com.iflytek.speech.util.FucUtil;
    import com.iflytek.speech.util.JsonParser;
    import com.iflytek.sunflower.FlowerCollector;
    
    public class IatDemo extends Activity implements OnClickListener {
    	private static String TAG = IatDemo.class.getSimpleName();
    	// 语音听写对象
    	private SpeechRecognizer mIat;
    	// 语音听写UI
    	private RecognizerDialog mIatDialog;
    	// 用HashMap存储听写结果
    	private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
    
    	private EditText mResultText;
    	private Toast mToast;
    	private SharedPreferences mSharedPreferences;
    	// 引擎类型
    	private String mEngineType = SpeechConstant.TYPE_CLOUD;
    
    	private boolean mTranslateEnable = false;
    
    	private BroadcastReceiver receiver = new BroadcastReceiver() {
    
    		@Override
    		public void onReceive(Context arg0, Intent intent) {
    			String action = intent.getAction();
    			if (action.equals("android.intent.action.VOICE_COMMAND")) {
    				Log.i("main", "======你点击了按钮");
    			}
    		}
    	};
    
    	@SuppressLint("ShowToast")
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		requestWindowFeature(Window.FEATURE_NO_TITLE);
    		setContentView(R.layout.iatdemo);
    		initReceiver();
    		initLayout();
    		mIat = SpeechRecognizer.createRecognizer(IatDemo.this, mInitListener);
    		mIatDialog = new RecognizerDialog(IatDemo.this, mInitListener);
    
    		mSharedPreferences = getSharedPreferences(IatSettings.PREFER_NAME,
    				Activity.MODE_PRIVATE);
    		mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
    		mResultText = ((EditText) findViewById(R.id.iat_text));
    	}
    
    	private void initReceiver() {
    		IntentFilter filter = new IntentFilter();
    		filter.addAction("android.intent.action.VOICE_COMMAND");
    		registerReceiver(receiver, filter);
    	}
    
    	/**
    	 * 初始化Layout。
    	 */
    	AudioManager mAudioManager;
    
    	private void initLayout() {
    		mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    		findViewById(R.id.iat_recognize).setOnClickListener(IatDemo.this);
    		findViewById(R.id.iat_recognize_stream)
    				.setOnClickListener(IatDemo.this);
    		findViewById(R.id.iat_stop).setOnClickListener(IatDemo.this);
    		findViewById(R.id.iat_cancel).setOnClickListener(IatDemo.this);
    		findViewById(R.id.btn_test).setOnClickListener(IatDemo.this);
    	}
    
    	int ret = 0; // 函数调用返回值
    
    	@Override
    	public void onClick(View view) {
    		if (null == mIat) {
    			this.showTip("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");
    			return;
    		}
    
    		switch (view.getId()) {
    		case R.id.iat_recognize:
    			mAudioManager.setBluetoothScoOn(true);
    			mAudioManager.startBluetoothSco();
    
    			// 移动数据分析,收集开始听写事件
    			mResultText.setText(null);// 清空显示内容
    			mIatResults.clear();
    			// 设置参数
    			setParam();
    			boolean isShowDialog = mSharedPreferences.getBoolean(
    					getString(R.string.pref_key_iat_show), true);
    			if (isShowDialog) {
    				// 显示听写对话框
    				mIatDialog.setListener(mRecognizerDialogListener);
    				mIatDialog.show();
    				showTip(getString(R.string.text_begin));
    			} else {
    				// 不显示听写对话框
    				ret = mIat.startListening(mRecognizerListener);
    				if (ret != ErrorCode.SUCCESS) {
    					showTip("听写失败,错误码:" + ret);
    				} else {
    					showTip(getString(R.string.text_begin));
    				}
    			}
    			break;
    
    		case R.id.btn_test:
    			mResultText.setText(null);// 清空显示内容
    			mIatResults.clear();
    			// 设置参数
    			setParam();
    			// 设置音频来源为外部文件
    			// mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
    			// 也可以像以下这样直接设置音频文件路径识别(要求设置文件在sdcard上的全路径):
    			mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-2");
    			mIat.setParameter(SpeechConstant.ASR_SOURCE_PATH,
    					"sdcard/record.pcm");
    			ret = mIat.startListening(mRecognizerListener);
    			if (ret != ErrorCode.SUCCESS) {
    				showTip("识别失败,错误码:" + ret);
    			} else {
    				byte[] audioData = FucUtil.readAudioFile(IatDemo.this,
    						"iattest.wav");
    				Log.i("main", "====获取的数据流===" + audioData.length);
    				if (null != audioData) {
    					showTip(getString(R.string.text_begin_recognizer));
    					// 一次(也可以分多次)写入音频文件数据,数据格式必须是采样率为8KHz或16KHz(本地识别只支持16K采样率,云端都支持),位长16bit,单声道的wav或者pcm
    					// 写入8KHz采样的音频时,必须先调用setParameter(SpeechConstant.SAMPLE_RATE,
    					// "8000")设置正确的采样率
    					// 注:当音频过长,静音部分时长超过VAD_EOS将导致静音后面部分不能识别。
    					// 音频切分方法:FucUtil.splitBuffer(byte[] buffer,int length,int
    					// spsize);
    					mIat.writeAudio(audioData, 0, audioData.length);
    					mIat.stopListening();
    				} else {
    					mIat.cancel();
    					showTip("读取音频流失败");
    				}
    			}
    			break;
    		// 音频流识别
    		case R.id.iat_recognize_stream:
    			mResultText.setText(null);// 清空显示内容
    			mIatResults.clear();
    			// 设置参数
    			setParam();
    			// 设置音频来源为外部文件
    			mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
    			// 也可以像以下这样直接设置音频文件路径识别(要求设置文件在sdcard上的全路径):
    			// mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-2");
    			// mIat.setParameter(SpeechConstant.ASR_SOURCE_PATH,
    			// "sdcard/record.pcm");
    			ret = mIat.startListening(mRecognizerListener);
    			if (ret != ErrorCode.SUCCESS) {
    				showTip("识别失败,错误码:" + ret);
    			} else {
    				// byte[] audioData = FucUtil.readAudioFile(IatDemo.this,
    				// "record.wav");
    				byte[] audioData = FucUtil.readSdFile(IatDemo.this);
    				Log.i("main", "====获取的数据流===" + audioData.length);
    				if (null != audioData) {
    					showTip(getString(R.string.text_begin_recognizer));
    					// 一次(也可以分多次)写入音频文件数据,数据格式必须是采样率为8KHz或16KHz(本地识别只支持16K采样率,云端都支持),位长16bit,单声道的wav或者pcm
    					// 写入8KHz采样的音频时,必须先调用setParameter(SpeechConstant.SAMPLE_RATE,
    					// "8000")设置正确的采样率
    					// 注:当音频过长,静音部分时长超过VAD_EOS将导致静音后面部分不能识别。
    					// 音频切分方法:FucUtil.splitBuffer(byte[] buffer,int length,int
    					// spsize);
    					mIat.setParameter(SpeechConstant.VAD_BOS, "4000");
    					mIat.setParameter(SpeechConstant.VAD_EOS, "4000");
    					mIat.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
    					mIat.writeAudio(audioData, 0, audioData.length);
    					mIat.stopListening();
    				} else {
    					mIat.cancel();
    					showTip("读取音频流失败");
    				}
    			}
    			break;
    		// 停止听写
    		case R.id.iat_stop:
    			mIat.stopListening();
    			showTip("停止听写");
    			break;
    		// 取消听写
    		case R.id.iat_cancel:
    
    			mAudioManager.setBluetoothScoOn(false);
    			mAudioManager.stopBluetoothSco();
    			mIat.cancel();
    			showTip("取消听写");
    			break;
    		default:
    			break;
    		}
    	}
    
    	/**
    	 * 初始化监听器。
    	 */
    	private InitListener mInitListener = new InitListener() {
    
    		@Override
    		public void onInit(int code) {
    			Log.d(TAG, "SpeechRecognizer init() code = " + code);
    			if (code != ErrorCode.SUCCESS) {
    				showTip("初始化失败,错误码:" + code);
    			}
    		}
    	};
    
    	/**
    	 * 上传联系人/词表监听器。
    	 */
    	private LexiconListener mLexiconListener = new LexiconListener() {
    
    		@Override
    		public void onLexiconUpdated(String lexiconId, SpeechError error) {
    			if (error != null) {
    				showTip(error.toString());
    			} else {
    				showTip(getString(R.string.text_upload_success));
    			}
    		}
    	};
    
    	/**
    	 * 听写监听器。
    	 */
    	private RecognizerListener mRecognizerListener = new RecognizerListener() {
    
    		@Override
    		public void onBeginOfSpeech() {
    			// 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
    			showTip("开始说话");
    		}
    
    		@Override
    		public void onError(SpeechError error) {
    			// Tips:
    			// 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
    			// 如果使用本地功能(语记)需要提示用户开启语记的录音权限。
    			if (mTranslateEnable && error.getErrorCode() == 14002) {
    				showTip(error.getPlainDescription(true) + "\n请确认是否已开通翻译功能");
    			} else {
    				showTip(error.getPlainDescription(true));
    			}
    		}
    
    		@Override
    		public void onEndOfSpeech() {
    			// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
    			showTip("结束说话");
    		}
    
    		@Override
    		public void onResult(RecognizerResult results, boolean isLast) {
    			Log.d(TAG, results.getResultString());
    			if (mTranslateEnable) {
    				printTransResult(results);
    			} else {
    				printResult(results);
    			}
    
    			if (isLast) {
    				// TODO 最后的结果
    			}
    		}
    
    		@Override
    		public void onVolumeChanged(int volume, byte[] data) {
    			showTip("当前正在说话,音量大小:" + volume);
    			Log.d(TAG, "返回音频数据:" + 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);
    			// }
    		}
    	};
    
    	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));
    		}
    
    		mResultText.setText(resultBuffer.toString());
    		mResultText.setSelection(mResultText.length());
    	}
    
    	/**
    	 * 听写UI监听器
    	 */
    	private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
    		public void onResult(RecognizerResult results, boolean isLast) {
    			if (mTranslateEnable) {
    				printTransResult(results);
    			} else {
    				printResult(results);
    			}
    
    		}
    
    		/**
    		 * 识别回调错误.
    		 */
    		public void onError(SpeechError error) {
    			if (mTranslateEnable && error.getErrorCode() == 14002) {
    				showTip(error.getPlainDescription(true) + "\n请确认是否已开通翻译功能");
    			} else {
    				showTip(error.getPlainDescription(true));
    			}
    		}
    
    	};
    
    	/**
    	 * 获取联系人监听器。
    	 */
    	private ContactListener mContactListener = new ContactListener() {
    
    		@Override
    		public void onContactQueryFinish(final String contactInfos,
    				boolean changeFlag) {
    			// 注:实际应用中除第一次上传之外,之后应该通过changeFlag判断是否需要上传,否则会造成不必要的流量.
    			// 每当联系人发生变化,该接口都将会被回调,可通过ContactManager.destroy()销毁对象,解除回调。
    			// if(changeFlag) {
    			// 指定引擎类型
    			runOnUiThread(new Runnable() {
    				public void run() {
    					mResultText.setText(contactInfos);
    				}
    			});
    
    			mIat.setParameter(SpeechConstant.ENGINE_TYPE,
    					SpeechConstant.TYPE_CLOUD);
    			mIat.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");
    			ret = mIat.updateLexicon("contact", contactInfos, mLexiconListener);
    			if (ret != ErrorCode.SUCCESS) {
    				showTip("上传联系人失败:" + ret);
    			}
    		}
    	};
    
    	private void showTip(final String str) {
    		mToast.setText(str);
    		mToast.show();
    	}
    
    	/**
    	 * 参数设置
    	 * 
    	 * @param param
    	 * @return
    	 */
    	public void setParam() {
    		// 清空参数
    		mIat.setParameter(SpeechConstant.PARAMS, null);
    
    		// 设置听写引擎
    		mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
    		// 设置返回结果格式
    		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");
    	}
    
    	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 {
    			mResultText.setText("原始语言:\n" + oris + "\n目标语言:\n" + trans);
    		}
    
    	}
    
    	@Override
    	protected void onDestroy() {
    		super.onDestroy();
    		if (null != mIat) {
    			mIat.cancel();
    			mIat.destroy();
    		}
    		unregisterReceiver(receiver);
    	}
    
    }
    














    展开全文
  • 近阶段在开发一款app,实现通过蓝牙耳机进行讯飞语音识别,获取识别结果之后再通过语音合成从蓝牙耳机播报出识别结果。上网也查了很多资料,大多是说通过一下两行代码: mAudioManager.setBluetoothScoOn(true); ...
    近阶段在开发一款app,实现通过蓝牙耳机进行讯飞语音识别,获取识别结果之后再通过语音合成从蓝牙耳机播报出识别结果。上网也查了很多资料,大多是说通过一下两行代码:      mAudioManager.setBluetoothScoOn(true);                           mAudioManager.startBluetoothSco();
    来打开蓝牙连接。
    我在自己的代码中也进行了以下修改:


    但是,奇怪的是,现在倒是可以通过蓝牙耳机进行语音识别了,但是语音合成结果播报却还是通过手机播放器播放的。请问,怎么修改才能使语音识别和合成播放都通过蓝牙耳机啊?看到的各位同志请指点一下吧,谢谢了。
    展开全文
  • 本人转来的android代码 android 讯飞语音识别到串口发出舵机协议指令,集成讯飞语音包,识别不同的命令词,根据识别的命令,通过串口发出协议指令给舵机控制板来控制机器人的动作
  • 前段时间写了一个关于百度语音唤醒文章,最近有做了一个讯飞语音的应用,在这里把学习的资料整理一下。 唤醒的整个过程如下: (图源自讯飞官网) 讯飞的语音唤醒功能实现起来挺方便的(相比百度,百度语音...

    前段时间写了一个关于百度语音唤醒文章,最近有做了一个讯飞语音的应用,在这里把学习的资料整理一下。
    唤醒的整个过程如下:
    这里写图片描述(图源自讯飞官网)
    讯飞的语音唤醒功能实现起来挺方便的(相比百度,百度语音Android端的语音唤醒是基于service实现的)百度语音唤醒识别效果对于不建议使用的唤醒词识别较差,而讯飞相对较容易。并且讯飞语音唤醒可以自己设定很多参数,来提高识别率,百度提供给用户的设置接口很少。俗话说“鱼和熊掌不可兼得”,一句话总结这两个平台就是——百度免费,讯飞收费。
    这里写图片描述
    这里写图片描述
    大家可以根据自己项目的实际需求作抉择。
    下面我们就言归正传:
    我们先来讲一讲讯飞语音唤醒的参数设置。下面是讯飞官方文档的内容这里写图片描述
    唤醒业务类型,分为如下几种:
    唤醒:wakeup;(单唤醒词,多唤醒词,或特定人唤醒)
    注册:enroll;(特定人唤醒注册,又称为“训练”,用于特定人唤醒时,注册用户唤醒词)
    唤醒识别:oneshot;

    唤醒门限值:
    格式:id:门限值;* (*代表可多个),根据资源携带的唤醒词个数按照“id:门限;id:门限” 的格式传入。门限值越高,则要求匹配度越高,才能唤醒。
    是否必须设置:否
    默认值:0
    值范围:[-150, 150]

    持续唤醒:
    在持续唤醒时,唤醒一次后,当前会话依然继续,录音还在继续,当有匹配的唤醒 时,会返回结果;否则,唤醒一次后,当前会话已结束,录音也结束,不会再监听。
    此参数对唤醒识别不起作用,见IVW_SST。
    是否必须设置:否
    默认值:0
    值范围:{null, 0, 1}

    唤醒资源路径:
    唤醒需要使用本地资源,通过此参数设置本地资源所在的路径。多个资源间,以英文分号”;”分隔。 与IVW_ENROLL_RES_PATH一样,用于使用的资源,需要通过 ResourceUtil.generateResourcePath(Context, com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE, java.lang.String)生成标准的资源路径值。 请参考 ResourceUtil.generateResourcePath(Context, com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE, java.lang.String)。
    是否必须设置:是(在非注册时)
    默认值:null
    值范围:有效的资源文件路径

    引擎类型:
    设置使用的引擎类型:在线、离线、混合。在申请了离线合成资源和权限, 或使用语记方式时,可以选择使用本地或在线的方式进行语音服务。使用在线模式(又称云端模式)时,需要使用网络,产生一定流量,但有更好的识别 或合成的效果,如更高的识别匹配度,更多的发音人等。使用离线模式(又称本地模式)时,不需要使用网络,且识别和合成的速度更快,但同 时要求使用对应的离线资源或安装“语记”(安卓或iOS平台)。在混合模式时,可以通过混合类型、 云端超时、本地置信门限 使用对应的策略,提高识别准确度与成功率。详情参见前面的几个参数说明。
    在离线或混合模式下,需要设置对应的资源。请参考
    合成资源路径:ResourceUtil.TTS_RES_PATH;
    识别资源路径:ResourceUtil.ASR_RES_PATH;
    唤醒资源路径:IVW_RES_PATH;
    关于离线资源的其他介绍,参考ResourceUtil类的说明。
    是否必须设置:否
    默认值:”cloud”
    值范围:{ “cloud”, “local”,”mixed” }

    讯飞 语音唤醒实现起来相当简单,具体步骤如下

    • 申请账号

    首先需要去讯飞开放平台申请一个账号,之后注册一个自己的应用,这里我们以Android端为例来说明。对于第一次使用讯飞语音的人,首先先要创建一个应用
    这里写图片描述

    • 开通服务

    大家可以根据自己的实际需求开通相应的服务。
    这里写图片描述
    这里大家一定要记住Appid很重要,这就相当于你应用的身份证号码。

    • 下载SDK

    下载分为组合下载和单个服务SDK下载
    这里写图片描述

    • 文件拷贝

    我们下载的SDK正常情况下为
    这里写图片描述
    assets文件夹下面主要是讯飞语音的一些界面图标,如果你需要使用讯飞的语音输入界面,可以将这个文件夹下面的内容拷贝到你相应的Android工程目录下。doc下面为文档libs下面使我们需要的.so文件和jar文件,libs下面有不同cpu下的so文件,不同的cpu平台需要不同的so文件,这里面的so文件是使用c/c++写的,根据需求自己选择,并将相应的文件拷贝到自己的Android工程对应的目录下。如果Android工程中没有libs目录,需要我们自己创建一个目录。res下面是一些讯飞语音的资源文件,需要将这些文件拷贝到自己Android工程的assets文件中,res中的ivw文件为唤醒词的资源文件。sample文件是一个demo工程,大家可以参考demo完成自己的功能需求。

    • 代码实现

    代码实现之前我们还需要添加一些权限,Android6.0以及之后的版本需要动态申请权限,这里大家自行学习,我不在赘述。
    在AndroidManifest.xml文件中添加如下权限

        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <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.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.READ_CONTACTS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    在代码实现过程中,首先我们需要初始化讯飞语音,代码如下:

         /**
          * 初始化讯飞语音
          */
         private void initializeIflytek()
         {
            StringBuffer param = new StringBuffer();
            //IflytekAPP_id为我们申请的Appid
            param.append("appid="+getString(R.string.IflytekAPP_id));
            param.append(",");
            // 设置使用v5+
            param.append(SpeechConstant.ENGINE_MODE+"="+SpeechConstant.MODE_MSC);
            SpeechUtility.createUtility(DWEApplication.this, param.toString());
         }

    初始化最好放在APP初始化阶段,也就是所继承Application类,然后把讯飞初始化的内容放到该类里面。

    前面说的内容适合于讯飞的所有语音产品,下面我讲给出讯飞语音唤醒的代码实现。

    import org.json.JSONException;
    import org.json.JSONObject;
    import com.iflytek.cloud.SpeechConstant;
    import com.iflytek.cloud.SpeechError;
    import com.iflytek.cloud.VoiceWakeuper;
    import com.iflytek.cloud.WakeuperListener;
    import com.iflytek.cloud.WakeuperResult;
    import com.iflytek.cloud.util.ResourceUtil;
    import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    /**
     * 讯飞语音唤醒
     * @author Administrator
     *
     */
    public class IflytekWakeUp {
    
        private Context mContext;
        //唤醒的阈值,就相当于门限值,当用户输入的语音的置信度大于这一个值的时候,才被认定为成功唤醒。
        private int curThresh = 10;
        //是否持续唤醒
        private String keep_alive = "1";
        /**
          * 闭环优化网络模式有三种:
          * 模式0:关闭闭环优化功能
          * 
          * 模式1:开启闭环优化功能,允许上传优化数据。需开发者自行管理优化资源。
          * sdk提供相应的查询和下载接口,请开发者参考API文档,具体使用请参考本示例
          * queryResource及downloadResource方法;
          * 
          * 模式2:开启闭环优化功能,允许上传优化数据及启动唤醒时进行资源查询下载;
          * 本示例为方便开发者使用仅展示模式0和模式2;
         */
        private String ivwNetMode = "0";
        // 语音唤醒对象
        private VoiceWakeuper mIvw;
        //存储唤醒词的ID
        private String wordID = "";
    
        public IflytekWakeUp(Context context)
        {
            this.mContext = context;
            // 初始化唤醒对象
            mIvw = VoiceWakeuper.createWakeuper(mContext, null);
        }
        /**
         * 开启唤醒功能
         */
        public void startWakeuper()
        {
            //非空判断,防止因空指针使程序崩溃
            mIvw = VoiceWakeuper.getWakeuper();
            if(mIvw != null) {
                // 清空参数
                mIvw.setParameter(SpeechConstant.PARAMS, null);
                // 唤醒门限值,根据资源携带的唤醒词个数按照“id:门限;id:门限”的格式传入
                mIvw.setParameter(SpeechConstant.IVW_THRESHOLD, "0:"+ curThresh);
                // 设置唤醒模式
                mIvw.setParameter(SpeechConstant.IVW_SST, "wakeup");
                // 设置持续进行唤醒
                mIvw.setParameter(SpeechConstant.KEEP_ALIVE, keep_alive);
                // 设置闭环优化网络模式
                mIvw.setParameter(SpeechConstant.IVW_NET_MODE, ivwNetMode);
                // 设置唤醒资源路径
                mIvw.setParameter(SpeechConstant.IVW_RES_PATH, getResource());
                // 设置唤醒录音保存路径,保存最近一分钟的音频
                mIvw.setParameter( SpeechConstant.IVW_AUDIO_PATH, Environment.getExternalStorageDirectory().getPath()+"/msc/ivw.wav" );
                mIvw.setParameter( SpeechConstant.AUDIO_FORMAT, "wav" );
                // 如有需要,设置 NOTIFY_RECORD_DATA 以实时通过 onEvent 返回录音音频流字节
                //mIvw.setParameter( SpeechConstant.NOTIFY_RECORD_DATA, "1" );
    
                // 启动唤醒
                mIvw.startListening(new MyWakeuperListener());
            }
        }
        /**
         * 获取唤醒词功能
         * @return 返回文件位置
         */
        private String getResource() {
            final String resPath = ResourceUtil.generateResourcePath(mContext, RESOURCE_TYPE.assets, "ivw/"+mContext.getString(R.string.IflytekAPP_id)+".jet");
            return resPath;
        }
    
        /**
         * 销毁唤醒功能
         */
        public void destroyWakeuper()
        {
            // 销毁合成对象
            mIvw = VoiceWakeuper.getWakeuper();
            if (mIvw != null) {
                mIvw.destroy();
            }
        }
        /**
         * 停止唤醒
         */
        public void stopWakeuper()
        {
            mIvw.stopListening();
        }
    
        /**
         * 唤醒词监听类
         * @author Administrator
         *
         */
        private class MyWakeuperListener implements WakeuperListener
        {
            //开始说话
            @Override
            public void onBeginOfSpeech() {
    
            }
            //错误码返回
            @Override
            public void onError(SpeechError arg0) {
    
            }
    
            @Override
            public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {
    
            }
    
            @Override
            public void onResult(WakeuperResult result) {
    
                if(!"1".equalsIgnoreCase(keep_alive)) {
                    //setRadioEnable(true);
                }
                try {
                    String text = result.getResultString();
                    JSONObject object;
                    object = new JSONObject(text);
                    StringBuffer buffer = new StringBuffer();
                    buffer.append("【RAW】 "+text);
                    buffer.append("\n");
                    buffer.append("【操作类型】"+ object.optString("sst"));
                    buffer.append("\n");
                    buffer.append("【唤醒词id】"+ object.optString("id"));
                    buffer.append("\n");
                    buffer.append("【得分】" + object.optString("score"));
                    buffer.append("\n");
                    buffer.append("【前端点】" + object.optString("bos"));
                    buffer.append("\n");
                    buffer.append("【尾端点】" + object.optString("eos"));
                    resultString =buffer.toString();
                } catch (JSONException e) {
                    e.printStackTrace();
            }
            /**
             *声音改变回调
            */
            @Override
            public void onVolumeChanged(int arg0) {
    
            }
        }
    }
    

    讯飞语音唤醒大体实现过程就是如上所述,其他功能也类似。我这里知识简单的实现了一下,语音唤醒里面还有其他方法,我把文档截图放在这里,大几可以参考一下。
    这里写图片描述
    这里写图片描述

    原创文章不容易,转载请注明出处!!Thank you!

    (昨天晚上写到凌晨,今天总算把后面的内容写完了,这样一来总算把国内做语音唤醒的比较好的平台介绍完了,今天放五一假,是不是应该出去走走呢?)

    展开全文
  • 语音识别的选择前面我们准备好了BlueZ stack, 接下来就需要准备语音识别库了。对于语音识别,国内主要的提供商有:科大讯飞图灵机器人思必驰信息科技有限公司北京捷通华声科技股份有限公司百度语音北京云知声信息...

    语音识别的选择
    前面我们准备好了BlueZ stack, 接下来就需要准备语音识别库了。对于语音识别,国内主要的提供商有:

    • 科大讯飞
    • 图灵机器人
    • 思必驰信息科技有限公司
    • 北京捷通华声科技股份有限公司
    • 百度语音
    • 北京云知声信息技术有限公司
    • 哦啦语音


    但是,我们是在ARM Cortex-A7单核上面跑,平台为ARM Linux,而且我们不准备跑python,而是使用C/C++, python脚本写代码会很快,但是效率较低,在这里可能不那么合适。
    同时,考虑到我们需要从BlueZ那边获取音频,且音频数据量不小,为了有更好的体验,所以用C/C++会较好。


    国内提到语音识别,那么大家会很可能马上想打的是科大讯飞,但是科大讯飞最新的Linux SDK库,里面有各prebuilt shared library,这个shared library只提供了x86和x64的版本,无法在ARM Cortex-A7平台使用。当然,我们也可以使用旧版本泄漏出来的,大家都用在树莓派上面的版本,但是毕竟现在官方不再释放出来,我们就选择其他的好了。

    稍微对比了一下,决定选用百度的语音识别。
    百度语音号称基础服务永久免费,且支持全平台的API:

    使用百度SDK
    我们直接创建一个应用

    选择和现在SDK



    我们查看一下依赖的头文件和库



    下面是库文件,这些库文件我们无法使用,需要编译arm版本的


    编译libcrypto-cpp
    扫了一眼,我们需要自己来写recipe的只有libcrypto-cpp,即最后一个。其他的包在Yocto中直接就有,编译就可以了。
    而libcrypto-cpp在github上面可以找到一个:



    这个recipe需要更改一下,就是install中的ln,同时也需要将版本改成更高的版本。
    然后直接bitbake编译即可:

    得到的lib库如下:



    编译百度sdk例子
    编译完所有的依赖库后,直接就用devshell来编译:


    注意里面我们需要使用$CXX,而不是arm-poky-gnueabi-g++, 这个在我以前的Yocto Tips专栏(https://blog.csdn.net/column/details/yocto.html)有提及。


    然后接下来我们将在后面的章节中测试,而这需要我们准备好蓝牙语音遥控器,因此我们将需要先说明一下遥控器。下次继续。

    展开全文
  • 讯飞语音--唤醒Demo

    2018-03-02 10:31:45
    这时,拿手机那哥们回了男子一个尴尬而不失礼貌的微笑,哈哈所以我想起讯飞语音,就试着写了一下语音唤醒的Demo, 也借鉴了很多前辈的博客, 就不一一列举了,各位不喜勿喷接下来进入正题,首先在讯飞官网下载对应的SD...
  • 之前已经设计了一款app,实现了讯飞语音的语音听写接口,功能正常。但是不久之后,我在此这个app的基础上,修改一些别的逻辑,包装成第二个app,只是把一些表现给用户的部分修改了,比如:名称,图片,布局啥的。...
  • 功能描述  语音听写和语音合成都是较为基础也是最常使用的两个基本功能。  语音合成是将文本转化为语音说出来,就是读文章。  语音听写是什么呢?  开启或者说触发语音听写的功能,我
  • 科大讯飞语音识别demo

    2020-07-29 14:18:24
    基于科大讯飞平台android-sdk的语音识别demo。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
  • 最近项目原因需要我完成一个在树莓派上的离线语音识别,忙活了近一周,起初用了开源的PocketSphinx,但是不得不说,识别率低的惊人,甚至可以说有些字词根本没法识别,除非你自己制作声学模型,不然这玩意儿就是个...
  • 第一步 导入jar SDK 下载地址 http://www.xfyun.cn/ 先创建...第二步 导入所需权限<!--连接网络权限,用于执行云端语音能力 --> <!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 --> <uses-permi
  • 一直想研究一下语音识别,用来做家庭物联网的控制入口,未来也许就是这样,讯飞的叮咚音响可以连接京东的物联平台,苹果的homekit平台,华为的平台暂时落后的有点多... 国内语音识别领域,我个人比较欣赏讯飞.识别效果业界...
  • 自己的这个是毕业设计的一部分,用来控制小灯亮灭的程序,过程是对手机APP将一句话,然后通过蓝牙传送到arduino中,再由arduino控制外接的LED和步进电机,进行预期的动作。
  • 因为最近项目需要,需要集成语音识别的功能,这里记录下科大讯飞语音识别的集成和使用,也方便其它小伙伴参考,如果哪里有问题,可以提出来以便改正。 一、准备工作 1、注册一个讯飞开放平台账号,官网...
  • 我之前发过我的贪吃蛇的代码,我想把它变成语音控制上下左右的,于是选择科大讯飞的SDK,官方有一些文档,但有一些细节还是会让在linux下开发的孩子们产生困惑比如我,现在总结在此~  首先下载科大讯飞的SDK-linux...
  • 其中有一个蓝牙耳机下的语音识别问题,比较折腾人,问题描述:1.蓝牙耳机连接下捕获蓝牙按键事件,启动语音识别;2.正常启动识别时也必须通过蓝牙耳机录入音频进行语音识别。本就这两个问题寻求解决办法。
  • 音频流是通过MIC录入的,录入的音频流会经过讯飞模块消除噪音之后,再给到讯飞识别模块,或者给到蓝牙电话等其他应用使用。 首先这里有两种输入模式:外挂模式和顶灯模式。如果是单个麦克风,由于声音能量比较小,...
1 2 3 4 5 ... 7
收藏数 125
精华内容 50
关键字:

蓝牙 讯飞语音识别