diff --git a/app/build.gradle b/app/build.gradle index 65bc240..996b129 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles 'consumer-rules.pro' - ndk { abiFilters "armeabi-v7a" } - + ndk { abiFilters "armeabi-v7a", "arm64-v8a" } + // "armeabi-v7a" "arm64-v8a" javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] @@ -59,6 +59,9 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + packagingOptions { + doNotStrip "**/*.so" + } } packagingOptions { diff --git a/app/libs/armeabi/libailog2.so b/app/libs/armeabi/libailog2.so deleted file mode 100644 index 27f2051..0000000 Binary files a/app/libs/armeabi/libailog2.so and /dev/null differ diff --git a/app/libs/armeabi/libduidns.so b/app/libs/armeabi/libduidns.so deleted file mode 100644 index 6abe214..0000000 Binary files a/app/libs/armeabi/libduidns.so and /dev/null differ diff --git a/app/libs/armeabi/libduiitn.so b/app/libs/armeabi/libduiitn.so deleted file mode 100644 index 1f8817f..0000000 Binary files a/app/libs/armeabi/libduiitn.so and /dev/null differ diff --git a/app/libs/armeabi/libduiutils.so b/app/libs/armeabi/libduiutils.so deleted file mode 100644 index c80757c..0000000 Binary files a/app/libs/armeabi/libduiutils.so and /dev/null differ diff --git a/app/libs/armeabi/libliteca.so b/app/libs/armeabi/libliteca.so deleted file mode 100644 index 6b6874e..0000000 Binary files a/app/libs/armeabi/libliteca.so and /dev/null differ diff --git a/app/libs/armeabi/libmp3.so b/app/libs/armeabi/libmp3.so deleted file mode 100644 index 809c961..0000000 Binary files a/app/libs/armeabi/libmp3.so and /dev/null differ diff --git a/app/libs/armeabi/libopusogg.so b/app/libs/armeabi/libopusogg.so deleted file mode 100644 index 31c5ed6..0000000 Binary files a/app/libs/armeabi/libopusogg.so and /dev/null differ diff --git a/app/libs/armeabi/libspeex.so b/app/libs/armeabi/libspeex.so deleted file mode 100644 index 647ebd4..0000000 Binary files a/app/libs/armeabi/libspeex.so and /dev/null differ diff --git a/app/libs/armeabi/libvad.so b/app/libs/armeabi/libvad.so deleted file mode 100644 index d88be80..0000000 Binary files a/app/libs/armeabi/libvad.so and /dev/null differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 557e8d0..fb3a017 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,11 @@ + + + + + diff --git a/app/src/main/assets/wakeup_aifar_comm_h7_20210127.bin b/app/src/main/assets/wakeup_aifar_comm_h7_20210127.bin new file mode 100644 index 0000000..ebfdd8a Binary files /dev/null and b/app/src/main/assets/wakeup_aifar_comm_h7_20210127.bin differ 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 22a56f9..d373361 100644 --- a/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java +++ b/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java @@ -43,6 +43,7 @@ import com.aispeech.export.config.AILocalSignalAndWakeupConfig; import com.aispeech.export.engines2.AICloudASREngine; import com.aispeech.export.engines2.AILocalSignalAndWakeupEngine; import com.aispeech.export.intent.AICloudASRIntent; +import com.aispeech.export.intent.AILocalSignalAndWakeupIntent; import com.aispeech.export.listeners.AIASRListener; import com.aispeech.export.listeners.AILocalSignalAndWakeupListener; import com.alibaba.android.arouter.facade.annotation.Route; @@ -51,6 +52,7 @@ import com.alibaba.android.arouter.launcher.ARouter; import org.greenrobot.eventbus.EventBus; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -86,16 +88,15 @@ public class WebViewActivity extends BaseActivity { static final int TYPE_GO_SAVESCREEN = 300;//导视通知跳转屏保 static final int TYPE_HINT_PASSWORD = 3;//隐藏密码输入框 static final int TYPE_START_SERVER = 4;//重新启动web服务 - //static String HtmlUrl = "http://127.0.0.1:8080/index.html";//webServer服务地址 http://192.168.1.218:5173/ - static String HtmlUrl = "http://192.168.1.196:5173/"; //"http://192.168.0.109:5173/"; + static String HtmlUrl = "http://127.0.0.1:8080/index.html";//webServer服务地址 http://192.168.1.218:5173/ + //static String HtmlUrl = "http://192.168.1.196:5173/"; //"http://192.168.0.109:5173/"; int time = 0; private VideoView currentVideo; private SoundPool soundPool; private int soundId; // 语音听写对象 - private AILocalSignalAndWakeupEngine mLocalEngine; - private AICloudASREngine mEngine; - private AICloudASRIntent aiCloudASRIntent; + private AILocalSignalAndWakeupEngine mEngine; + private AICloudASREngine mAsrEngine; private TTSUtil ttsUtil; private String oldString=""; private Map videoMap = new HashMap<>(); @@ -832,12 +833,11 @@ public class WebViewActivity extends BaseActivity { public void startRecord() { LoggerUtil.e(TAG,"JS调用了Android的方法:startRecord()"); ttsUtil.stopTTs(); - stopAsr(); - if(mEngine == null){ + if(mAsrEngine == null){ LoggerUtil.d(TAG, "未初始化"); initASR(); } - mEngine.start(aiCloudASRIntent); + startEngine(); runOnUiThread(new Runnable() { @Override public void run() { @@ -933,34 +933,24 @@ public class WebViewActivity extends BaseActivity { //-------- private void initASR(){ - AILocalSignalAndWakeupConfig config = new AILocalSignalAndWakeupConfig(); - config.setSspeResource("sspe_aec-bf-bss-wkp_ch10-mic8-ref2_outgain4_v2.0.0.165_20251127_v1.bin");//设置SSPE资源 + config.setWakeupResource("wakeup_aifar_comm_h7_20210127.bin");//设置唤醒资源 + config.setSspeResource("sspe_aec-bf-bss-wkp_ch10-mic8-ref2_outgain4_v2.0.0.165_20251127_v1.bin"); //设置SSPE资源 + + config.setWakeupWord(new String[]{"ni hao xiao le"}, new int[]{1}); + config.setThreshold(new float[]{0.9f}); //设置唤醒词对应的阈值 config.setEchoChannelNum(2); - mLocalEngine = AILocalSignalAndWakeupEngine.createInstance(); - mLocalEngine.init(config, new SSPEListener()); - - if(mEngine == null){ - AICloudASRConfig asrconfig = new AICloudASRConfig(); - asrconfig.setLocalVadEnable(true); - asrconfig.setVadResource("vad_aihome_v0.12c_noDither.bin"); - mEngine = AICloudASREngine.createInstance(); - mEngine.init(asrconfig, new AIASRListenerImpl()); - - aiCloudASRIntent = new AICloudASRIntent(); - aiCloudASRIntent.setEnablePunctuation(true); - aiCloudASRIntent.setRealback(true);//打开实时反馈功能 - aiCloudASRIntent.setCloudVadEnable(false); - aiCloudASRIntent.setAudioType(AICloudASRIntent.PCM_ENCODE_TYPE.valueOf("WAV")); - aiCloudASRIntent.setResourceType(Constant.asrModel); - aiCloudASRIntent.setEnableNumberConvert(true);//设置启用识别结果汉字数字转阿拉伯数字功能 - aiCloudASRIntent.setWaitingTimeout(10000); //设置等待识别结果超时时长,默认5000ms - aiCloudASRIntent.setNoSpeechTimeOut(5000); - aiCloudASRIntent.setPauseTime(3000); - //aiCloudASRIntent.setUseCustomFeed(false); // 设置是否使用外部喂音频 - } + config.enableDulWakeupWithE2E(new String[]{"ni hao xiao le"}, new String[]{}, new float[]{0.9f}, new float[]{0.1f}); + mEngine = AILocalSignalAndWakeupEngine.createInstance(); + mEngine.init(config, new SSPEListener()); + + mAsrEngine = AICloudASREngine.createInstance(); + AICloudASRConfig asrconfig = new AICloudASRConfig(); + asrconfig.setLocalVadEnable(true); + asrconfig.setVadResource("vad_aihome_v0.12c_noDither.bin"); + mAsrEngine.init(asrconfig, new AIASRListenerImpl()); - //initRecorder(); //暂不开 + initRecorder(); } private void initRecorder() { @@ -968,22 +958,37 @@ public class WebViewActivity extends BaseActivity { IRecord.RecordConfig config = new IRecord.RecordConfig(); config.recorderType = IRecord.TYPE_JNI; config.audioChannel = 10; -// config.filter = new int[]{0, 1, 2, 3, 6, 7}; config.dump = true; // 不保存外部录音机收到的音频 AudioRecorder.getInstance().init(getApplicationContext(), config); } - public class RecorderListener implements AudioRecorder.RecorderListener { + private void startEngine(){ + AudioRecorder.getInstance().startRecord(); + AILocalSignalAndWakeupIntent intent = new AILocalSignalAndWakeupIntent(); + intent.setUseCustomFeed(true); + intent.setInputContinuousAudio(true); + mEngine.start(intent); + AICloudASRIntent aiCloudASRIntent = new AICloudASRIntent(); + aiCloudASRIntent.setRealback(true);//打开实时反馈功能 + aiCloudASRIntent.setCloudVadEnable(false); + aiCloudASRIntent.setAudioType(AICloudASRIntent.PCM_ENCODE_TYPE.WAV); + aiCloudASRIntent.setResourceType(Constant.asrModel); + aiCloudASRIntent.setEnableNumberConvert(true);//设置启用识别结果汉字数字转阿拉伯数字功能 + aiCloudASRIntent.setWaitingTimeout(10000); //设置等待识别结果超时时长,默认5000ms + aiCloudASRIntent.setNoSpeechTimeOut(5000); + aiCloudASRIntent.setPauseTime(3000); + aiCloudASRIntent.setUseCustomFeed(true); // 设置是否使用外部喂音频 + //aiCloudASRIntent.setServer("wss://asr.dui.ai/runtime/v2/recognize"); + mAsrEngine.start(aiCloudASRIntent); + LoggerUtil.e("ASRInit", "start asr engine"); + } + public class RecorderListener implements AudioRecorder.RecorderListener { @Override public void onAudioBuffer(byte[] data, int size) { - feedEngine(data, size); - } - } - - protected void feedEngine(byte[] data, int length) { - if (mLocalEngine != null) { - mLocalEngine.feedData(data, length); + if (mEngine != null) { + mEngine.feedData(data, size); + } } } @@ -1002,9 +1007,13 @@ public class WebViewActivity extends BaseActivity { } public void onResults(AIResult results) { - LoggerUtil.e("ASRInitResult: ", String.valueOf(results.isLast())); + LoggerUtil.e("ASRInitResult: ", String.valueOf(results)); + if (results.getResultType() == AIConstant.AIENGINE_MESSAGE_TYPE_JSON) { JSONResultParser parser = new JSONResultParser((String) results.getResultObject()); + if (parser.getEof() == 1) { + LoggerUtil.e("ASRInitResult: ",parser.getText()); + } if("".equals(parser.getVar()) && !"".equals(parser.getText())){ oldString = StringUtil.strSplice(oldString,parser.getText()); } @@ -1126,8 +1135,8 @@ public class WebViewActivity extends BaseActivity { @Override public void onResultDataReceived(byte[] bytes, int size, int wakeupType) { - if (mEngine != null) { - mEngine.feedData(bytes, size); + if (mAsrEngine != null) { + mAsrEngine.feedData(bytes, size); } } @@ -1190,9 +1199,13 @@ public class WebViewActivity extends BaseActivity { } private void stopAsr(){ if(mEngine != null){ - mEngine.cancel(); mEngine.stop(); } + if(mAsrEngine != null){ + mAsrEngine.cancel(); + mAsrEngine.stop(); + } + AudioRecorder.getInstance().stopRecord(); } } diff --git a/app/src/main/java/qianmu/container/app/MyApplication.java b/app/src/main/java/qianmu/container/app/MyApplication.java index 90865b3..f981cb3 100644 --- a/app/src/main/java/qianmu/container/app/MyApplication.java +++ b/app/src/main/java/qianmu/container/app/MyApplication.java @@ -92,8 +92,10 @@ public class MyApplication extends Application { } private void initSbcSDK(){ + DUILiteSDK.init(getApplicationContext()); + AuthConfig authConfig = new AuthConfig.Builder() - .setCustomDeviceName("ae28ccd49e9c53b9") // + .setCustomDeviceName("c3ffda1477043e88") // ae28ccd49e9c53b9 .setAuthTimeout(5000) .setLoadSerial(true) .setLoadMacAddress(true) @@ -114,21 +116,15 @@ public class MyApplication extends Application { .create(); config.setAudioRecorderType(13); - DUILiteSDK.init(getApplicationContext()); - - //DUILiteSDK.setGlobalAudioSaveEnable(true); //使能全局音频保存开关,此开关关闭则不保存音频.默认为开,但是需要设置下面的保存路径才能保存音频 - //DUILiteSDK.setGlobalAudioSavePath(Constant.CACHE_PATH); - - // SDK 授权 DUILiteSDK.doAuth(getApplicationContext(), config, new DUILiteSDK.InitListener() { @Override public void success() { DUILiteSDK.setGlobalDisableAudioSaveEngines(Engines.VPRINT); + DUILiteSDK.openGlobalAudioSave(Constant.CACHE_PATH2); LoggerUtil.d("DUILiteSDKInit: ", "授权成功! "); } - @Override - public void error(String errorCode,String errorInfo) { + public void error(String errorCode, String errorInfo) { LoggerUtil.d("DUILiteSDKInit: ", "授权失败, errorcode: "+errorCode+",errorInfo:"+errorInfo); } }); diff --git a/app/src/main/java/qianmu/container/recorder/AudioRecorder.java b/app/src/main/java/qianmu/container/recorder/AudioRecorder.java index b81057d..2adda33 100644 --- a/app/src/main/java/qianmu/container/recorder/AudioRecorder.java +++ b/app/src/main/java/qianmu/container/recorder/AudioRecorder.java @@ -16,6 +16,8 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; +import qianmu.container.util.LoggerUtil; + /** * Created by Android Studio. * User: gaozhilong @@ -32,28 +34,27 @@ public class AudioRecorder { private IRecord mRecorder; private FileOutputStream mDumpFileStream; private Context mContext; + private static AudioRecorder INSTANCE = null; private AudioRecorder() { } - private static class AudioRecorderHolder { - private static final AudioRecorder INSTANCE = new AudioRecorder(); - } public static AudioRecorder getInstance() { - return AudioRecorderHolder.INSTANCE; + if(INSTANCE == null){ + INSTANCE = new AudioRecorder(); + } + return INSTANCE; } public synchronized void init(Context context, IRecord.RecordConfig cfg) { - Log.i(TAG, "record cfg=" + cfg.toString()); + LoggerUtil.i(TAG, "record cfg=" + cfg.toString()); mConfig = cfg; mContext = context; if (mConfig.recorderType == TYPE_NATIVE) { mRecorder = new NativeRecorder(); } else if (mConfig.recorderType == TYPE_JNI) { mRecorder = new JniRecorder(); - } else if (mConfig.recorderType == TYPE_HOTWORD) { - } mRecorder.init(context, mConfig); mCurrentState = State.READY; @@ -67,47 +68,37 @@ public class AudioRecorder { } public synchronized void startRecord() { - Log.i(TAG, "startRecord"); + LoggerUtil.i(TAG, "startRecord"); if (mCurrentState == State.NO_READY) { - Log.e(TAG, "record not initialized"); return; } if (mCurrentState == State.START) { - Log.w(TAG, "already recording...ignore"); return; } - Log.d(TAG, "startRecord: ============startRecord begin============"); mRecorder.start(); new Thread(this::recordRead).start(); - Log.d(TAG, "startRecord: ============startRecord end============"); } public synchronized void stopRecord() { - Log.d(TAG, "stopRecord: ============stopRecord begin============"); - if (mCurrentState == State.NO_READY || mCurrentState == State.READY) { - Log.e(TAG, "record not started yet"); - } else { + if (mCurrentState != State.NO_READY && mCurrentState != State.READY) { mRecorder.stop(); mCurrentState = State.STOP; } - Log.d(TAG, "stopRecord: ============stopRecord end============"); } public void release() { - Log.d(TAG, "release: ============release begin============"); if (mRecorder != null) { mRecorder.release(); } mCurrentState = State.NO_READY; - Log.d(TAG, "release: ============release end============"); } private void recordRead() { byte[] audioData = new byte[mRecorder.getBufferSize()]; mCurrentState = State.START; + LoggerUtil.d("recordRead: ",String.valueOf(mRecorder.getBufferSize())); while (mCurrentState == State.START) { int size = mRecorder.read(audioData, 0, mRecorder.getBufferSize()); - byte[] publishBuffer; if (mConfig.filter != null) { publishBuffer = new byte[audioData.length / mConfig.audioChannel * mConfig.filter.length]; @@ -127,7 +118,6 @@ public class AudioRecorder { listener.onAudioBuffer(publishBuffer, publishBuffer.length); } } - dump(publishBuffer); } } @@ -136,7 +126,7 @@ public class AudioRecorder { public void registerListener(RecorderListener cb) { if (cb != null && !mListeners.contains(cb)) { - Log.i(TAG, "registerListener " + cb.toString()); + LoggerUtil.i(TAG, "registerListener " + cb.toString()); mListeners.add(cb); } } @@ -167,7 +157,7 @@ public class AudioRecorder { public void unregisterListener(RecorderListener cb) { if (cb != null && mListeners.contains(cb)) { - Log.i(TAG, "unregisterListener " + cb.toString()); + LoggerUtil.i(TAG, "unregisterListener " + cb.toString()); mListeners.remove(cb); } if (mListeners.isEmpty()) { @@ -183,12 +173,12 @@ public class AudioRecorder { File file = new File(dumpPath); if (!Objects.requireNonNull(file.getParentFile()).exists()) { if (file.getParentFile().mkdirs()) { - Log.i(TAG, "successfully created " + file.getParentFile().getPath()); + LoggerUtil.i(TAG, "successfully created " + file.getParentFile().getPath()); } } mDumpFileStream = new FileOutputStream(file); } catch (IllegalStateException | FileNotFoundException e) { - Log.e(TAG, "create audio data file error: " + e.getMessage()); + LoggerUtil.e(TAG, "create audio data file error: " + e.getMessage()); } } @@ -207,7 +197,7 @@ public class AudioRecorder { mDumpFileStream.flush(); mDumpFileStream.close(); } catch (IOException e) { - Log.e(TAG, "close audio data file error: " + e.getMessage()); + LoggerUtil.e(TAG, "close audio data file error: " + e.getMessage()); } } diff --git a/app/src/main/java/qianmu/container/util/SSLSocketClient.java b/app/src/main/java/qianmu/container/util/SSLSocketClient.java index f4c53a2..4da958d 100644 --- a/app/src/main/java/qianmu/container/util/SSLSocketClient.java +++ b/app/src/main/java/qianmu/container/util/SSLSocketClient.java @@ -44,11 +44,8 @@ public class SSLSocketClient { // 获取包装后的 SSLSocketFactory(强制绑定 TrustManager) public static SSLSocketFactory getSSLSocketFactory() { try { - // 1. 使用 TLSv1.2 协议(Android 14 强制要求) - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); - // 2. 绑定我们的 TrustManager + SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{X509}, new SecureRandom()); - // 3. 用自定义类包装,避免系统替换 return new CustomSSLSocketFactory(sslContext.getSocketFactory()); } catch (Exception e) { throw new RuntimeException("创建 SSLSocketFactory 失败", e);