版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

上一篇集成的是V3.0.7.3版本的SDK《BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.7.3)》,这次发现官网的SDK进行了升级,感觉有必要进行重新集成。

1、修复了APP同时集成多个SDK,不能同时使用的问题;——所以需要使用新sdk的jar文件;

2、既然官网也使用了module方式;——那么就不需要自己创建module了,直接在官网的core这个module中优化;

3、修复长语音无结束回调;——增加长语音结束回调的监听;

本Demo中使用的appkey已失效,请自行创建应用,使用新的appkey。

效果图

和《BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.7.3)》类似,这里就不单独截图了。

代码分析

普通话 search搜索模型:参考SpeechBottomSheetDialog.java类

普通话 input输入法模型,适用于长句及长语音,有逗号分割,无语义:参考SpeechLongBottomSheetDialog.java类

注意:关于语音识别状态维护,API调用的代码,是自己根据官网demo的理解进行整理的,可能有所偏颇,仅供参考。【希望官网demo可以添加百度APP的语音对话框效果就好了】

使用步骤

一、项目组织结构图

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

(1)在项目中导入官网demo中的core这个module,同时修改名称,修改为baiduspeech

(2)修改baiduspeech的AndroidManifest.xml(修改官网申请的应用信息)

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test2.baidu.com.baseasr">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application>
<meta-data
android:name="com.baidu.speech.APP_ID"
android:value="11588936"/>
<meta-data
android:name="com.baidu.speech.API_KEY"
android:value="XRF3IOf2tNGePzlv47cBnvF3"/>
<meta-data
android:name="com.baidu.speech.SECRET_KEY"
android:value="diC8lQ7XDcGBKQ6FzCpvnan54F5CnMZI"/>
</application>
</manifest>

(3)修改MessageStatusRecogListener.java文件【根据实际情况进行修改】

package com.baidu.aip.asrwakeup3.core.recog.listener;

