失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 百度语音识别结合云知声离线TTSDemo(AS)

百度语音识别结合云知声离线TTSDemo(AS)

时间:2021-01-10 06:03:01

相关推荐

百度语音识别结合云知声离线TTSDemo(AS)

最近项目需要,需要调研几家语音识别(离线/在线),语义理解,TTS(在线/离线),离线命令词,甚至百度的UNIT上下文使用等,虽然看的不怎么深入,但是也确实调研的不是,主要有百度,科大讯飞,搜狗,云知声,奇梦者等几家,还有包括硬件(科大的四麦直线麦克风,五麦环绕麦克风,最后升级的六麦环绕麦克风;奇梦者的四麦环绕麦克风+柱形麦克风阵列等)。也写了很多Demo,每一家的特色都不同。这里就不一一列举了。以后有机会在慢慢写下来,这里就简单给一个百度在线ASR和云知声离线TTS结合的案列,实现一个复读机的功能。

因为现在比较晚了,我先上代码,后面会补充几点注意事项。

1,准备工作:

(1)百度SDK的JAR包bdasr_V3_xxx_xxx.jar与云知声的JAR包usc.jar:

百度SDK下载

云知声SDK下载

(先注册登录,选择服务再下载)

解压找到工程libs中的对应的jar(不在详说),添加在自己新建的工程的libs目录下,添加为library。

(2)so文件:同理,在刚刚下载的SDK中找到对应的so文件,然后早项目新建一个jniLibs目录(../src/main/)

(3)云知声离线TTS需要语音包(发不同音色使用的):使用时,需要先运行自己编写的工程,然后在对应设备的app安装的目录下新建tts文件夹,把下面三个文件放进去:

backend_female

backend_lzl

frontend_model

2,代码环节:

(1)AndroidManifest.xml:主要就是注意几个权限和百度的APP_ID,API_KEY,SECRET_KEY,这个需要自己创建应用,获取这三个值;这步不在累述。

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="/apk/res/android"package=".baidurecongdemo"><!-- begin: baidu speech sdk 权限 --><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" /><applicationandroid:allowBackup="true"android:icon="@mipmap/talk"android:label="@string/app_name"android:roundIcon="@mipmap/talk"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><meta-dataandroid:name="com.baidu.speech.APP_ID"android:value="XXXXXXX" /><meta-dataandroid:name="com.baidu.speech.API_KEY"android:value="XXXXXXXXXXX..." /><meta-dataandroid:name="com.baidu.speech.SECRET_KEY"android:value="XXXXXXXXXXXX...." /><serviceandroid:name=".ASRService"android:enabled="true"android:exported="true"><intent-filter><action android:name=".ASRService" /></intent-filter></service></application></manifest>

(2)ASRService:这里我把百度语音识别写成了服务的形式,并开放了AIDL接口,别的应用可以直接调用即可(里面的方法未完善,学习者可以自行添加和修改)

