|
- package com.aispeech.nativedemo;
-
- import android.annotation.TargetApi;
- import android.app.Notification;
- import android.app.PendingIntent;
- import android.app.Service;
- import android.content.Context;
- import android.content.Intent;
- import android.media.AudioFormat;
- import android.media.AudioManager;
- import android.os.Build;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Looper;
- import android.telephony.TelephonyManager;
- import android.text.TextUtils;
- import android.util.Base64;
- import android.util.Log;
- import android.widget.Toast;
-
- import com.aispeech.dui.dds.DDS;
- import com.aispeech.dui.dds.DDSAuthListener;
- import com.aispeech.dui.dds.DDSConfig;
- import com.aispeech.dui.dds.DDSConfigBuilder;
- import com.aispeech.dui.dds.DDSInitListener;
- import com.aispeech.dui.dds.DDSMode;
- import com.aispeech.dui.dds.agent.tts.TTSEngine;
- import com.aispeech.dui.dds.exceptions.DDSNotInitCompleteException;
- import com.aispeech.nativedemo.face.FaceManager;
- import com.aispeech.nativedemo.log.Logger;
- import com.aispeech.nativedemo.mqtt.MqttManager;
- import com.aispeech.nativedemo.network.ws.MessageUtils;
- import com.aispeech.nativedemo.network.ws.WebSocketManager;
- import com.aispeech.nativedemo.ui.LauncherActivity;
- import com.aispeech.nativedemo.config.Config;
-
- import org.json.JSONException;
- import org.json.JSONObject;
-
- import java.io.File;
- import java.io.IOException;
- import java.util.UUID;
-
- /**
- * 参见Android SDK集成文档: https://www.dui.ai/docs/operation/#/ct_common_Andriod_SDK
- */
- public class DDSService extends Service {
- public static final String TAG = "DDSService";
- private static boolean isStarted = false;
-
- public static int initCompleted = 0;
-
- public DDSService() {
- }
-
- public static Intent newDDSServiceIntent(Context context, String action) {
- Intent intent = new Intent(context, DDSService.class);
- intent.setAction(action);
- return intent;
- }
-
- @Override
- public void onCreate() {
- Log.i(TAG, "DDSService on create");
- isStarted = false;
- setForeground();
- super.onCreate();
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- @TargetApi(Build.VERSION_CODES.O)
- private void setForeground() {
- Intent intent = new Intent(DDSService.this, LauncherActivity.class);
- PendingIntent pi = PendingIntent.getActivity(DDSService.this, 0, intent, 0);
-
- Notification notification = Util.pupNotification(DDSService.this, pi, "DUI ...");
- startForeground(1, notification);
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- if (intent != null) {
- String action = intent.getAction();
- Log.i(TAG, "action:" + action);
- if (TextUtils.equals(action, "start")) {
- if (isStarted) {
- Log.i(TAG, "already started");
- return super.onStartCommand(intent, flags, startId);
- }
- init();
- isStarted = true;
- } else if (TextUtils.equals(action, "stop")) {
- //关闭timerstopRefreshTokenTimer()
- if (!isStarted) {
- Log.i(TAG, "already stopped");
- return super.onStartCommand(intent, flags, startId);
- }
- isStarted = false;
- DDS.getInstance().releaseSync();
- }
- }
- return super.onStartCommand(intent, flags, startId);
- }
-
- // 初始化dds组件
- private void init() {
- // DDS.getInstance().setDebugMode(2); //在调试时可以打开sdk调试日志,在发布版本时,请关闭
- DDS.getInstance().init(getApplicationContext(), createConfig(), mInitListener, mAuthListener);
- }
-
- // dds初始状态监听器,监听init是否成功
- private DDSInitListener mInitListener = new DDSInitListener() {
- @Override
- public void onInitComplete(boolean isFull) {
- Logger.e("思必驰初始化成功:onInitComplete " + isFull);
- if (isFull) {
- // 发送一个init成功的广播
- Logger.e("init face sdk");
- FaceManager.getInstance(DuiApplication.getContext()).initEngine();
- Logger.e("init face sdk over");
- sendBroadcast(new Intent("ddsdemo.intent.action.init_complete"));
- initCompleted = 1;
- try {
- DDS.getInstance().getAgent().getTTSEngine().setMode(TTSEngine.LOCAL);
- // DDS.getInstance().getAgent().getTTSEngine().setMode(DDSMode.TTS_SILENCE);
- // DDS.getInstance().getAgent().getTTSEngine().setSpeaker("zhilingfp");
- DDS.getInstance().getAgent().getTTSEngine().setSpeaker("hqqiaf","hqqiaf_lstm_210909.bin");
- } catch (DDSNotInitCompleteException e) {
- throw new RuntimeException(e);
- }
- Logger.e("思必驰--------");
- } else{
- Logger.e("思必驰++++++++++++++++++++");
- }
- DDS.getInstance().setAudioDebug(true);
-
- // startTtsListening();
- }
-
- @Override
- public void onError(int what, final String msg) {
- Logger.e("思必驰初始化失败:Init onError: " + what + ", error: " + msg);
- new Handler(Looper.getMainLooper()).post(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(getApplicationContext(), "初始化失败...", Toast.LENGTH_SHORT).show();
- }
- });
- }
- };
-
- // dds认证状态监听器,监听auth是否成功
- private DDSAuthListener mAuthListener = new DDSAuthListener() {
- @Override
- public void onAuthSuccess() {
- Log.d(TAG, "onAuthSuccess");
- }
-
- @Override
- public void onAuthFailed(final String errId, final String error) {
- Logger.e("思必驰认证成功:onAuthFailed: " + errId + ", error:" + error);
- new Handler(Looper.getMainLooper()).post(new Runnable() {
- @Override
- public void run() {
- MqttManager.getInstance(MainActivity.instance).getFileUploadPath(Config.ErrorEvent.ERROR_UPLOAD_WARNING, Config.ErrorEvent.ERROR_LEVEL_2, "speech_sdk_err_code", TAG);
-
- Toast.makeText(getApplicationContext(),
- "授权错误:" + errId + ":\n" + error + "\n请查看手册处理", Toast.LENGTH_SHORT).show();
- }
- });
- // 发送一个认证失败的广播
- sendBroadcast(new Intent("ddsdemo.intent.action.auth_failed"));
- }
- };
-
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- // 在退出app时将dds组件注销
- isStarted = false;
- DDS.getInstance().releaseSync();
- }
-
- // 创建dds配置信息
- private DDSConfig createConfig() {
- // 用户设置自己实现的单个功能,目前支持 wakeup 和 vad。WakeupII.class 是一个使用示例
- // DDS.getInstance().setOutsideEngine(IEngine.Name.WAKEUP_SINGLE_MIC, WakeupII.class);
- // DDSConfigBuilder builder = new DDSConfigBuilder(
- // "279616521",
- // "test",
- // "d797bc5edc9778f7d0ca8242643fa41a",
- // "e98db68bd807accc8eb12144c54ef1a1",
- // "6d7db9adbc8dbb5efd89e4d5bf46db7f",
- // "duicore.zip"
- // );
- // builder.createTtsBuilder().setAudioFocusMode("external");
- // DDSConfig config = builder.build();
- DDSConfig config = new DDSConfig();
- // 基础配置项
- // config.addConfig(DDSConfig.K_PRODUCT_ID, "279615550"); // 产品ID -- 必填
- // config.addConfig(DDSConfig.K_USER_ID, "aispeech"); // 用户ID -- 必填
- // config.addConfig(DDSConfig.K_ALIAS_KEY, "test"); // 产品的发布分支 -- 必填
- // config.addConfig(DDSConfig.K_PRODUCT_KEY, "1fc9d84d79c5b1861bbecbdae698d5a4");// Product Key -- 必填
- // config.addConfig(DDSConfig.K_PRODUCT_SECRET, "92c15b48b15820bace5b1c0cf4af614d");// Product Secre -- 必填
- // config.addConfig(DDSConfig.K_API_KEY, "0d78cbc00447ef5719a518d363b7ba8b"); // 产品授权秘钥,服务端生成,用于产品授权 -- 必填
- // config.addConfig(DDSConfig.K_DEVICE_ID, getDeviceId(getApplicationContext()));//填入唯一的deviceId -- 选填
-
- // config.addConfig(DDSConfig.K_PRODUCT_ID, "279617275"); // 产品ID -- 必填
- // config.addConfig(DDSConfig.K_USER_ID, "aispeech"); // 用户ID -- 必填
- // config.addConfig(DDSConfig.K_ALIAS_KEY, "test"); // 产品的发布分支 -- 必填
- // config.addConfig(DDSConfig.K_PRODUCT_KEY, "12b64c4441d654ecc0cc98e9797f9d28");// Product Key -- 必填
- // config.addConfig(DDSConfig.K_PRODUCT_SECRET, "2f8bdd769cc7de7294b061b0c1e0f89d");// Product Secre -- 必填
- // config.addConfig(DDSConfig.K_API_KEY, "d709678a1595dcf1e18956da6440cd6c"); // 产品授权秘钥,服务端生成,用于产品授权 -- 必填
- // config.addConfig(DDSConfig.K_DEVICE_ID, getDeviceId(getApplicationContext()));//填入唯一的deviceId -- 选填
-
- config.addConfig(DDSConfig.K_PRODUCT_ID, "279616521"); // 产品ID -- 必填
- config.addConfig(DDSConfig.K_USER_ID, "aispeech"); // 用户ID -- 必填
- config.addConfig(DDSConfig.K_ALIAS_KEY, "test"); // 产品的发布分支 -- 必填
- config.addConfig(DDSConfig.K_PRODUCT_KEY, "e98db68bd807accc8eb12144c54ef1a1");// Product Key -- 必填
- config.addConfig(DDSConfig.K_PRODUCT_SECRET, "6d7db9adbc8dbb5efd89e4d5bf46db7f");// Product Secre -- 必填
- config.addConfig(DDSConfig.K_API_KEY, "d797bc5edc9778f7d0ca8242643fa41a"); // 产品授权秘钥,服务端生成,用于产品授权 -- 必填
- config.addConfig(DDSConfig.K_DEVICE_ID, getDeviceId(getApplicationContext()));//填入唯一的deviceId -- 选填
- config.addConfig(DDSConfig.K_DEVICE_NAME, getDeviceId(getApplicationContext()));//填入唯一的deviceId -- 选填
- // config.addConfig(DDSConfig.K_AUDIO_FOCUS_MODE, "external");//填入唯一的deviceId -- 选填
-
- // config.addConfig(DDSConfig.K_PRODUCT_ID, "279617278"); // 产品ID -- 必填
- // config.addConfig(DDSConfig.K_USER_ID, "aispeech"); // 用户ID -- 必填
- // config.addConfig(DDSConfig.K_ALIAS_KEY, "test"); // 产品的发布分支 -- 必填
- // config.addConfig(DDSConfig.K_PRODUCT_KEY, "da09e6ff1a4ca4de4a6a447e596ed41e");// Product Key -- 必填
- // config.addConfig(DDSConfig.K_PRODUCT_SECRET, "6def485b9e41c80e1a24a9ca4d1865f4");// Product Secre -- 必填
- // config.addConfig(DDSConfig.K_API_KEY, "c27a9e478c3bbe8f87b03b266440e2ff"); // 产品授权秘钥,服务端生成,用于产品授权 -- 必填
- // config.addConfig(DDSConfig.K_DEVICE_ID, getDeviceId(getApplicationContext()));//填入唯一的deviceId -- 选填
-
- // 更多高级配置项,请参考文档: https://www.dui.ai/docs/ct_common_Andriod_SDK 中的 --> 四.高级配置项
-
- config.addConfig(DDSConfig.K_DUICORE_ZIP, "duicore.zip"); // 预置在指定目录下的DUI内核资源包名, 避免在线下载内核消耗流量, 推荐使用
- config.addConfig(DDSConfig.K_USE_UPDATE_DUICORE, "false"); //设置为false可以关闭dui内核的热更新功能,可以配合内置dui内核资源使用
-
- // 资源更新配置项
- config.addConfig(DDSConfig.K_CUSTOM_ZIP, "product.zip"); // 预置在指定目录下的DUI产品配置资源包名, 避免在线下载产品配置消耗流量, 推荐使用
- config.addConfig(DDSConfig.K_USE_UPDATE_NOTIFICATION, "false"); // 是否使用内置的资源更新通知栏
-
- // 录音配置项
- // config.addConfig(DDSConfig.K_RECORDER_MODE, "internal"); //录音机模式:external(使用外置录音机,需主动调用拾音接口)、internal(使用内置录音机,DDS自动录音)
- // config.addConfig(DDSConfig.K_IS_REVERSE_AUDIO_CHANNEL, "false"); // 录音机通道是否反转,默认不反转
- // config.addConfig(DDSConfig.K_AUDIO_SOURCE, AudioSource.DEFAULT); // 内置录音机数据源类型
- // config.addConfig(DDSConfig.K_AUDIO_BUFFER_SIZE, (16000 * 1 * 16 * 100 / 1000)); // 内置录音机读buffer的大小
-
- // TTS配置项
- // config.addConfig(DDSConfig.K_STREAM_TYPE, AudioManager.STREAM_MUSIC); // 内置播放器的STREAM类型
- // config.addConfig(DDSConfig.K_TTS_MODE, "internal"); // TTS模式:external(使用外置TTS引擎,需主动注册TTS请求监听器)、internal(使用内置DUI TTS引擎)
- // config.addConfig(DDSConfig.K_CUSTOM_TIPS, "{\"71304\":\"请讲话\",\"71305\":\"不知道你在说什么\",\"71308\":\"咱俩还是聊聊天吧\"}"); // 指定对话错误码的TTS播报。若未指定,则使用产品配置。
-
- //唤醒配置项
- // config.addConfig(DDSConfig.K_WAKEUP_ROUTER, "dialog"); //唤醒路由:partner(将唤醒结果传递给partner,不会主动进入对话)、dialog(将唤醒结果传递给dui,会主动进入对话)
- // config.addConfig(DDSConfig.K_WAKEUP_BIN, "/sdcard/wakeup.bin"); //商务定制版唤醒资源的路径。如果开发者对唤醒率有更高的要求,请联系商务申请定制唤醒资源。
- // config.addConfig(DDSConfig.K_ONESHOT_MIDTIME, "500");// OneShot配置:
- // config.addConfig(DDSConfig.K_ONESHOT_ENDTIME, "2000");// OneShot配置:
-
- //识别配置项
- // config.addConfig(DDSConfig.K_ASR_ENABLE_PUNCTUATION, "false"); //识别是否开启标点
- // config.addConfig(DDSConfig.K_ASR_ROUTER, "dialog"); //识别路由:partner(将识别结果传递给partner,不会主动进入语义)、dialog(将识别结果传递给dui,会主动进入语义)
- // config.addConfig(DDSConfig.K_VAD_TIMEOUT, 5000); // VAD静音检测超时时间,默认8000毫秒
- // config.addConfig(DDSConfig.K_ASR_ENABLE_TONE, "true"); // 识别结果的拼音是否带音调
- // config.addConfig(DDSConfig.K_ASR_TIPS, "true"); // 识别完成是否播报提示音
- // config.addConfig(DDSConfig.K_VAD_BIN, "/sdcard/vad.bin"); // 商务定制版VAD资源的路径。如果开发者对VAD有更高的要求,请联系商务申请定制VAD资源。
-
- // 麦克风阵列配置项
- // config.addConfig(DDSConfig.K_RECORDER_MODE, "internal"); //(适配了hal之后选内部,或者不写这一条,SDK默认是内部---录音机模式:external(使用外置录音机,需主动调用拾音接口)、internal(使用内置录音机,DDS自动录音)
- // config.addConfig(DDSConfig.K_MIC_TYPE, 2); // (根据麦克风实际类型进行配置)设置硬件采集模组的类型 0:无。默认值。 1:单麦回消 2:线性四麦 3:环形六麦 4:车载双麦 5:家具双麦 6: 环形四麦 7: 新车载双麦 8: 线性6麦
- //
- // config.addConfig(DDSConfig.K_USE_SSPE,"true");//如果资源是SSPE资源,则需要将此配置置为true
- // config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN,"sspe_aec_ula_wkp_35mm_ch6_mic4_ref2_v2.0.0.130.bin");//SSPE资源(放在test/src/main/assert文件夹下,或放到机器上指定绝对路径)(已包含aec算法)绝对路径,请务必保证绝对路径有可读写权限
- // //config.addConfig(DDSConfig.K_WAKEUP_BIN, "wakeup_s20_zhihuijingling_20230103.bin"); //商务定制版唤醒资源的路径。如果开发者对唤醒率有更高的要求,请联系商务申请定制唤醒资源。
- // config.addConfig(DDSConfig.K_AEC_MODE, "internal");//AEC模式,HAL层未集成AEC算法时,选择"internal"。HAL已经集成AEC算法时,选择"external"
-
- config.addConfig(DDSConfig.K_MIC_TYPE, 2);
- config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN, "sspe_aec_ula_wkp_35mm_ch6_mic4_ref2_v2.0.0.130.bin");
- // config.addConfig(DDSConfig.K_MIC_ARRAY_SSPE_BIN, "sspe_aec_ula_wkp_35mm_ch6_mic4_ref2_v2.0.0.130_post_20230530.bin");
- config.addConfig(DDSConfig.K_MIC_ECHO_CHANNEL_NUM, 2);
- config.addConfig(DDSConfig.K_AUDIO_SOURCE, 6);
- config.addConfig(DDSConfig.K_AUDIO_CHANNEL_COUNT, 6);
- config.addConfig(DDSConfig.K_AUDIO_CHANNEL_CONF, AudioFormat.CHANNEL_IN_MONO);
- config.addConfig(DDSConfig.K_AUDIO_SAMPLERATE, 32000);
-
- // config.addConfig(DDSConfig.K_VAD_BIN, "vad_modify.bin");
-
- // config.addConfig(DDSConfig.K_MIC_ARRAY_AEC_CFG, "/data/aec.bin"); // 麦克风阵列aec资源的磁盘绝对路径,需要开发者确保在这个路径下这个资源存在
- // config.addConfig(DDSConfig.K_MIC_ARRAY_BEAMFORMING_CFG, "/data/beamforming.bin"); // 麦克风阵列beamforming资源的磁盘绝对路径,需要开发者确保在这个路径下这个资源存在
-
- // 全双工/半双工配置项
- // config.addConfig(DDSConfig.K_DUPLEX_MODE, "HALF_DUPLEX");// 半双工模式
- // config.addConfig(DDSConfig.K_DUPLEX_MODE, "FULL_DUPLEX");// 全双工模式
-
- // 声纹配置项
- // config.addConfig(DDSConfig.K_VPRINT_ENABLE, "true");// 是否使用声纹
- // config.addConfig(DDSConfig.K_USE_VPRINT_IN_WAKEUP, "true");// 是否与唤醒结合使用声纹
- // config.addConfig(DDSConfig.K_VPRINT_BIN, "/sdcard/vprint.bin");// 声纹资源的绝对路径
-
- // asrpp配置荐
- // config.addConfig(DDSConfig.K_USE_GENDER, "true");// 使用性别识别
- // config.addConfig(DDSConfig.K_USE_AGE, "true");// 使用年龄识别
-
- Log.i(TAG, "config->" + config.toString());
- return config;
- }
-
- // 获取手机的唯一标识符: deviceId
- private String getDeviceId(Context context) {
- TelephonyManager telephonyMgr = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
- String imei = null;
- try {
- imei = telephonyMgr.getDeviceId();
- } catch (Exception e) {
- e.printStackTrace();
- }
- String serial = Build.SERIAL;
- String uuid;
- if (TextUtils.isEmpty(imei)) {
- imei = "unkown";
- } else if (TextUtils.isEmpty(serial)) {
- serial = "unkown";
- }
- uuid = UUID.nameUUIDFromBytes((imei + serial).getBytes()).toString();
- return uuid;
- }
-
- private long mTime = 0;
-
- public void startTtsListening() {
- try {
- DDS.getInstance().getAgent().getTTSEngine().setMode(DDSMode.TTS_SILENCE);
- DDS.getInstance().getAgent().getTTSEngine().setListener(new TTSEngine.Callback() {
- @Override
- public void beginning(String ttsId) {
- Log.d(TAG, "TTS开始播报 ttsId = " + ttsId);
- }
-
- @Override
- public void received(byte[] data) {
- Log.d(TAG, "收到音频,此方法会回调多次,直至data为0,音频结束 data = " + data.length);
- String pcmData = Base64.encodeToString(data, Base64.DEFAULT);
- JSONObject jo = new JSONObject();
- try {
- jo.put("type", "djTts");
- jo.put("data", pcmData);
- WebSocketManager.getInstance(MainActivity.instance).sendMsg(jo.toString());
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- // File file = createFile(mTime + ".pcm");
- // RandomAccessFile raf = null;
- // try {
- // raf = new RandomAccessFile(file, "rw");
- // raf.seek(file.length());
- // raf.write(data);
- // raf.close();
- // } catch (IOException e) {
- // throw new RuntimeException(e);
- // }
- }
-
- @Override
- public void end(String ttsId, int status) {
-
- }
-
- @Override
- public void error(String error) {
- Log.d(TAG, "出现错误," + error);
- }
-
- @Override
- public void phoneReturnReceived(String s) {
-
- }
- });
- } catch (DDSNotInitCompleteException e) {
- e.printStackTrace();
- }
-
- }
-
- public File createFile(String name) {
- String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath()
- +"/Android/data/com.aispeech.nativedemo/cache/asrCache/";
- File file = new File(dirPath);
- if(!file.exists()) {
- file.mkdirs();
- }
- String filePath = dirPath +name;
- File objFile = new File(filePath);
- if (!objFile.exists()) {
- try {
- objFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return objFile;
- }
- return objFile;
- }
-
- }
|