import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.baidu.aip.asrwakeup3.core.recog.RecogResult;
import com.baidu.speech.asr.SpeechConstant; /**
* Created by fujiayi on 2017/6/16.
*/ public class MessageStatusRecogListener extends StatusRecogListener {
private Handler handler; private long speechEndTime = 0; private boolean needTime = true; private static final String TAG = "MesStatusRecogListener"; public MessageStatusRecogListener(Handler handler) {
this.handler = handler;
} @Override
public void onAsrReady() {
super.onAsrReady();
speechEndTime = 0;
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_WAKEUP_READY, "引擎就绪,可以开始说话。");
} @Override
public void onAsrBegin() {
super.onAsrBegin();
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_BEGIN, "检测到用户说话");
} @Override
public void onAsrEnd() {
super.onAsrEnd();
speechEndTime = System.currentTimeMillis();
sendMessage("【asr.end事件】检测到用户说话结束");
} @Override
public void onAsrPartialResult(String[] results, RecogResult recogResult) {
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL,
"临时识别结果,结果是“" + results[0] + "”;原始json:" + recogResult.getOrigalJson());
super.onAsrPartialResult(results, recogResult);
} @Override
public void onAsrFinalResult(String[] results, RecogResult recogResult) {
super.onAsrFinalResult(results, recogResult);
//String message = "识别结束,结果是”" + results[0] + "”";//why 实际中可以去掉,不需要
String message = recogResult.getOrigalJson();//{"results_recognition":["什么什么"],"origin_result":{"corpus_no":6522034498058113957,"err_no":0,"result":{"word":["什么什么"]},"sn":"bfa8b286-ab0e-4f86-9209-1d36d38b1224","voice_energy":16191.7705078125},"error":0,"best_result":"什么什么","result_type":"final_result"}
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL,
message + ";原始json:" + recogResult.getOrigalJson());
if (speechEndTime > 0) {
long currentTime = System.currentTimeMillis();
long diffTime = currentTime - speechEndTime;
//message += ";说话结束到识别结束耗时【" + diffTime + "ms】";// why 实际中可以去掉,不需要 }
speechEndTime = 0;
sendMessage(message, status, true);
} @Override
public void onAsrFinishError(int errorCode, int subErrorCode, String descMessage,
RecogResult recogResult) {
super.onAsrFinishError(errorCode, subErrorCode, descMessage, recogResult);
//String message = "识别错误, 错误码:" + errorCode + " ," + subErrorCode + " ; " + descMessage;// why 实际中可以去掉,不需要
String message = recogResult.getOrigalJson();//{"origin_result":{"sn":"","error":7,"desc":"No recognition result match","sub_error":7001},"error":7,"desc":"No recognition result match","sub_error":7001}
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL, message);
if (speechEndTime > 0) {
long diffTime = System.currentTimeMillis() - speechEndTime;
//message += "。说话结束到识别结束耗时【" + diffTime + "ms】";// why实际中可以去掉,不需要
}
speechEndTime = 0;
sendMessage(message, status, true);
speechEndTime = 0;
} @Override
public void onAsrOnlineNluResult(String nluResult) {
super.onAsrOnlineNluResult(nluResult);
if (!nluResult.isEmpty()) {
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL, "原始语义识别结果json:" + nluResult);
}
} @Override
public void onAsrFinish(RecogResult recogResult) {
super.onAsrFinish(recogResult);
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_FINISH, "识别一段话结束。如果是长语音的情况会继续识别下段话。"); } /**
* 长语音识别结束
*/
@Override
public void onAsrLongFinish() {
super.onAsrLongFinish();
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH, "长语音识别结束。");
} /**
* 使用离线命令词时,有该回调说明离线语法资源加载成功
*/
@Override
public void onOfflineLoaded() {
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_LOADED, "离线资源加载成功。没有此回调可能离线语法功能不能使用。");
} /**
* 使用离线命令词时,有该回调说明离线语法资源加载成功
*/
@Override
public void onOfflineUnLoaded() {
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED, "离线资源卸载成功。");
} @Override
public void onAsrExit() {
super.onAsrExit();
sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_EXIT, "识别引擎结束并空闲中");
} private void sendStatusMessage(String eventName, String message) {
message = "[" + eventName + "]" + message;
sendMessage(message, status);
} private void sendMessage(String message) {
sendMessage(message, WHAT_MESSAGE_STATUS);
} private void sendMessage(String message, int what) {
sendMessage(message, what, false);
} private void sendMessage(String message, int what, boolean highlight) { if (needTime && what != STATUS_FINISHED) {
message += " ;time=" + System.currentTimeMillis();
}
if (handler == null) {
Log.i(TAG, message);
return;
}
Message msg = Message.obtain();
msg.what = what;
msg.arg1 = status;
if (highlight) {
msg.arg2 = 1;
}
msg.obj = message + "\n";
handler.sendMessage(msg);
}
}

至此,百度语音SDK集成到baiduspeech中了,下一步就是创建UI对话框(建议再单独创建一个新的module)。

(4)新建baiduspeechdialog这个module

1、在baiduspeechdialog的build.gradle中引用recyclerview【版本号和项目的appcompat保持一致】【因为demo中用到了】【注意:还需要导入baiduspeech这个module】

apply plugin: 'com.android.library'

android {
compileSdkVersion 27 defaultConfig {
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
} } dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
//RecyclerView
compile 'com.android.support:recyclerview-v7:27.1.1'
//baiduspeech
implementation project(':baiduspeech')
}

2、对话框类、列表适配器类、布局文件xml文件、图片资源、动画style样式等复制到baiduspeechdialog中【参考《BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.7.3)》】

3、SpeechBottomSheetDialog.java和SpeechLongBottomSheetDialog.java在V3.0.7.3版本和V3.0.8.1版本的区别

3.1、需要将Logger修改为MyLogger

修改为:

三、使用方法

(1)因为需要使用到运行时权限,所以参考《Android6.0运行时权限(基于RxPermission开源库)》在APP的build.gradle中引入第三方库

(2)在APP的build.gradle中引入baiduspeechdialog

(3)在Activity中调用

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.why.project.baiduspeechdemo.MainActivity"> <TextView
android:id="@+id/tv_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.448"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.325"/> <Button
android:id="@+id/btn_openSpeechDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:text="打开搜索模型语音识别对话框"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.419"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/> <Button
android:id="@+id/btn_openSpeechLongDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="打开input输入模型语音识别对话框"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_openSpeechDialog"/> </android.support.constraint.ConstraintLayout>