package .baidurecongdemo;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.Message;import android.os.RemoteCallbackList;import android.os.RemoteException;import android.util.Log;import com.baidu.speech.EventListener;import com.baidu.speech.EventManager;import com.baidu.speech.EventManagerFactory;import com.baidu.speech.asr.SpeechConstant;import com.unisound.client.SpeechConstants;import com.unisound.client.SpeechSynthesizer;import com.unisound.client.SpeechSynthesizerListener;import org.json.JSONObject;import java.io.File;import java.util.LinkedHashMap;import java.util.Map;public class ASRService extends Service implements EventListener {private EventManager asr;public static String result;private boolean logTime = true;private String language;long startTime = 0;long endTime = 0;private MainActivity mainActivity = new MainActivity();private SpeechSynthesizer mTTSPlayer;private final String mFrontendModel= "/sdcard/unisound/tts/frontend_model";private final String mBackendModel = "/sdcard/unisound/tts/backend_lzl";//主动发数据final RemoteCallbackList<IRemoteServiceCallback> mCallbacks= new RemoteCallbackList<IRemoteServiceCallback>();private int mValue = 0;private static final int REPORT_MSG = 1;@Overridepublic void onCreate() {System.out.println("服务创建了:" + "onCreate");asr = EventManagerFactory.create(this, "asr");asr.registerListener(this);super.onCreate();//初始化离线引擎initTts();}@Overridepublic void onStart(Intent intent, int startId) {System.out.println("服务开启了:" + "onStart");super.onStart(intent, startId);}/*** 测试参数填在这里*/public void start() {Map<String, Object> params = new LinkedHashMap<String, Object>();String event = null;event = SpeechConstant.ASR_START; // 替换成测试的eventparams.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);//判断调用者传过来的语言类型if (MainActivity.languge_id == 1) {params.put(SpeechConstant.PID, 1736);} else if (MainActivity.languge_id == 2) {params.put(SpeechConstant.PID, 1836);} else if (MainActivity.languge_id == 3) {params.put(SpeechConstant.PID, 1636);} else {params.put(SpeechConstant.PID, 1536);}System.out.println("MMMMMMMMMMMMMMMMMMLanguage:" + MainActivity.languge_id);// 请先使用如‘在线识别’界面测试和生成识别参数。 params同ActivityRecog类中myRecognizer.start(params);String json = null; //可以替换成自己的jsonjson = new JSONObject(params).toString(); // 这里可以替换成你需要测试的jsonasr.send(event, json, null, 0, 0);printLog("输入参数:" + json);}private void stop() {asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0); //}// EventListener 回调方法/*** @param name :当前asr状态* @param params :解析结果字符串* @author why*/@Overridepublic void onEvent(String name, String params, byte[] data, int offset, int length) {String logTxt = "name: " + name;if (params != null && !params.isEmpty()) {logTxt += " ;params :" + params;//通过name来确定当前状态,从而获取解析结果显示if (name.equals("asr.partial")) {String start = "[";String end = "]";//截取解析json字符串中结果显示result = StringTools.SubStringTwoChar(params, start, end);startTime = System.currentTimeMillis();}}if (name.equals("asr.finish")) {//识别结束if(MainActivity.btn.getText().toString().equals("停止")){if (result.equals("")||result==null){result="没有识别到声音";}MainActivity.btn.setText("开始");}else{if (result.equals("")||result==null){result="No sound at all";}MainActivity.btn.setText("start");}MainActivity.txtResult.setText(result);//TTS语音合成mTTSPlayer.playText(result);}//会话结束标识,发送广播传数据if (name.equals("asr.exit")) {mainActivity.test(result);}if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {if (params.contains("\"nlu_result\"")) {if (length > 0 && data.length > 0) {logTxt += ", 语义解析结果:" + new String(data, offset, length);}}} else if (data != null) {logTxt += " ;data length=" + data.length;}//打印识别日志printLog(logTxt);}//打印识别日志实现private void printLog(String text) {if (logTime) {text += " ;time=" + System.currentTimeMillis();}text += "\n";Log.i(getClass().getName(), text);}//返回可调用服务方法的接口@Overridepublic IBinder onBind(Intent intent) {System.out.println("MMMMMMMMMMMMMMMMM" + "服务绑定了!");return new MyASRresultAIDL();}//百度语音识别class MyASRresultAIDL extends ASRresultAIDL.Stub {@Overridepublic String getASRResult() throws RemoteException {return result;}@Overridepublic void callStart() throws RemoteException {start();}@Overridepublic void callStop() throws RemoteException {stop();}}//初始化离线语音合成引擎实现private void initTts() {// 初始化语音合成对象//mTTSPlayer = new SpeechSynthesizer(this, Config.appKey, Config.secret);mTTSPlayer = new SpeechSynthesizer(this, "", "");System.out.println("TTTTTTTTTTTTTTTTTTS:"+mTTSPlayer);// 设置本地合成mTTSPlayer.setOption(SpeechConstants.TTS_SERVICE_MODE, SpeechConstants.TTS_SERVICE_MODE_LOCAL);File _FrontendModelFile = new File(mFrontendModel);if (!_FrontendModelFile.exists()) {System.out.println("文件:" + mFrontendModel + "不存在,请将assets下相关文件拷贝到SD卡指定目录!");}File _BackendModelFile = new File(mBackendModel);if (!_BackendModelFile.exists()) {System.out.println("文件:" + mBackendModel + "不存在,请将assets下相关文件拷贝到SD卡指定目录!");}// 设置前端模型mTTSPlayer.setOption(SpeechConstants.TTS_KEY_FRONTEND_MODEL_PATH, mFrontendModel);// 设置后端模型mTTSPlayer.setOption(SpeechConstants.TTS_KEY_BACKEND_MODEL_PATH, mBackendModel);// 设置回调监听mTTSPlayer.setTTSListener(new SpeechSynthesizerListener() {@Overridepublic void onEvent(int type) {switch (type) {case SpeechConstants.TTS_EVENT_INIT:// 初始化成功回调Log.i("", "回调成功 ");break;case SpeechConstants.TTS_EVENT_SYNTHESIZER_START:// 开始合成回调Log.i("", "开始同步");break;case SpeechConstants.TTS_EVENT_SYNTHESIZER_END:// 合成结束回调Log.i("", "结束同步");break;case SpeechConstants.TTS_EVENT_BUFFER_BEGIN:// 开始缓存回调Log.i("", "开始缓存 ");break;case SpeechConstants.TTS_EVENT_BUFFER_READY:// 缓存完毕回调Log.i("", "准备缓存 ");break;case SpeechConstants.TTS_EVENT_PLAYING_START:// 开始播放回调Log.i("", "播放开始 ");break;case SpeechConstants.TTS_EVENT_PLAYING_END:// 播放完成回调Log.i("", "播放结束 ");break;case SpeechConstants.TTS_EVENT_PAUSE:// 暂停回调Log.i("", "暂停 ");break;case SpeechConstants.TTS_EVENT_RESUME:// 恢复回调//log_i("resume");break;case SpeechConstants.TTS_EVENT_STOP:// 停止回调Log.i("", "停止");break;case SpeechConstants.TTS_EVENT_RELEASE:// 释放资源回调Log.i("", "释放资源");break;default:break;}}@Overridepublic void onError(int type, String errorMSG) {// 语音合成错误回调Log.e("","Error");}});// 初始化合成引擎int returnvalue= mTTSPlayer.init("");System.out.println("EEEEEEEEEEE:"+"初始化引擎"+returnvalue);}}

(3)StringUtils : ASRService中使用的一个工具类

package .baidurecongdemo;/*** author:why* created on: /1/31 15:25* description:*/public class StringTools {//截取固定字符床中指定两个字符或者字符串之间的子字符串/**** @param target :要处理字符串* @param start :起始字符串/字符* @param end :结束字符串/字符* @return*/public static String SubStringTwoChar(String target, String start, String end) {int startIndex = target.indexOf(start);int endIndex = target.indexOf(end);return target.substring(startIndex, endIndex).substring(start.length());}}

(4)MainActivity:调用服务,演示效果

package .baidurecongdemo;import android.Manifest;import ponentName;import android.content.Intent;import android.content.ServiceConnection;import android.content.pm.PackageManager;import android.os.IBinder;import android.os.RemoteException;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.AbsSpinner;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.Spinner;import android.widget.TextView;import com.baidu.speech.asr.SpeechConstant;/*** @author why*/public class MainActivity extends AppCompatActivity implements InterfaceTest{protected TextView txtLog;public static TextView txtResult;public static Button btn;private String result;private static String DESC_TEXT = "在线识别日志";public static int languge_id = 0;private Intent intent;private MyServiceConnection connection;private ASRresultAIDL asRresultAIDL;private Spinner spinner;private String butContext;/*** 测试参数填在这里*/@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(mon_mini);initView();intent = new Intent(this, ASRService.class);connection = new MyServiceConnection();bindService(intent, connection, BIND_AUTO_CREATE);}//触发语音识别开始与停止public void startOrEnd(View view) {butContext = btn.getText().toString();System.out.println("BBBBBBBBBBBBBBBBBBBBBB"+butContext);//先判断选择的语言if (butContext.equals("开始") || butContext.equals("start")) {//识别结果制空try {asRresultAIDL.callStart();} catch (RemoteException e) {e.printStackTrace();}if (butContext.equals("开始")) {ASRService.result="没有识别到声音";txtResult.setText("请说,我在听");btn.setText("停止");} else {ASRService.result="No sound at all";txtResult.setText("Please say,I am listening");btn.setText("stop");}} else {if (butContext.equals("停止")) {btn.setText("开始");try {txtResult.setText("识别结果:" + asRresultAIDL.getASRResult());} catch (RemoteException e) {e.printStackTrace();}} else {btn.setText("start");try {txtResult.setText("ASR result:" + asRresultAIDL.getASRResult());} catch (RemoteException e) {e.printStackTrace();}}try {asRresultAIDL.callStop();} catch (RemoteException e) {e.printStackTrace();}}}@Overrideprotected void onDestroy() {unbindService(connection);super.onDestroy();}private void initView() {txtResult = (TextView) findViewById(R.id.txtResult);txtLog = (TextView) findViewById(R.id.txtLog);btn = (Button) findViewById(R.id.btn);txtLog.setText(DESC_TEXT + "\n");spinner = findViewById(R.id.languge_list);//下拉框实现ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.Data, android.R.layout.simple_spinner_item);adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);spinner.setAdapter(adapter);spinner.setPrompt("选择语言");//设置下拉框监听spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> parent, View view, int position, long id) {languge_id = position;System.out.println("QQQQQQQQQQQQQQQQQQQQQ"+languge_id);switch (languge_id) {//普通话case 0:txtResult.setText("点击‘开始’");btn.setText("开始");break;//英语case 1://interfaceBaiduParams.setLanguage("English");txtResult.setText("click 'start'");btn.setText("start");break;// 四川话case 2://interfaceBaiduParams.setLanguage("SiChuanHua");txtResult.setText("点击‘开始’");btn.setText("开始");break;//粤语case 3://interfaceBaiduParams.setLanguage("YueYu");txtResult.setText("点击‘开始’");btn.setText("开始");break;}}@Overridepublic void onNothingSelected(AdapterView<?> parent) {}});}@Overridepublic void test(String str) {}private class MyServiceConnection implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {asRresultAIDL = ASRresultAIDL.Stub.asInterface(iBinder);System.out.println("绑定服务成功了");}@Overridepublic void onServiceDisconnected(ComponentName componentName) {System.out.println("解绑服务成功了");}}}

(5)ASRresultAIDL.aidl:开放服务里面的方法,供其他应用调用

// ASRresultAIDL.aidlpackage .baidurecongdemo;// Declare any non-default types here with import statementsinterface ASRresultAIDL {String getASRResult();void callStart();void callStop();}

(6)build.gradle:

apply plugin: 'com.android.application'android {compileSdkVersion 26defaultConfig {applicationId ".baidurecongdemo"minSdkVersion 21targetSdkVersion 26versionCode 1versionName "1.0"testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"//加载对应so文件ndk{abiFilters 'armeabi'}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}}dependencies {implementation fileTree(include: ['*.jar'], dir: 'libs')implementation 'com.android.support:appcompat-v7:26.1.0'implementation 'com.android.support.constraint:constraint-layout:1.0.2'testImplementation 'junit:junit:4.12'androidTestImplementation 'com.android.support.test:runner:1.0.1'androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'implementation files('libs/bdasr_V3_1108_9800a2a.jar')implementation files('libs/usc.jar')}

3,注意事项:

(1)云知声离线TTSso文件不是X86的,所以window下的x86模拟器是用不了的,但是在window系统下运行arm的模拟器很卡,所以建议真机调试

(2)我这里在百度语音识别的地方只是实现了最简单的语音识别调用流程,很多的参数没有使用,学习者可以自己完善和添加

(3)我这里只添加了百度armeabi下的so文件,所以在gradle文件用ndk指定了(ndk已经安装),也可以什么都不加

(4)我这里主要是实现了一个复读机的功能,你说什么,那边会把识别文本语音合成播放出来,可以自己选择音色

(5)我这里百度开发了四种语言语音识别

注:欢迎扫码关注

如果觉得《百度语音识别结合云知声离线TTSDemo(AS)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。