BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.8.1)
版权声明:本文为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)的更多相关文章
- BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.7.3)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本Demo将百度语音SDK(其中一部分功能)和自定义的UI对话框封装到一个module中,便于后续的SDK版本更新以及调用. 本De ...
- iOS百度地图SDK集成详细步骤
1.iOS百度地图下载地址 http://developer.baidu.com/map/index.php?title=iossdk/sdkiosdev-download 根据需要选择不同的版本 ...
- 接入百度语音SDK的步骤
1.导入依赖库 SystemConfiguration.framework AudioToolbox.framework UIkit.framework AVFoundation.framework ...
- AEAI BPM流程集成平台V3.0.2版本开源发布
本次开源发布的是AEAI BPMV3.0.2版流程平台,该版本是数通畅联首次正式对外发布的版本,产品现已开源并上传至开源社区http://www.oschina.net/p/aeai-bpm. 产品说 ...
- iOS开发——百度地图SDK集成
(正在形成文档,待更新……)
- Android Studio集成百度地图SDK
1.建议先阅读百度地图官方的继承指南,针对了Eclipse和Android Studio. 百度官方集成指南 2.下载百度地图SDK Android SDK v4.1.1 下载有两种: 1.一键下载( ...
- Xamarin.Android 集成百度地图SDK
前言:趁着周六闲得没事干,赶紧搞一搞Xamarin,最近也是怪无聊的,枯燥的生活不如打几行代码带劲:好了我们进入正题 我这篇文章时参考一位大佬的博客进行改变的,当然他写的需要一定的经验才可以看得懂,我 ...
- 全志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 ...
- 百度地图SDK for Android【检索服务】
1搜索服务 百度地图SDK集成搜索服务包括:位置检索.周边检索.范围检索.公交检索.驾乘检索.步行检索,通过初始化MKSearch类,注册搜索结果的监听对象MKSearchListener,实现异步搜 ...
随机推荐
- 接口测试返回的json文件中字符串是乱序
问题描述 接口测试中post方式匹配返回信息时显示不匹配, 但是statuscode明明是200, 而且用postman /restclient等工具测出来也是没问题的. 根本原因 封装了这么个方法来 ...
- client_v1.go
package nsqlookupd import ( "net" ) //客户端 结构体 type ClientV1 struct { net.Conn //客户 ...
- 第十三章——卷积神经网络(CNN)
卷积神经网络(Convolutional neural networks,CNNs)来源于对大脑视觉皮层的研究,并于1980s开始应用于图像识别.现如今CNN已经在复杂的视觉任务中取得了巨大成功,比如 ...
- BZOJ_2151_种树_贪心+堆+链表
BZOJ_2151_种树_贪心+堆 Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编 ...
- [NOIP2014]飞扬的小鸟 D1 T3 loj2500 洛谷P1941
分析: 这是一个DP,没什么好说的,细节很烦人. DP[i][j]表示到第i个位置,高度为j点最少的次数. 转移: 当j=m时 k属于[m-h,m]都可以向DP[i][j]转移,即dp[i][j]=m ...
- Python数据结构应用4——搜索(search)
Search是数据结构中最基础的应用之一了,在python中,search有一个非常简单的方法如下: 15 in [3,5,4,1,76] False 不过这只是search的一种形式,下面列出多种形 ...
- MyBatis新手教程(一)
MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache 迁移到了 google,并改名为MyBatis,2013年迁移到Github. MyBatis是一个优秀的持 ...
- JDBC知识详解
一.相关概念 1.什么是JDBC JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它 ...
- CountDownLatch和CyclicBarrier 区别
CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行. CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都 ...
- 开发 chrome 扩展 GitHub-Remarks 的一些想法以及遗憾
前文 对于单页应用中如何监听 URL 变化的思考 说到我在开发 chrome 扩展 GitHub Remarks 中遇到的一个问题,本文来聊聊开发这个扩展的前后心路历程. 为什么开发这个扩展?前文说到 ...