百度语音识别、合成项目集成及遇到的一些问题注意

官网:http://yuyin.baidu.com/ 或 http://ai.baidu.com/sdk#tts(建议)

第一步:下载SDK,将demo运行起来,没问题的话在应用管理 | 控制台创建新的应用,绑定包名,开通语音识别和语音合成的服务。

第二步:在工程中添加jar以及so库,raw,assets(有的话)等,记得这个有个坑,就是在上传svn或者其他什么操作时,授权失败,不识别语音了,看下是不是so库丢失了,重新添加下。

这里因为已经用过了语音识别封装了方法,只要在onCreate方法调用该方法即可进行语音识别,这里是没有百度语音识别的UI界面的,结果在onResult方法里,可以自己直接处理或eventbus post出去操作。

下面是方法:

// 语音识别客户端
private SpeechRecognizer speechRecognizer;
    private void initRecognizer() {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this, new ComponentName(this, VoiceRecognitionService.class));
speechRecognizer.setRecognitionListener(new RecognitionListener() {
@Override
public void onReadyForSpeech(Bundle params) {
progressView.start();
status = STATUS_Ready;
print("准备就绪,可以开始说话");
}

@Override
public void onBeginningOfSpeech() {

time = System.currentTimeMillis();
status = STATUS_Speaking;
print("检测到用户的已经开始说话");
Log.e("555555555", "onBeginningOfSpeech: ");
}

@Override
public void onRmsChanged(float rmsdB) {
if (rmsdB < 100) {
rmsdB = 0;
}
if (rmsdB > 900) {
rmsdB = 900;
}
progressView.setVolume((int) (rmsdB / 42f));
Log.e(TAG, "onRmsChanged: " + rmsdB);
}

@Override
public void onBufferReceived(byte[] buffer) {

}

@Override
public void onEndOfSpeech() {
speechEndTime = System.currentTimeMillis();
status = STATUS_Recognition;
print("检测到用户的已经停止说话");
Log.e("555555555", "onEndOfSpeech: ");
}

@Override
public void onError(int error) {
time = 0;
status = STATUS_None;
StringBuilder sb = new StringBuilder();
switch (error) {
case SpeechRecognizer.ERROR_AUDIO:
sb.append("音频问题");
break;
case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
sb.append("没有语音输入");
break;
case SpeechRecognizer.ERROR_CLIENT:
sb.append("其它客户端错误");
break;
case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
sb.append("权限不足");
break;
case SpeechRecognizer.ERROR_NETWORK:
sb.append("网络问题");
break;
case SpeechRecognizer.ERROR_NO_MATCH:
sb.append("没有匹配的识别结果");
break;
case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
sb.append("引擎忙");
break;
case SpeechRecognizer.ERROR_SERVER:
sb.append("服务端错误");
break;
case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
sb.append("连接超时");
break;
}
sb.append(":" + error);
print("识别失败:" + sb.toString());
handlerRecognizer.sendEmptyMessage(0);
}

@Override
public void onResults(Bundle results) {
long end2finish = System.currentTimeMillis() - speechEndTime;
status = STATUS_None;
ArrayList<String> nbest = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
print("识别成功:" + Arrays.toString(nbest.toArray(new String[nbest.size()])));
String json_res = results.getString("origin_result");
try {
print("origin_result=\n" + new JSONObject(json_res).toString(4));
} catch (Exception e) {
print("origin_result=[warning: bad json]\n" + json_res);
}
String strEnd2Finish = "";
if (end2finish < 60 * 1000) {
strEnd2Finish = "(waited " + end2finish + "ms)";
}
//最终结果
// txtResult.setText(nbest.get(0) + strEnd2Finish);
Log.e("111111111111", "onResults: " + nbest.get(0) + strEnd2Finish);
EventBus.getDefault().post(new EventAction(1002, nbest.get(0)));

time = 0;
}

@Override
public void onPartialResults(Bundle partialResults) {
ArrayList<String> nbest = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
if (nbest.size() > 0) {
print("~临时识别结果:" + Arrays.toString(nbest.toArray(new String[0])));
// txtResult.setText(nbest.get(0));
Log.e("111111111111", "onPartialResults: " + nbest.get(0));
}
}

@Override
public void onEvent(int eventType, Bundle params) {
switch (eventType) {
case EVENT_ERROR:
String reason = params.get("reason") + "";
print("EVENT_ERROR, " + reason);
break;
case VoiceRecognitionService.EVENT_ENGINE_SWITCH:
int type = params.getInt("engine_type");
print("*引擎切换至" + (type == 0 ? "在线" : "离线"));
break;
}
}
});
}

第三步:语音合成:和语音识别同样的操作,开通服务,在工程中添加jar和其他so库等,添加完了后,这里也进行了方法封装,只要在onCreate方法里调用该方法就可以开启语音合成。

下面是语音合成的方法:

// 语音合成客户端
private SpeechSynthesizer mSpeechSynthesizer;
// 初始化语音合成客户端并启动
private void initTTS() {
// 获取语音合成对象实例
mSpeechSynthesizer = SpeechSynthesizer.getInstance();
// 设置context
mSpeechSynthesizer.setContext(this);

// 设置语音合成状态监听器
mSpeechSynthesizer.setSpeechSynthesizerListener(new SpeechSynthesizerListener() {
@Override
public void onSynthesizeStart(String s) {
Log.e("444444444", "onSynthesizeStart: ");
}

@Override
public void onSynthesizeDataArrived(String s, byte[] bytes, int i) {
Log.e("444444444", "onSynthesizeDataArrived: ");
}

@Override
public void onSynthesizeFinish(String s) {
Log.e("444444444", "onSynthesizeFinish: ");
}

@Override
public void onSpeechStart(String s) {
Log.e("444444444", "onSpeechStart: ");
}

@Override
public void onSpeechProgressChanged(String s, int i) {

}

@Override
public void onSpeechFinish(String s) {//监听到播放结束
Log.e("444444444", "onSpeechFinish: ");
if ("我暂时停止接受您的指令,需要恢复,请按恢复按钮。".equals(message)) {

} else {
handlerRecognizer.sendEmptyMessage(0);//由于项目需求在监听到语音播放结束的时候重新开启语音识别,但是语音识别只能在主线程中执行,所以这里用handler起了一个线程,方法在下面赋
}
}

@Override
public void onError(String s, SpeechError speechError) {
Log.e("444444444", "onError: ");
}
});
// 设置在线语音合成授权,需要填入从百度语音官网申请的api_key和secret_key
mSpeechSynthesizer.setApiKey("Uod13Hd6rURLvDLRlVP5PgSB", "cba32e2cc5189a886bd127715dcafabe");
// 设置离线语音合成授权,需要填入从百度语音官网申请的app_id
mSpeechSynthesizer.setAppId("9942218");
// 文本模型文件路径 (离线引擎使用)
this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/"
+ TEXT_MODEL_NAME);
// 声学模型文件路径 (离线引擎使用)
this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/"
+ SPEECH_FEMALE_MODEL_NAME);
// 本地授权文件路径,如未设置将使用默认路径.设置临时授权文件路径,
// LICENCE_FILE_NAME请替换成临时授权文件的实际路径,仅在使用临时license文件时需要进行设置,
// 如果在[应用管理]中开通了正式离线授权,不需要设置该参数,建议将该行代码删除(离线引擎)
// 如果合成结果出现临时授权文件将要到期的提示,说明使用了临时授权文件,请删除临时授权即可。
// this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_LICENCE_FILE, mSampleDirPath + "/"
// + LICENSE_FILE_NAME);
// 获取语音合成授权信息---有两种模式:仅在线;混合(离在线)
//初始化合成引擎,可以指定使用online在线,或者mix离在线混合引擎. mix混合引擎会在online在线不能用的情况下自动使用offline离线引擎。
AuthInfo authInfo = mSpeechSynthesizer.auth(TtsMode.MIX);
// 判断授权信息是否正确,如果正确则初始化语音合成器并开始语音合成,如果失败则做错误处理
if (authInfo.isSuccess()) {
mSpeechSynthesizer.initTts(TtsMode.MIX);
} else {
// 授权失败
Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show();

}

}
第四步:重新开启语音识别,用handler起了一个线程
Handler handlerRecognizer = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
startRecognizer();
}
};

第五步:需要控制语音识别的开始和停止的方法,这里也做了封装,在需要的时候调用即可。

下面是语音识别开始和停止的方法:


/**
* 开始识别语音
*/
private void startRecognizer() {
Intent intent = new Intent();
intent.putExtra("language", "cmn-Hans-CN");
intent.putExtra("prop", 10005);
speechEndTime = -1;
speechRecognizer.startListening(intent);

}
//暂停语音识别
private void stopRecognizer() {
speechRecognizer.stopListening();
print("点击了“说完了”");
}
//停止语音识别
private void cancelRecognizer() {
speechRecognizer.cancel();
status = STATUS_None;
print("点击了“取消”");
}
这里需要注意的是,我遇到的一个问题:
在需要停止监听语音的时候,刚开始我调用的是stop方法,但是并不能真正的停止语音监听,在和百度的技术人员沟通后才知道要调用cancle方法才可以,两个方法同时调用也不可取。
第六步:百度语音合成的方法:
//语音开始播报
mSpeechSynthesizer.speak(“text”);
//语音停止播报mSpeechSynthesizer.stop();
第七步:
当然语音合成和识别都要在activity或fragment的生命周期中做相应的操作:

@Override
protected void onResume() {
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {//横屏操作
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
mSpeechSynthesizer.resume();
super.onResume();
}

@Override
protected void onPause() {
cancelRecognizer();
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {//横屏操作
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
mSpeechSynthesizer.pause();
super.onPause();
}

@Override
protected void onDestroy() {
if (null != mSpeechSynthesizer) {
mSpeechSynthesizer.release();
}
if (null != speechRecognizer) {
// 退出时释放连接
speechRecognizer.destroy();
}
super.onDestroy();
}






posted @ 2017-08-19 18:54  薇薇果  阅读(2960)  评论(0编辑  收藏  举报