diff --git a/app/build.gradle b/app/build.gradle index e5f50b2..2c6b420 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ android { minSdkVersion 22 targetSdkVersion 30 versionCode 6 - versionName "V2.0.7.33" + versionName "V2.0.7.30" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles 'consumer-rules.pro' @@ -90,14 +90,14 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation files('libs\\ymeeting.jar')//亿晟 implementation project(path: ':playerview') - implementation files('libs/SparkChain.aar') implementation files('libs\\zckjAPI-2.2.jar')//卓策 implementation files('libs\\jna-min.jar') implementation files('libs\\toolbox_kit.jar')//灰度主板 罗湖寻车机 implementation files('libs\\shockman.jar')//指路机 implementation files('libs\\signway.jar') //欣威视通 implementation files('libs\\sdkapi.jar') //Bv-3588 - implementation files('libs\\smdt.jar')//视美泰 + implementation files('libs\\smdt.jar') //视美泰 + implementation files('libs\\DUI-lite-SDK-for-Android-3.5.0-466a4c77.jar') //思必驰语音 testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' diff --git a/app/libs/DUI-lite-SDK-for-Android-3.5.0-466a4c77.jar b/app/libs/DUI-lite-SDK-for-Android-3.5.0-466a4c77.jar new file mode 100644 index 0000000..6f50de5 Binary files /dev/null and b/app/libs/DUI-lite-SDK-for-Android-3.5.0-466a4c77.jar differ diff --git a/app/libs/arm64-v8a/libailog2.so b/app/libs/arm64-v8a/libailog2.so new file mode 100644 index 0000000..a825503 Binary files /dev/null and b/app/libs/arm64-v8a/libailog2.so differ diff --git a/app/libs/arm64-v8a/libduidns.so b/app/libs/arm64-v8a/libduidns.so new file mode 100644 index 0000000..485f33d Binary files /dev/null and b/app/libs/arm64-v8a/libduidns.so differ diff --git a/app/libs/arm64-v8a/libduiitn.so b/app/libs/arm64-v8a/libduiitn.so new file mode 100644 index 0000000..bfdcad9 Binary files /dev/null and b/app/libs/arm64-v8a/libduiitn.so differ diff --git a/app/libs/arm64-v8a/libduiutils.so b/app/libs/arm64-v8a/libduiutils.so new file mode 100644 index 0000000..da35d18 Binary files /dev/null and b/app/libs/arm64-v8a/libduiutils.so differ diff --git a/app/libs/arm64-v8a/libliteca.so b/app/libs/arm64-v8a/libliteca.so new file mode 100644 index 0000000..25f6ba8 Binary files /dev/null and b/app/libs/arm64-v8a/libliteca.so differ diff --git a/app/libs/arm64-v8a/libmp3.so b/app/libs/arm64-v8a/libmp3.so new file mode 100644 index 0000000..a71fc8e Binary files /dev/null and b/app/libs/arm64-v8a/libmp3.so differ diff --git a/app/libs/arm64-v8a/libopusogg.so b/app/libs/arm64-v8a/libopusogg.so new file mode 100644 index 0000000..fe6263d Binary files /dev/null and b/app/libs/arm64-v8a/libopusogg.so differ diff --git a/app/libs/arm64-v8a/libspeex.so b/app/libs/arm64-v8a/libspeex.so new file mode 100644 index 0000000..f2a7cfc Binary files /dev/null and b/app/libs/arm64-v8a/libspeex.so differ diff --git a/app/libs/arm64-v8a/libvad.so b/app/libs/arm64-v8a/libvad.so new file mode 100644 index 0000000..9345453 Binary files /dev/null and b/app/libs/arm64-v8a/libvad.so differ diff --git a/app/libs/armeabi-v7a/libailog2.so b/app/libs/armeabi-v7a/libailog2.so new file mode 100644 index 0000000..27f2051 Binary files /dev/null and b/app/libs/armeabi-v7a/libailog2.so differ diff --git a/app/libs/armeabi-v7a/libduidns.so b/app/libs/armeabi-v7a/libduidns.so new file mode 100644 index 0000000..d91224f Binary files /dev/null and b/app/libs/armeabi-v7a/libduidns.so differ diff --git a/app/libs/armeabi-v7a/libduiitn.so b/app/libs/armeabi-v7a/libduiitn.so new file mode 100644 index 0000000..1f8817f Binary files /dev/null and b/app/libs/armeabi-v7a/libduiitn.so differ diff --git a/app/libs/armeabi-v7a/libduiutils.so b/app/libs/armeabi-v7a/libduiutils.so new file mode 100644 index 0000000..905f206 Binary files /dev/null and b/app/libs/armeabi-v7a/libduiutils.so differ diff --git a/app/libs/armeabi-v7a/libliteca.so b/app/libs/armeabi-v7a/libliteca.so new file mode 100644 index 0000000..cab87e0 Binary files /dev/null and b/app/libs/armeabi-v7a/libliteca.so differ diff --git a/app/libs/armeabi-v7a/libmp3.so b/app/libs/armeabi-v7a/libmp3.so new file mode 100644 index 0000000..809c961 Binary files /dev/null and b/app/libs/armeabi-v7a/libmp3.so differ diff --git a/app/libs/armeabi-v7a/libopusogg.so b/app/libs/armeabi-v7a/libopusogg.so new file mode 100644 index 0000000..3efb823 Binary files /dev/null and b/app/libs/armeabi-v7a/libopusogg.so differ diff --git a/app/libs/armeabi-v7a/libspeex.so b/app/libs/armeabi-v7a/libspeex.so new file mode 100644 index 0000000..f31f8c1 Binary files /dev/null and b/app/libs/armeabi-v7a/libspeex.so differ diff --git a/app/libs/armeabi-v7a/libvad.so b/app/libs/armeabi-v7a/libvad.so new file mode 100644 index 0000000..8823e30 Binary files /dev/null and b/app/libs/armeabi-v7a/libvad.so differ diff --git a/app/libs/armeabi/libailog2.so b/app/libs/armeabi/libailog2.so new file mode 100644 index 0000000..27f2051 Binary files /dev/null and b/app/libs/armeabi/libailog2.so differ diff --git a/app/libs/armeabi/libduidns.so b/app/libs/armeabi/libduidns.so new file mode 100644 index 0000000..6abe214 Binary files /dev/null and b/app/libs/armeabi/libduidns.so differ diff --git a/app/libs/armeabi/libduiitn.so b/app/libs/armeabi/libduiitn.so new file mode 100644 index 0000000..1f8817f Binary files /dev/null and b/app/libs/armeabi/libduiitn.so differ diff --git a/app/libs/armeabi/libduiutils.so b/app/libs/armeabi/libduiutils.so new file mode 100644 index 0000000..c80757c Binary files /dev/null and b/app/libs/armeabi/libduiutils.so differ diff --git a/app/libs/armeabi/libliteca.so b/app/libs/armeabi/libliteca.so new file mode 100644 index 0000000..6b6874e Binary files /dev/null and b/app/libs/armeabi/libliteca.so differ diff --git a/app/libs/armeabi/libmp3.so b/app/libs/armeabi/libmp3.so new file mode 100644 index 0000000..809c961 Binary files /dev/null and b/app/libs/armeabi/libmp3.so differ diff --git a/app/libs/armeabi/libopusogg.so b/app/libs/armeabi/libopusogg.so new file mode 100644 index 0000000..31c5ed6 Binary files /dev/null and b/app/libs/armeabi/libopusogg.so differ diff --git a/app/libs/armeabi/libspeex.so b/app/libs/armeabi/libspeex.so new file mode 100644 index 0000000..647ebd4 Binary files /dev/null and b/app/libs/armeabi/libspeex.so differ diff --git a/app/libs/armeabi/libvad.so b/app/libs/armeabi/libvad.so new file mode 100644 index 0000000..d88be80 Binary files /dev/null and b/app/libs/armeabi/libvad.so differ diff --git a/app/src/main/assets/vad_aihome_v0.11.bin b/app/src/main/assets/vad_aihome_v0.11.bin new file mode 100644 index 0000000..a609b40 Binary files /dev/null and b/app/src/main/assets/vad_aihome_v0.11.bin differ diff --git a/app/src/main/java/qianmu/container/activity/H5/UpdateFileActivity.java b/app/src/main/java/qianmu/container/activity/H5/UpdateFileActivity.java index 55e6610..0ba4156 100644 --- a/app/src/main/java/qianmu/container/activity/H5/UpdateFileActivity.java +++ b/app/src/main/java/qianmu/container/activity/H5/UpdateFileActivity.java @@ -16,8 +16,6 @@ import androidx.databinding.DataBindingUtil; import com.alibaba.android.arouter.facade.annotation.Route; import com.alibaba.android.arouter.launcher.ARouter; -import com.iflytek.sparkchain.core.SparkChain; -import com.iflytek.sparkchain.core.SparkChainConfig; import com.sdkapi.api.SdkApi; import java.io.File; @@ -255,23 +253,6 @@ public class UpdateFileActivity extends BaseActivity { SdkApi.newInstance(this); } - if("kdxf".equals(Constant.TTSFac)){ - Log.d("MainActivity: ","initKDXFSDK"); - // 初始化SDK,Appid等信息在清单中配置 - SparkChainConfig sparkChainConfig = SparkChainConfig.builder(); - sparkChainConfig.appID(getResources().getString(R.string.appid)) - .apiKey(getResources().getString(R.string.apikey)) - .apiSecret(getResources().getString(R.string.apiSecret))//应用申请的appid三元组 - .logLevel(666); - int ret = SparkChain.getInst().init(getApplicationContext(),sparkChainConfig); - String result; - if(ret == 0){ - result = "SDK初始化成功,请选择相应的功能点击体验。"; - }else{ - result = "SDK初始化失败,错误码:" + ret; - } - Log.e("MainActivity: ",result); - } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if(!Environment.isExternalStorageManager()){ Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); @@ -280,6 +261,7 @@ public class UpdateFileActivity extends BaseActivity { return; } } + //设置开机自启应用 if(Constant.androidBoardType.equals("smt")){ MyApplication.getInstance().getSmdt().sys_setSystemBootApp(MyApplication.getInstance().getPackageName()); diff --git a/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java b/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java index 22623b3..4ebd9f0 100644 --- a/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java +++ b/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java @@ -32,31 +32,20 @@ import androidx.annotation.NonNull; import androidx.databinding.DataBindingUtil; import androidx.recyclerview.widget.GridLayoutManager; +import com.aispeech.AIError; +import com.aispeech.AIResult; +import com.aispeech.common.AIConstant; +import com.aispeech.common.JSONResultParser; +import com.aispeech.export.config.AICloudASRConfig; +import com.aispeech.export.engines2.AICloudASREngine; +import com.aispeech.export.intent.AICloudASRIntent; +import com.aispeech.export.listeners.AIASRListener; import com.alibaba.android.arouter.facade.annotation.Route; import com.alibaba.android.arouter.launcher.ARouter; -import com.google.gson.Gson; -import com.iflytek.sparkchain.core.asr.ASR; -import com.iflytek.sparkchain.core.asr.AsrCallbacks; -import com.iflytek.sparkchain.core.asr.Segment; -import com.iflytek.sparkchain.core.asr.Transcription; -import com.iflytek.sparkchain.core.asr.Vad; -import com.shockman.sm.vendor.IHttp; -import com.shockman.sm.vendor.SmUtils; -import com.shockman.sm.vendor.TargetVo; import org.greenrobot.eventbus.EventBus; -import org.java_websocket.drafts.Draft_6455; -import org.java_websocket.enums.ReadyState; -import java.io.File; -import java.net.URI; import java.text.SimpleDateFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Scanner; -import java.util.concurrent.Executors; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import qianmu.container.R; import qianmu.container.activity.BaseActivity; @@ -64,24 +53,12 @@ import qianmu.container.adapter.KeyAdapter; import qianmu.container.app.Constant; import qianmu.container.app.MyApplication; import qianmu.container.data.AppData; -import qianmu.container.data.DeviceData; import qianmu.container.data.ScreenSaverData; import qianmu.container.databinding.ActivityWebviewBinding; -import qianmu.container.entity.AppVersion; -import qianmu.container.entity.KdxfBean; import qianmu.container.entity.MessageEvent; -import qianmu.container.entity.ResourceFileBean; -import qianmu.container.entity.ScreenSaver; -import qianmu.container.entity.TTSMessage; -import qianmu.container.entity.Vocbean; -import qianmu.container.listener.QueryFinishListener; import qianmu.container.socket.SocketClient; -import qianmu.container.util.AppUtil; -import qianmu.container.util.AudioPlay; import qianmu.container.util.CalendarUtils; import qianmu.container.util.DeviceUtil; -import qianmu.container.util.FileUtil; -import qianmu.container.util.GsonUtil; import qianmu.container.util.KeyboardUtil; import qianmu.container.util.LoggerUtil; import qianmu.container.util.StringUtil; @@ -103,13 +80,10 @@ public class WebViewActivity extends BaseActivity { //static String HtmlUrl = "http://192.168.1.196:5173/"; int time = 0; private VideoView currentVideo; - SocketClient localSocketClient; // 语音听写对象 - private ASR mAsr; - private boolean isrun = false; // 是否正在听写 - private boolean isdws = false; // 是否可以修正 - private String language = "zh_cn"; + private AICloudASREngine mEngine; + private AICloudASRIntent aiCloudASRIntent; private TTSUtil ttsUtil; Handler handler = new Handler() { @@ -176,8 +150,6 @@ public class WebViewActivity extends BaseActivity { //设置密码 initPass(); if("sbc".equals(Constant.TTSFac)){ // 思必驰 - connectLocalSocket(); - }else{ //kdxf initASR(); ttsUtil = new TTSUtil(); ttsUtil.initTts(); @@ -422,7 +394,6 @@ public class WebViewActivity extends BaseActivity { @Override protected void onDestroy() { super.onDestroy(); - destroyLocalSocketClient(); LoggerUtil.e(TAG, "onDestroy()"); } @@ -447,7 +418,6 @@ public class WebViewActivity extends BaseActivity { }); binding.web.addJavascriptInterface(new AndroidtoJs(), "android"); } - int count = 0; // JS 调用 android public class AndroidtoJs extends Object { // 回到屏保页面 @@ -484,25 +454,12 @@ public class WebViewActivity extends BaseActivity { public void startRecord() { LoggerUtil.e(TAG,"JS调用了Android的方法:startRecord()"); if("sbc".equals(Constant.TTSFac)) { - if (localSocketClient == null) initLocalSocketClient(); //------------------------------- - localSocketClient.send(StringUtil.strSplice("{\"method\":\"/tts/stop\"}")); - localSocketClient.send(StringUtil.strSplice("{\"method\":\"/asr/start\"}")); - }else{ - if(isrun){ - return; - } ttsUtil.stopTTs(); - if(mAsr == null){ + if(mEngine == null){ LoggerUtil.d(TAG, "未初始化"); initASR(); } - count++; - int ret = mAsr.startListener(count+""); - if(ret != 0){ - LoggerUtil.d(TAG,"识别开启失败,错误码:"+ret+"\n"); - }else{ - isrun = true; - } + mEngine.start(aiCloudASRIntent); } runOnUiThread(new Runnable() { @Override @@ -516,9 +473,6 @@ public class WebViewActivity extends BaseActivity { public void stopRecord() { LoggerUtil.e(TAG,"JS调用了Android的方法:stopRecord()"); if("sbc".equals(Constant.TTSFac)) { - if (localSocketClient == null) initLocalSocketClient(); //------------------------------- - localSocketClient.send(StringUtil.strSplice("{\"method\":\"/asr/stop\"}")); - }else{ stopAsr(); } } @@ -527,9 +481,6 @@ public class WebViewActivity extends BaseActivity { public void startTTS(String txt) { LoggerUtil.e(TAG,"JS调用了Android的方法:startTTS()"); if("sbc".equals(Constant.TTSFac)) { - if (localSocketClient == null) initLocalSocketClient(); //------------------------------- - localSocketClient.send(StringUtil.strSplice("{\"method\": \"/tts/start\",\"params\": {\"text\":\"", txt, "\", \"mode\":\"autoPlay\"}}")); - }else{ ttsUtil.startTTs(txt); } } @@ -538,9 +489,6 @@ public class WebViewActivity extends BaseActivity { public void stopTTS() { LoggerUtil.e(TAG,"JS调用了Android的方法:stopTTS()"); if("sbc".equals(Constant.TTSFac)){ - if (localSocketClient == null) initLocalSocketClient(); //------------------------------- - localSocketClient.send(StringUtil.strSplice("{\"method\":\"/tts/stop\"}")); - }else{ ttsUtil.stopTTs(); } runOnUiThread(new Runnable() { @@ -611,37 +559,26 @@ public class WebViewActivity extends BaseActivity { //-------- 科大讯飞 private void initASR(){ - if(mAsr == null){ - mAsr = new ASR(); - mAsr.registerCallbacks(mAsrCallbacks); - mAsr.language(language);//语种,zh_cn:中文,en_us:英文。其他语种参见集成文档 - mAsr.domain("iat");//应用领域,iat:日常用语。其他领域参见集成文档 - mAsr.accent("mandarin");//方言,mandarin:普通话。方言仅当language为中文时才会生效。其他方言参见集成文档。 - mAsr.vinfo(true);//返回子句结果对应的起始和结束的端点帧偏移值。 - if("zh_cn".equals(language)){ - mAsr.dwa("wpgs");//动态修正 - } + if(mEngine == null){ + AICloudASRConfig config = new AICloudASRConfig(); + config.setLocalVadEnable(true); + config.setVadResource("vad_aihome_v0.11.bin"); + mEngine = AICloudASREngine.createInstance(); + aiCloudASRIntent = new AICloudASRIntent(); + aiCloudASRIntent.setRealback(true);//打开实时反馈功能 + aiCloudASRIntent.setResourceType("aihome"); + aiCloudASRIntent.setEnableNumberConvert(true);//设置启用识别结果汉字数字转阿拉伯数字功能 + aiCloudASRIntent.setWaitingTimeout(5000);//设置等待识别结果超时时长,默认5000ms + aiCloudASRIntent.setNoSpeechTimeOut(2000); + aiCloudASRIntent.setPauseTime(1000); + mEngine.init(config, new AIASRListenerImpl()); } } - AsrCallbacks mAsrCallbacks = new AsrCallbacks() { - @Override - public void onResult(ASR.ASRResult asrResult, Object o) { - //以下信息需要开发者根据自身需求,如无必要,可不需要解析执行。 - int status = asrResult.getStatus(); //结果数据状态,0:识别的第一块结果,1:识别中间结果,2:识别最后一块结果 - String result = asrResult.getBestMatchText(); //识别结果 - if(status == 0){ - voiceContent(result); - }else if(status == 2){ - voiceContent(result); - stopAsr(); - }else{ - voiceContent(result); - } - } + private class AIASRListenerImpl implements AIASRListener { - @Override - public void onError(ASR.ASRError asrError, Object o) { + public void onError(AIError error) { + LoggerUtil.e("ASRInit: ",error.getMessage()); // 在非主线程中需要调用 WebView 方法时 runOnUiThread(new Runnable() { @Override @@ -652,28 +589,82 @@ public class WebViewActivity extends BaseActivity { stopAsr(); } + public void onResults(AIResult results) { + if (results.getResultType() == AIConstant.AIENGINE_MESSAGE_TYPE_JSON) { + JSONResultParser parser = new JSONResultParser((String) results.getResultObject()); + if("".equals(parser.getAllText())) { + voiceContent(parser.getVar()); + } + } + } + + @Override + public void onInit(int status) { + if (status == AIConstant.OPT_SUCCESS) { + LoggerUtil.e("ASRInit: ","初始化成功!"); + } else { + LoggerUtil.e("ASRInit: ","初始化失败!code:" + status); + } + } + @Override - public void onBeginOfSpeech() { + public void onBeginningOfSpeech() { + //本地vad打开时,才会执行 + LoggerUtil.e("ASRInit: ","onBeginningOfSpeech"); + } + @Override + public void onNotOneShot() { + //do nothing + LoggerUtil.e("ASRInit: ","onNotOneShot"); } @Override public void onEndOfSpeech() { - Log.d(TAG, "结束说话"); + //本地vad打开时,才会执行 runOnUiThread(new Runnable() { @Override public void run() { binding.web.evaluateJavascript("javascript: window.youAskOver('');", null); } }); + LoggerUtil.e("ASRInit: ","onEndOfSpeech"); } - }; + + @Override + public void onReadyForSpeech() { + LoggerUtil.e("ASRInit: ","onReadyForSpeech"); + } + + @Override + public void onResultDataReceived(byte[] buffer, int size, int wakeupType) { + LoggerUtil.e("ASRInit: ","onReadyForSpeech "+String.valueOf(size)); + } + + @Override + public void onRmsChanged(float rmsdB) { + Log.d(TAG, "" + rmsdB); + } + + @Override + public void onResultDataReceived(byte[] buffer, int size) { + //do nothing + } + + @Override + public void onRawDataReceived(byte[] buffer, int size) { + //do nothing + LoggerUtil.e("ASRInit: ","onRawDataReceived "+String.valueOf(size)); + } + + } + /** * android调用js:传送识别语音内容 */ public void voiceContent(String msg) { if (binding.web != null) { - LoggerUtil.e(TAG, "android调用js方法:voiceContent(),语音内容:" + msg); + LoggerUtil.e(TAG, "android调用js方法:giveAskText(),语音内容:" + msg); runOnUiThread(new Runnable() { @Override public void run() { @@ -683,110 +674,9 @@ public class WebViewActivity extends BaseActivity { } } private void stopAsr(){ - if(isrun){ - if(mAsr!=null){ - mAsr.stopListener(false); - } - isrun = false; - } - } - - // 思必驰---------------- - private void initLocalSocketClient() { - try { - URI localUri = new URI("ws://127.0.0.1:50002"); - LoggerUtil.e("TTSSocketUri", localUri.toString()); - localSocketClient = new SocketClient(localUri, new Draft_6455()); - setLocalSocketListener(); - } catch (Throwable t) { - LoggerUtil.e("initSocketClient", StringUtil.getThrowableStr(t)); - } - } - public void connectLocalSocket() { - try { - //客户端不存在时 创建客户端设置监听事件 - if (localSocketClient == null) initLocalSocketClient(); - //获取客户端当前的连接状态 - ReadyState state = localSocketClient.getReadyState(); - LoggerUtil.e("connectLocalSocket", "TTS客户端连接状态:"+ GsonUtil.getGson().toJson(state)); - boolean open = localSocketClient.isOpen(); - LoggerUtil.e("connectLocalSocket", "TTS客户端连接状态:open="+open); - if (open) return; - //获取客户端当前的连接状态 - if (localSocketClient.isOpen()) return; - //未连接状态时 连接服务器 - if (state.equals(ReadyState.NOT_YET_CONNECTED)) localSocketClient.connect(); - else if (state.equals(ReadyState.CLOSING) || state.equals(ReadyState.CLOSED)) { - //正在关闭或者关闭状态时 重新连接服务器 - localSocketClient.reconnect(); - } - } catch (Throwable t) { - LoggerUtil.e("connectLocalSocket", StringUtil.getThrowableStr(t)); - destroyLocalSocketClient(); + if(mEngine!=null){ + mEngine.cancel(); } } - //语音交互 - private void setLocalSocketListener() { - localSocketClient.setOnOpenListener((handshakeData) -> { - LoggerUtil.e("connectLocalSocket", "TTS客户端连接成功"); - localSocketClient.send(StringUtil.strSplice("{\"method\":\"/asr/stop\"}")); - }); - - localSocketClient.setOnMessageListener((conn, message) -> { - try { - TTSMessage messageBean = new Gson().fromJson(message, TTSMessage.class); - TTSMessage.Params content = messageBean.getParams(); - if (content == null) return; - String method = messageBean.getMethod(); - if("asr.text".equals(method)){ - LoggerUtil.e("ttsSocket:",content.getText()); - runOnUiThread(new Runnable() { - @Override - public void run() { - binding.web.loadUrl(StringUtil.strSplice("javascript:window.giveAskText('", content.getText(), "');")); - } - }); - }else if("asr.result".equals(method)){ - LoggerUtil.e("ttsSocket:",content.getText()); - runOnUiThread(new Runnable() { - @Override - public void run() { - localSocketClient.send(StringUtil.strSplice("{\"method\":\"/asr/stop\"}")); - binding.web.loadUrl(StringUtil.strSplice("javascript:window.youAskOver('", content.getText(), "');")); - } - }); - }else if("tts.result".equals(method)){ - LoggerUtil.e("ttsSocket:", messageBean.getParams().getStatus().trim()); - if("end".equals(messageBean.getParams().getStatus().trim())) { - runOnUiThread(new Runnable() { - @Override - public void run() { - changeVideo("bg"); - } - }); - } - } - } catch (Throwable t) { - LoggerUtil.e("setOnMessageListener", StringUtil.getThrowableStr(t)); - } - }); - - localSocketClient.setOnCloseListener((code, reason, remote) -> { - LoggerUtil.e("LocSocCliManager", "onClose:code="+code); - if (localSocketClient == null){ - initLocalSocketClient(); - }else { - localSocketClient.reconnect(); - } - - }); - localSocketClient.setOnErrorListener((ex) -> LoggerUtil.e("LocSocCliManager", "onError")); - } - //销毁当前的客户端 - public void destroyLocalSocketClient() { - if (localSocketClient == null) return; - localSocketClient.close(); - localSocketClient = null; - } } diff --git a/app/src/main/java/qianmu/container/app/Constant.java b/app/src/main/java/qianmu/container/app/Constant.java index 8d75107..ba594c9 100644 --- a/app/src/main/java/qianmu/container/app/Constant.java +++ b/app/src/main/java/qianmu/container/app/Constant.java @@ -23,7 +23,7 @@ public class Constant { public static boolean newGuide = false; // 指路机类型,true:新版指路机 false:老板指路机(流花) public static String mqttState = ""; // 屏幕连接方式 // public static String androidBoardType = ""; //设备板子型号 无固定版 - // public static String androidBoardType = "ys"; // 设备板子型号 ys(亿晟) 北京颐堤港定制touch + public static String androidBoardType = "ys"; // 设备板子型号 ys(亿晟) 北京颐堤港定制touch // public static String androidBoardType = "xwst"; //设备板子型号 xwst(欣威视通3399) // public static String androidBoardType = "xwst2"; //设备板子型号 xwst2(欣威视通3588、T982、3576) // public static String androidBoardType = "zc"; //设备板子型号 zc(卓策主板——王府井喜悦、杨浦中心医院) @@ -31,7 +31,7 @@ public class Constant { // public static String androidBoardType = "nova"; //设备板子型号 诺瓦盒子 华贸LED // public static String androidBoardType = "huidu"; //设备板子型号 huidu(灰度主板) 罗湖寻车机 // public static String androidBoardType = "bv"; //设备板子型号 Bv-3588M - public static String androidBoardType = "smt"; //设备板子型号 视美泰 + // public static String androidBoardType = "smt"; //设备板子型号 视美泰 public static String TTSFac = "sbc"; // 语音识别厂家 kdxf--科大讯飞 sbc-思必驰 public static final String VOID_STOP = "void_stop";// diff --git a/app/src/main/java/qianmu/container/app/MyApplication.java b/app/src/main/java/qianmu/container/app/MyApplication.java index 1b568f5..89e7888 100644 --- a/app/src/main/java/qianmu/container/app/MyApplication.java +++ b/app/src/main/java/qianmu/container/app/MyApplication.java @@ -7,7 +7,10 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.PowerManager; +import android.util.Log; +import com.aispeech.DUILiteConfig; +import com.aispeech.DUILiteSDK; import com.alibaba.android.arouter.BuildConfig; import com.alibaba.android.arouter.launcher.ARouter; import com.jakewharton.processphoenix.ProcessPhoenix; @@ -81,9 +84,35 @@ public class MyApplication extends Application { if (Constant.androidBoardType.equals("smt")) { smdt = SmdtManagerNew.getInstance(this); } + if(Constant.TTSFac.equals("sbc")){ + initSbcSDK(); + } // refWatcher = LeakCanary.install(this); } + private void initSbcSDK(){ + // 产品认证需设置 apiKey, productId, productKey, productSecret + DUILiteConfig config = new DUILiteConfig.Builder() + .setApiKey("d823edab41b8d823edab41b868ecc552") + .setProductId("279632533") + .setProductKey("ab73065d16e11bcfac026eee3db9f6cb") + .setProductSecret("85d9490c438099acc33be7676799399f").create(); + + DUILiteSDK.init(getApplicationContext()); + // SDK 授权 + DUILiteSDK.doAuth(getApplicationContext(), config, new DUILiteSDK.InitListener() { + @Override + public void success() { + LoggerUtil.d("DUILiteSDKInit: ", "授权成功! "); + } + + @Override + public void error(String errorCode,String errorInfo) { + LoggerUtil.d("DUILiteSDKInit: ", "授权失败, errorcode: "+errorCode+",errorInfo:"+errorInfo); + } + }); + } + public Lztek getLztek() { if (lztek == null) { lztek = Lztek.create(this.getBaseContext()); diff --git a/app/src/main/java/qianmu/container/util/TTSUtil.java b/app/src/main/java/qianmu/container/util/TTSUtil.java index 55f9f3e..9f93487 100644 --- a/app/src/main/java/qianmu/container/util/TTSUtil.java +++ b/app/src/main/java/qianmu/container/util/TTSUtil.java @@ -1,20 +1,18 @@ package qianmu.container.util; -import android.media.AudioFormat; -import android.media.AudioManager; -import android.media.AudioTrack; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; + import android.util.Log; -import androidx.annotation.NonNull; -import com.iflytek.sparkchain.core.tts.OnlineTTS; -import com.iflytek.sparkchain.core.tts.TTS; -import com.iflytek.sparkchain.core.tts.TTSCallbacks; + +import com.aispeech.AIError; +import com.aispeech.common.AIConstant; +import com.aispeech.export.config.AICloudTTSConfig; +import com.aispeech.export.engines2.AICloudTTSEngine; +import com.aispeech.export.intent.AICloudTTSIntent; +import com.aispeech.export.listeners.AITTSListener; import org.greenrobot.eventbus.EventBus; +import org.json.JSONArray; import qianmu.container.app.Constant; import qianmu.container.entity.MessageEvent; @@ -22,158 +20,99 @@ import qianmu.container.entity.MessageEvent; public class TTSUtil { private static String TAG = "TTS: "; // 语音合成对象 - private OnlineTTS mOnlineTTS; - private int sampleRate = 16000; - - TTSCallbacks mTTSCallback = new TTSCallbacks() { - - @Override - public void onResult(TTS.TTSResult result, Object o) { - //解析获取的交互结果,示例展示所有结果获取,开发者可根据自身需要,选择获取。 - byte[] audio = result.getData();//音频数据 - int status = result.getStatus();//数据状态 - - Bundle bundle = new Bundle(); - bundle.putByteArray("audio", audio); - Message msg = mAudioPlayHandler.obtainMessage(); - msg.what = AUDIOPLAYER_WRITE; - msg.obj = bundle; - mAudioPlayHandler.sendMessage(msg); - if(status == 2){ - //音频合成回调结束状态,注意,此状态不是播报完成状态 - mAudioPlayHandler.sendEmptyMessage(AUDIOPLAYER_END); - } - } + private AICloudTTSEngine mEngine; + private AICloudTTSIntent intent; - @Override - public void onError(TTS.TTSError ttsError, Object o) { - int errCode = ttsError.getCode();//错误码 - String errMsg = ttsError.getErrMsg();//错误信息 - LoggerUtil.d(TAG, "onError:errCode:" + errCode+ ",errMsg:" + errMsg); - //如果此时已经播报,则停止播报 - EventBus.getDefault().post(new MessageEvent(Constant.VOID_STOP)); - stopTTs(); - } - }; public void initTts(){ - mAudioPlayThread.start(); - // 初始化合成对象 发音人 - mOnlineTTS = new OnlineTTS("xiaoyan"); //xiaoyan + mEngine = AICloudTTSEngine.createInstance(); + AICloudTTSConfig config = new AICloudTTSConfig(); + config.setUseCache(false); + mEngine.init(config, new AITTSListener() { + @Override + public void onInit(int status) { + Log.d(TAG, "onInit()"); + if (status == AIConstant.OPT_SUCCESS) { + Log.i(TAG, "初始化成功!"); + } else { + Log.i(TAG, "初始化失败!"); + } + } + + @Override + public void onError(String utteranceId, AIError error) { + Log.e(TAG, "onError: " + utteranceId + "," + error.toString()); + EventBus.getDefault().post(new MessageEvent(Constant.VOID_STOP)); + } + + @Override + public void onReady(String utteranceId) { + Log.e(TAG, "onReady: " + utteranceId); + } + + @Override + public void onCompletion(String utteranceId) { + LoggerUtil.e(TAG, "onCompletion: " + utteranceId); + EventBus.getDefault().post(new MessageEvent(Constant.VOID_STOP)); + } + + @Override + public void onProgress(int currentTime, int totalTime, boolean isRefTextTTSFinished) { + } + + @Override + public void onSynthesizeStart(String utteranceId) { + } + + @Override + public void onSynthesizeDataArrived(String utteranceId, byte[] audioData) { + } + + @Override + public void onSynthesizeFinish(String utteranceId) { + } + + @Override + public void onTimestampReceived(byte[] bytes, int i) { + } + + @Override + public void onPhonemesDataArrived(String s, String s1) { + } + + @Override + public void onHighInfoReceived(JSONArray textArray, int curIndex, int curDuration, int curStart) { + Log.d("onHighInfoReceived", "textArray = " + textArray + ", curText="+textArray.optString(curIndex)+",duration = " + curDuration + ", curStart = " + curStart); + } + }); + + intent = new AICloudTTSIntent(); + intent.setSpeaker("qianranfv5"); + intent.setVolume("100"); + intent.setSpeed("0.8"); + intent.setTextType("text"); + intent.setSpeakingStyle("happy"); + intent.setHighLightInfo(false); } //开始听写 public void startTTs(String texts){ - if (null == mOnlineTTS) { + if (null == mEngine) { LoggerUtil.d(TAG, "未初始化"); initTts(); } - if(audioTrack == null){ - mAudioPlayHandler.sendEmptyMessage(AUDIOPLAYER_INIT); - }else{ - mAudioPlayHandler.sendEmptyMessage(AUDIOPLAYER_START); - } - setParam(); - // 合成并播放 - int ret = mOnlineTTS.aRun(texts); - if(ret!=0){ - LoggerUtil.d(TAG, "语音合成失败" ); - } + LoggerUtil.e(TAG, texts); + mEngine.speak(intent, texts, "1024"); } //停止听写 public void stopTTs(){ LoggerUtil.d(TAG, "手动暂停播放"); - if (null == mOnlineTTS) { - LoggerUtil.d(TAG, "未初始化"); - return; - } - mAudioPlayHandler.removeCallbacksAndMessages(null); - mAudioPlayHandler.sendEmptyMessage(AUDIOPLAYER_END); - mOnlineTTS.stop(); + mEngine.stop(); } - /** - * 参数设置 - * - * @return - */ - private void setParam() { - mOnlineTTS.aue("raw"); - mOnlineTTS.auf("audio/L16;rate="+sampleRate); // 8K 或 16K - mOnlineTTS.speed(60);//语速:0对应默认语速的1/2,100对应默认语速的2倍。最⼩值:0, 最⼤值:100 - mOnlineTTS.pitch(50);//语调:0对应默认语速的1/2,100对应默认语速的2倍。最⼩值:0, 最⼤值:100 - mOnlineTTS.volume(80);//音量:0是静音,1对应默认音量1/2,100对应默认音量的2倍。最⼩值:0, 最⼤值:100 - mOnlineTTS.bgs(0); //合成音频的背景音 0:无背景音(默认值) 1:有背景音 - mOnlineTTS.tte("UTF8"); - mOnlineTTS.registerCallbacks(mTTSCallback); - } - - /** - * 播放器,用于播报合成的音频。 - * 注意:当前Demo中的播放器仅实现了播放PCM格式的音频,如果客户合成的是其他格式的音频,需自行实现播放功能。 - */ - private static final int AUDIOPLAYER_INIT = 0x0000; - private static final int AUDIOPLAYER_START = 0x0001; - private static final int AUDIOPLAYER_WRITE = 0x0002; - private static final int AUDIOPLAYER_END = 0x0003; - private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_OUT_MONO; // 单声道输出 - private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; // PCM 16位编码 - private AudioTrack audioTrack; - private Handler mAudioPlayHandler; - private boolean isPlaying = false; - int count = 0; - private Thread mAudioPlayThread = new Thread(new Runnable() { - @Override - public void run() { - Looper.prepare(); - mAudioPlayHandler = new Handler(Looper.myLooper()){ - @Override - public void handleMessage(@NonNull Message msg) { - super.handleMessage(msg); - switch(msg.what){ - case AUDIOPLAYER_INIT: - Log.d(TAG,"audioInit"); - int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, CHANNEL_CONFIG, AUDIO_FORMAT); - audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, CHANNEL_CONFIG, AUDIO_FORMAT, minBufferSize, AudioTrack.MODE_STREAM); - mAudioPlayHandler.sendEmptyMessage(AUDIOPLAYER_START); - break; - case AUDIOPLAYER_START: - Log.d(TAG,"audioStart"); - if(audioTrack!=null) { - isPlaying = true; - audioTrack.play(); - } - break; - case AUDIOPLAYER_WRITE: - count ++; - if(count%5 == 0){ - Log.d(TAG,"audioWrite"); - count = 0; - } - Bundle bundle = (Bundle) msg.obj; - byte[] audioData = bundle.getByteArray("audio"); - if(audioTrack!=null&&audioData.length>0){ - audioTrack.write(audioData,0,audioData.length); - } - break; - case AUDIOPLAYER_END: - Log.d(TAG,"audioEnd"); - EventBus.getDefault().post(new MessageEvent(Constant.VOID_STOP)); - if(audioTrack!=null) { - audioTrack.stop(); - audioTrack.release(); - audioTrack = null; - isPlaying = false; - } - break; - - } - } - }; - Looper.loop(); - } - }); } + +