1、前言
最近智能语音很火呀,于是想在自己手机上也模拟智能音箱实现智能语音,利用语音控制手机,同时手机也能友好的回复。想想很高大上的感觉。目前很6的智能语音AIUI应该是讯飞了,各大帝国也有。反正很火,原本打算直接使用讯飞的,看了哈,开发文档有点绕。还是先找个简单的平台练练手,再去找讯飞。嘿,百度,就它了,必须简单。直接搜索百度语音,不用想,第一个就是。再说一点,这是小白的第一篇CSDN博客,就是开发中遇到很多坑,还有很多想吐槽的,所以花了点时间共享出来,希望对很多小白们有点帮助!说干就干!
2、开发前准备
1、Android studio,我是2.2.2的版本,集成gradle2.14的(台式机懒得升,笔记本是最新的,电脑性能你懂得),手机Android 5.1。
2、要开发百度语音,去百度语音控制台注册一下,成为开发者还是必要的吧,这个很简单。百度一向人性化,简单,按他步骤来就行。完后你就你能看到这个界面。我账号很久前就注册了,开发必备各大平台后台。我这里已经创建好了两个应用。不慌,会重头来过,吹6 前还是得打草稿。
3、利用别人的平台开发无非就几个步骤:
1. 创建应用,得到通行证(无非就是一些id,key什么的,套路)
2. 与自己的应用建立联系(绑定包名或者有个license什么的)
3. 下载SDK(注意,有些需要绑定后的SDK,比如百度语音,这就是我踩第一个坑,后面会说)
4. 集成jar包或者libs或so(这个开发第二个坑)到项目中
5. 配置同行证或者代码加载
最后调用代码完事是不是很简单。是不是很简单。是不是很简单
3、正式开发——百度语音识别
来,跟着我,左手右手一个慢动作(不是该动作,出错别搭理我,我第一次)
1、先用android studio创建一个项目,取名Test_BD_AIUI_1,包名就com.example.aiui。(讯飞别说我盗用名字)
2、去百度控制台,创建一个应用。跟着步骤,有坑(图片不好放,我就少放图了,后面再多放图)
1、点击“创建新应用”,输入应用名称(没要求,咱开发的,取个能证明我们是程序的名字,我就去BD_AIUI_1,高大上的感觉),选择应用类型,随你了。
2:选择服务,这里先做的是语音识别,咱把语音合成也选,反正可以多选呀。不存在,下一步。
3:下载SDK,这里就只能单选了(百度做的不好,东西都没配置完,就下SDK,此处有坑,跟紧了),我们选择”语音识别离在线融合SDK”下载,他会弹出新的窗口(有些浏览器覆盖的,你懂的哈),不要慌,回去。点击下一步。。或者你不选择,直接点击下一步。
4:重点来了。现在应该是集成开发了。有个平台选择和应用包名,重点,我开发Android,所以选择Android。应用包名非常重要,去我们工程下manifest下,把包名复制过来,我之前间工程包名是“com.example.aiui”,去应用中看哈,选择自己包名,我理解的是这是开发绑定证书,第一个坑解决。
5:就完成了,基本服务已经打通了,弹出的服务设置暂时不会用,要做很6的功能就要了。点击右上角的“X”吧。刷新一下就可以看到。进错地方的同志点击应用管理就能看到了。看看是不是样的,注意平台有不有,如没有,就是你没跟着我,左手右手一个慢动作。没事,还有救,右上角有个管理包名,把你应用的包名和平台选好,然后保存是一样的;
6:坑又来了。是不是很开心,每天一坑,点击顶上SDK下载。选择创建的应用,你不选下面是灰色的,UI做的不好。点击后感觉没反应,半天后才刷新,可以看到右上角有个图标了哈,下载Android 语音识别服务SDK,15M左右。应用平台这边搞定了。别关。等会还要用。刚才第三步不叫你下载,是有原因的,这就是我踩的坑。要是刚才下载SDK就会出现,包名没配置。是需要临时License这个文件。因为他得Demo中就有,管理包名中下载的。
3:解压下载的SDK,里面有4个文件(夹)一个demo,两个我们应用中要用的资源,一个apk。demo是eclipse的。可以看哈。apk可以安装体验哈。不错的。
4:体验完了,我们自己开发。大致可以实现它的功能
1:回到我们的AS工程,切换到project界面,开始导入开发的资源。一个libs,一个res。先导入libs,打开看哈是啥东西,两个含so的文件夹,一个jar文件。有so文件呢。。我们是AS哦。别犯二。。首先:在项目的main目录下创建一个jniLibs文件夹,将资源文件夹中的arm64-v8a和armeabi复制到jniLibs中。然后将jar文件放到工程的libs目录下,记得右键add as Library。
2:此处是有坑,jar文件可以add as library,jniLibs的so文件怎么加载呢。。问了百度,全是在build.gradle中添加如下代码。然后点击 编译“”C的那把锤子“”(build-make project)然后切换到android界面就可以看到jniLibs加载成功了。我牙刷,一个个,把我坑的青痛。哎哟,不说,一把泪,害得我纠结了一晚上。直接告诉你们正确的做法。
android {
compileSdkVersion 24
buildToolsVersion "24.0.3"
defaultConfig {
applicationId "com.example.aiui"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
//jniLibs.srcDirs = ['src/main/libs'] //设置目标的so存放路径
jniLibs.srcDirs = ['libs'] //设置目标的so存放路径
}
}
}
把那行代码换成这个就行了,第二个坑解决了:jniLibs.srcDirs = [‘src/main/jniLibs’] //设置目标的so存放路径
改了后再使用C的make project编译一下,切换到Android视图下就可以看到jniLibs加载成功了
3:libs导入完毕。再看哈资源文件有啥。drawable layout raw。可用可不用的文件,都明白,这个资源文件做UI和交互的。。可以导入也可以不导入,咱还是导入吧,先在项目下建立raw文件,这个是音频文件,然后把raw中的文件复制到我们工程的raw下。drawable,layout中的文件直接放进去就好。。预编译哈工程嘛。防止电脑太low,资源文件没有生成ID…所有资源导入完毕了哦。接下来。便是见证奇迹的时刻。
4、跟我编程——简单几步搞定
1:你可以看SDK中demo,也可以看百度的开发文档,demo必须看吧,学习别人优秀编程思想。过来开发,咱还是看开发文档,这有帮助。打开百度语音平台的文档中心,中间语音识别和语音合成都有开发文档,选择离在线语音识别Android SDK。开始阅读,建议把所有的文档,先过一遍。在定点过来。。文章不错的。。我就直接进去了。我读过了。
2:点击集成指南,由于之前的so文件和jar文件我们都成功集成到工程中。所以,这里我们就直接走不用管其他了。。在manifest 中 添加权限。。。配置appid和key和secret,还有添加服务,至于他还有个activity,放进去吧,。如果你的jar包和so成功加载,这里是不会报错的。。。。。记得appid和key和secret换成自己的哈。。在哪有,,在百度应用管理中”查看key”你的应用中去复制。。别傻傻的。
3:所有配置完了。先直接上代码,很简单的。只要前面配置没错。。后面就几行代码。我们先在界面放一个按钮和一个文本框显示我们说的话吧。为了简单,button直接设置了onclick
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.aiui.MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/bt_speek"
android:onClick="doClick"
android:text="点我说话"/>
<TextView
android:layout_width="match_parent"
android:id="@+id/tv_show"
android:text="我说:"
android:layout_height="wrap_content"/>
LinearLayout>
主代码部分 说哈流程。初始化控件,初始化语音识别实例。设置监听器,实现接口方法,点击按键,设置参数,在监听结果中处理结果。就这么简单。
package com.example.aiui;
import android.content.ComponentName;
import android.content.Intent;
import android.speech.RecognitionListener;
import android.speech.SpeechRecognizer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.baidu.speech.VoiceRecognitionService;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements RecognitionListener
{
private static final String TAG = "MainActivity";
private SpeechRecognizer speechRecognizer;
private Button button;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InitViews();//初始化页面控件
InitASR();//初始化SpeechRecognizer
}
/**初始化页面控件*/
private void InitViews()
{
button= (Button) findViewById(R.id.bt_speek);
textView= (TextView) findViewById(R.id.tv_show);
}
/**初始化实例*/
private void InitASR()
{
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this,
new ComponentName(this, VoiceRecognitionService.class));
speechRecognizer.setRecognitionListener(this);
}
public void doClick(View v)
{
switch (v.getId())
{
case R.id.bt_speek:
Intent intent = new Intent();
bindParams(intent);//设置一些参数
speechRecognizer.startListening(intent);
break;
}
}
/**设置参数*/
private void bindParams(Intent intent)
{
//就只设置声音吧,
intent.putExtra("sound_start", R.raw.bdspeech_recognition_start);
intent.putExtra("sound_end", R.raw.bdspeech_speech_end);
intent.putExtra("sound_success", R.raw.bdspeech_recognition_success);
intent.putExtra("sound_error", R.raw.bdspeech_recognition_error);
intent.putExtra("sound_cancel", R.raw.bdspeech_recognition_cancel);
//参数都有默认的 详细设置参考开发文档参数设置
}
@Override
public void onReadyForSpeech(Bundle params)
{
//准备就绪
Log.e(TAG, "onReadyForSpeech: " );
}
@Override
public void onBeginningOfSpeech()
{
//监听到开始说话
Log.e(TAG, "onBeginningOfSpeech: " );
}
@Override
public void onRmsChanged(float rmsdB)
{
//音量变化
Log.e(TAG, "onRmsChanged: " +rmsdB);
}
@Override
public void onBufferReceived(byte[] buffer)
{
//获取原始语音
Log.e(TAG, "onBufferReceived: " );
}
@Override
public void onEndOfSpeech()
{
//结束说话
Log.e(TAG, "onEndOfSpeech: " );
}
@Override
public void onError(int error)
{
//错误
Log.e(TAG, "onError: "+error);
}
@Override
public void onResults(Bundle results)
{
//结果
ArrayList r = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
textView.append(r.get(0)+"\n");
}
@Override
public void onPartialResults(Bundle partialResults)
{
//临时结果
Log.e(TAG, "onPartialResults: " );
}
@Override
public void onEvent(int eventType, Bundle params)
{
//识别事件返回
Log.e(TAG, "onEvent: " +eventType);
}
}
简单的语音的识别就实现了。这里只实现了语音的识别。语音有很多参数。这里就不挨着实现了。都是效果问题,简单。讯飞能够与你对话,百度语音我就没做了。就在服务设置里面,我估计不是像讯飞那种动态的。你可以写个service或者线程让它随时监听,或者使用语音唤醒功能。后面我只给出了语音合成的代码。与之类型。切记一般不说话,或者不能识别,,,没报错的话就是so文件没加载、
语音合成代码:你得按照步骤来。创建应用,选择服务。绑定包名,下载sdk,集成so和jar文件。然后使用下面代码就ok
**再次提醒加载jar包,add as library
加载so**
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jnilibs'] //设置目标的so
}
}
主工程:
package com.example.aiui;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.baidu.tts.auth.AuthInfo;
import com.baidu.tts.client.SpeechError;
import com.baidu.tts.client.SpeechSynthesizer;
import com.baidu.tts.client.SpeechSynthesizerListener;
import com.baidu.tts.client.TtsMode;
import com.baidu.tts.tools.StringTool;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;
public class MainActivity extends AppCompatActivity implements SpeechSynthesizerListener
{
private static final String TAG = "MainActivity";
private SpeechSynthesizer speechSynthesizer;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startTTS();
}
private void startTTS()
{
speechSynthesizer = SpeechSynthesizer.getInstance();
speechSynthesizer.setContext(this);
speechSynthesizer.setSpeechSynthesizerListener(this);
speechSynthesizer.setAppId("10057156");
speechSynthesizer.setApiKey("112TBkbBZiOwdYhCG2uTQYiD", "59969108c07ad6e2206ef692ebcf5cbc");
AuthInfo authInfo = speechSynthesizer.auth(TtsMode.ONLINE);
speechSynthesizer.initTts(TtsMode.ONLINE);
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "5");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "5");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "3");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT);
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_AUDIO_ENCODE, SpeechSynthesizer.AUDIO_ENCODE_AMR);
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_AUDIO_RATE, SpeechSynthesizer.AUDIO_BITRATE_AMR_15K85);
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOCODER_OPTIM_LEVEL, "0");
Log.e(TAG, "startTTS: "+authInfo.isSuccess() );
}
public void doClick(View v)
{
switch (v.getId())
{
case R.id.bt:
Log.e(TAG, "doClick: ");
int i = speechSynthesizer.speak("百度一下,你就知道");
Log.e(TAG, "doClick: "+i );
break;
}
}
@Override
public void onSynthesizeStart(String s)
{
Log.e(TAG, "onSynthesizeStart: "+s );
}
@Override
public void onSynthesizeDataArrived(String s, byte[] bytes, int i)
{
Log.e(TAG, "onSynthesizeDataArrived: "+s );
}
@Override
public void onSynthesizeFinish(String s)
{
Log.e(TAG, "onSynthesizeFinish: "+s );
}
@Override
public void onSpeechStart(String s)
{
Log.e(TAG, "onSpeechStart: "+s );
}
@Override
public void onSpeechProgressChanged(String s, int i)
{
Log.e(TAG, "onSpeechProgressChanged: "+s );
}
@Override
public void onSpeechFinish(String s)
{
Log.e(TAG, "onSpeechFinish: "+s );
}
@Override
public void onError(String s, SpeechError speechError)
{
Log.e(TAG, "onError: "+s +""+speechError.code);
}
}