activity_main.xml

package com.why.project.baiduspeechdemo;

import android.Manifest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast; import com.tbruyelle.rxpermissions2.RxPermissions;
import com.why.project.baiduspeechdialog.dialog.SpeechBottomSheetDialog;
import com.why.project.baiduspeechdialog.dialog.SpeechLongBottomSheetDialog; import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private Button mOpenSpeechDialogBtn;
private Button mOpenSpeechLongDialogBtn;
private TextView mResultTv; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); onePermission(); initViews();
initEvents();
} private void initViews() {
mOpenSpeechDialogBtn = findViewById(R.id.btn_openSpeechDialog);
mOpenSpeechLongDialogBtn = findViewById(R.id.btn_openSpeechLongDialog);
mResultTv = findViewById(R.id.tv_result);
} private void initEvents() {
mOpenSpeechDialogBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//打开百度语音对话框
SpeechBottomSheetDialog speechBottomSheetDialog = SpeechBottomSheetDialog.getInstance(MainActivity.this);
speechBottomSheetDialog.seOnResultListItemClickListener(new SpeechBottomSheetDialog.OnResultListItemClickListener() {
@Override
public void onItemClick(String title) {
//填充到输入框中
mResultTv.setText(title);
}
});
speechBottomSheetDialog.show(getSupportFragmentManager(), TAG);
}
});
mOpenSpeechLongDialogBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//打开百度语音对话框
SpeechLongBottomSheetDialog speechLongBottomSheetDialog = SpeechLongBottomSheetDialog.getInstance(MainActivity.this);
speechLongBottomSheetDialog.seOnResultListItemClickListener(new SpeechLongBottomSheetDialog.OnResultListItemClickListener() {
@Override
public void onItemClick(String title) {
//填充到输入框中
mResultTv.setText(mResultTv.getText()+title);
}
});
speechLongBottomSheetDialog.show(getSupportFragmentManager(), TAG);
}
}); } /**只有一个运行时权限申请的情况*/
private void onePermission(){
RxPermissions rxPermissions = new RxPermissions(MainActivity.this); // where this is an Activity instance
rxPermissions.request(Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE) //权限名称,多个权限之间逗号分隔开
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean granted) throws Exception {
Log.e(TAG, "{accept}granted=" + granted);//执行顺序——1【多个权限的情况,只有所有的权限均允许的情况下granted==true】
if (granted) { // 在android 6.0之前会默认返回true
// 已经获取权限
} else {
// 未获取权限
Toast.makeText(MainActivity.this, "您没有授权该权限,请在设置中打开授权", Toast.LENGTH_SHORT).show();
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e(TAG,"{accept}");//可能是授权异常的情况下的处理
}
}, new Action() {
@Override
public void run() throws Exception {
Log.e(TAG,"{run}");//执行顺序——2
}
});
}
}

混淆配置

#=====================百度语音混淆=====================
-keep class com.baidu.speech.**{*;}

参考资料

http://ai.baidu.com/tech/speech

项目demo下载地址

https://github.com/haiyuKing/BaiduSpeechNewDemo

BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.8.1)的更多相关文章

  1. BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.7.3)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本Demo将百度语音SDK(其中一部分功能)和自定义的UI对话框封装到一个module中,便于后续的SDK版本更新以及调用. 本De ...

  2. iOS百度地图SDK集成详细步骤

    1.iOS百度地图下载地址 http://developer.baidu.com/map/index.php?title=iossdk/sdkiosdev-download 根据需要选择不同的版本  ...

  3. 接入百度语音SDK的步骤

    1.导入依赖库 SystemConfiguration.framework AudioToolbox.framework UIkit.framework AVFoundation.framework ...

  4. AEAI BPM流程集成平台V3.0.2版本开源发布

    本次开源发布的是AEAI BPMV3.0.2版流程平台,该版本是数通畅联首次正式对外发布的版本,产品现已开源并上传至开源社区http://www.oschina.net/p/aeai-bpm. 产品说 ...

  5. iOS开发——百度地图SDK集成

    (正在形成文档,待更新……)

  6. Android Studio集成百度地图SDK

    1.建议先阅读百度地图官方的继承指南,针对了Eclipse和Android Studio. 百度官方集成指南 2.下载百度地图SDK Android SDK v4.1.1 下载有两种: 1.一键下载( ...

  7. Xamarin.Android 集成百度地图SDK

    前言:趁着周六闲得没事干,赶紧搞一搞Xamarin,最近也是怪无聊的,枯燥的生活不如打几行代码带劲:好了我们进入正题 我这篇文章时参考一位大佬的博客进行改变的,当然他写的需要一定的经验才可以看得懂,我 ...

  8. 全志tina v3.0系统编译时的时间错误的解决(全志SDK的维护BUG)

    全志tina v3.0系统编译时的时间错误的解决(全志SDK的维护BUG) 2018/6/13 15:52 版本:V1.0 开发板:SC3817R SDK:tina v3.0 1.01原始编译全志r1 ...

  9. 百度地图SDK for Android【检索服务】

    1搜索服务 百度地图SDK集成搜索服务包括:位置检索.周边检索.范围检索.公交检索.驾乘检索.步行检索,通过初始化MKSearch类,注册搜索结果的监听对象MKSearchListener,实现异步搜 ...

随机推荐

  1. mysql按条件 导出sql

    mysqldump还有一个参数,就是--where 指定条件,这样我们就可以对一张表里的某些符合条件的数据,进行备份,导出.sql文件了 mysqldump -u root -p DB_Name -- ...

  2. tcp.go

    )     _, err := io.ReadFull(clientConn, buf)     if err != nil {         p.ctx.nsqd.logf("ERROR ...

  3. 解锁 vmware esxi 6.7 并安装 mac os 10.13

    1.安装 esxi 6.7 2.下载 unlocker 2.1.1.zip 3.上传 unlocker 2.1.1.zip esxi的磁盘中 4.开启esxi的ssh登录 5.使用 ssh 登录 es ...

  4. Mtcnn进行人脸剪裁和对齐

    from scipy import misc import tensorflow as tf import detect_face import cv2 import matplotlib.pyplo ...

  5. 基于 ReactJS 开发简单的可视化业务编辑器 01

    线上可以看的,跟github上的代码不一样的:https://whensea.com/wfd/ 程序中经常有一些业务需要定制化,我定制化这些业务的方式主要是基于工作流.配置等方式.由于个人水平限制并不 ...

  6. 带你由浅入深探索webpack4(二)

    在前一篇文章已经介绍了webpack4从入门到一些核心常用的用法,大家可以从上一篇文章看起.带你由浅入深探索webpack4(一) 接着上一章,接下来我们会继续探讨webpack4中的各种实用用法,让 ...

  7. CSS 圣杯布局 / 双飞翼布局的实现

    工作的越久,有些基础知识我们可能就逐渐淡忘了,今天我们来回顾一下css的圣杯布局和双飞翼布局, 这两个名词你可能不熟, 那三栏布局你肯定就非常熟悉了, 就是两边定宽, 中间自适应 的 布局 1 , 圣 ...

  8. Vue.js组件间通信方式总结

    平时在使用Vue框架的业务开发中,组件不仅仅要把模板的内容进行复用,更重要的是组件之间要进行通信.组件之间通信分为三种:父-子:子-父:跨级组件通信.下面,就组件间如何通信做一些总结. 1.父组件到子 ...

  9. 『审慎』.Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历

    异步Task简单介绍 本标题有点 哗众取宠,各位都别介意(不排除个人技术能力问题) —— 接下来:我将会用一个小Demo 把 本文思想阐述清楚. .Net 4.0 就有了 Task 函数 —— 异步编 ...

  10. OSPF 基础实验

    一.环境准备 1. 软件:GNS3 2. 路由:c7200 二.实验操作 实验要求: 1.掌握多区域的 OSPF 配置方法. 2.区别不同区域的路由. 3.掌握 OSPF 的路由汇总配置. 4.掌握  ...