From c29a3f665a0661b1ef13370a848bd6e84cd806e7 Mon Sep 17 00:00:00 2001 From: "guangfei.zhao" Date: Tue, 30 Sep 2025 11:43:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dasr=20=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=B0=B1=E5=88=9D=E5=A7=8B=E5=8C=96=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit asrInstance.initialize 这个方法的作用是初始化阿里云 NUI SDK 的 ASR 实例。根据阿里云 SDK 的设计,这个初始化过程不仅仅是加载配置,它还会立即建立与云端的长连接(WebSocket),并进入一个“待命”状态。SDK 会请求打开音频设备。 延迟初始化,只在第一次需要时才进行初始化 --- .../AiAssistantPlugin.java | 48 +- .../ai_assistant_plugin/AsrCallBack.java | 4 +- .../reports/problems/problems-report.html | 663 ++++++++++++++++++ example/lib/main.dart | 2 +- lib/services/message_service.dart | 36 +- 5 files changed, 727 insertions(+), 26 deletions(-) create mode 100644 example/android/build/reports/problems/problems-report.html diff --git a/android/src/main/java/com/example/ai_assistant_plugin/AiAssistantPlugin.java b/android/src/main/java/com/example/ai_assistant_plugin/AiAssistantPlugin.java index 7651f3d..e5487ff 100644 --- a/android/src/main/java/com/example/ai_assistant_plugin/AiAssistantPlugin.java +++ b/android/src/main/java/com/example/ai_assistant_plugin/AiAssistantPlugin.java @@ -35,13 +35,14 @@ public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler { private static final String chineseVoice = "zhitian_emo"; private static final String englishVoice = "abby"; private final NativeNui streamInputTtsInstance = new NativeNui(Constants.ModeType.MODE_STREAM_INPUT_TTS); - private final NativeNui asrInstance = new NativeNui(); - /// The MethodChannel that will the communication between Flutter and native Android - /// - /// This local reference serves to register the plugin with the Flutter Engine and unregister it - /// when the Flutter Engine is detached from the Activity + // asr 是否初始化 + private boolean isAsrInitialized = false; + + // asr property private MethodChannel channel; + // asr instance + private final NativeNui asrInstance = new NativeNui(); private Handler asrHandler; private AsrCallBack asrCallBack; private Handler handler = new Handler(Looper.getMainLooper()); @@ -62,6 +63,21 @@ public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler { } }); + void initAsrInstance() { + if (!isAsrInitialized) { + Log.i(TAG, "Initializing ASR for the first time..."); + asrCallBack = new AsrCallBack(channel); + int initResult = asrInstance.initialize(asrCallBack, genAsrInitParams(), + Constants.LogLevel.LOG_LEVEL_NONE, false); + Log.i(TAG, "ASR initialization result: " + initResult); + if (initResult != Constants.NuiResultCode.SUCCESS) { + Log.i(TAG, "ASR initialization failed with error code: " + initResult); + return; + } + isAsrInitialized = true; + } + } + @Override public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) { channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), CHANNEL); @@ -69,9 +85,10 @@ public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler { HandlerThread asrHandlerThread = new HandlerThread("process_thread"); asrHandlerThread.start(); asrHandler = new Handler(asrHandlerThread.getLooper()); - asrCallBack = new AsrCallBack(channel); - asrInstance.initialize(asrCallBack, genAsrInitParams(), - Constants.LogLevel.LOG_LEVEL_NONE, false); + // 不能在这里初始化 asr, 初始化之后会占用麦克风 +// asrCallBack = new AsrCallBack(channel); +// asrInstance.initialize(asrCallBack, genAsrInitParams(), +// Constants.LogLevel.LOG_LEVEL_NONE, false); } @Override @@ -81,6 +98,16 @@ public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler { ttsAudioTrack.releaseAudioTrack(); streamInputTtsInstance.stopStreamInputTts(); streamInputTtsInstance.release(); + + if (isAsrInitialized) { + asrInstance.release(); + if (asrCallBack != null) { + asrCallBack.release(); + asrCallBack = null; + } + isAsrInitialized = false; + } + // asrInstance.release(); // if (asrCallBack != null) { // asrCallBack.release(); @@ -93,6 +120,7 @@ public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler { Map args = call.arguments(); switch (call.method) { case "startTts": + assert args != null; Object isChinese = args.get("isChinese"); if (isChinese == null || isChinese.toString().isBlank()) { return; @@ -101,6 +129,7 @@ public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler { result.success(isSuccess); break; case "sendTts": + assert args != null; Object textArg = args.get("text"); if (textArg == null || textArg.toString().isBlank()) { return; @@ -140,6 +169,9 @@ public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler { private void startAsr() { asrHandler.post(() -> { + // 初始化 + initAsrInstance(); + // 启动 String setParamsString = genAsrParams(); Log.i(TAG, "nui set params " + setParamsString); asrInstance.setParams(setParamsString); diff --git a/android/src/main/java/com/example/ai_assistant_plugin/AsrCallBack.java b/android/src/main/java/com/example/ai_assistant_plugin/AsrCallBack.java index 1d129ff..935e26f 100644 --- a/android/src/main/java/com/example/ai_assistant_plugin/AsrCallBack.java +++ b/android/src/main/java/com/example/ai_assistant_plugin/AsrCallBack.java @@ -18,7 +18,7 @@ import io.flutter.plugin.common.MethodChannel; public class AsrCallBack implements INativeNuiCallback { - private static final String TAG = "AliAsr"; + private static final String TAG = "AliAsr-Callbask"; private final static int ASR_SAMPLE_RATE = 16000; private final static int ASR_WAVE_FRAM_SIZE = 20 * 2 * 1 * ASR_SAMPLE_RATE / 1000; //20ms audio for 16k/16bit/mono private AudioRecord asrAudioRecorder = null; @@ -38,7 +38,7 @@ public class AsrCallBack implements INativeNuiCallback { if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_STARTED) { asrText = ""; } else if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_COMPLETE) { - + // complete } else if (event == Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT) { JSONObject jsonObject = JSON.parseObject(asrResult.allResponse); JSONObject payload = jsonObject.getJSONObject("payload"); diff --git a/example/android/build/reports/problems/problems-report.html b/example/android/build/reports/problems/problems-report.html new file mode 100644 index 0000000..8d63a46 --- /dev/null +++ b/example/android/build/reports/problems/problems-report.html @@ -0,0 +1,663 @@ + + + + + + + + + + + + + Gradle Configuration Cache + + + +
+ +
+ Loading... +
+ + + + + + diff --git a/example/lib/main.dart b/example/lib/main.dart index cede8b0..e0f59c2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -67,7 +67,7 @@ void main() async { runApp(const MyApp()); // AIChatAssistantManager.instance.setWakeWordDetection(true); - AIChatAssistantManager.instance.startVoskWakeword(); + // AIChatAssistantManager.instance.startVoskWakeword(); } diff --git a/lib/services/message_service.dart b/lib/services/message_service.dart index d7de224..fccd0d6 100644 --- a/lib/services/message_service.dart +++ b/lib/services/message_service.dart @@ -60,23 +60,29 @@ class MessageService extends ChangeNotifier { Future _handleMethodCall(MethodCall call) async { switch (call.method) { case "onAsrResult": - replaceMessage( - id: _latestUserMessageId!, text: call.arguments, status: MessageStatus.normal); - break; + { + debugPrint("ASR 结果: ${call.arguments}"); + replaceMessage( + id: _latestUserMessageId!, text: call.arguments, status: MessageStatus.normal); + break; + } case "onAsrStop": - int index = findMessageIndexById(_latestUserMessageId!); - if (index == -1) { - return; + { + debugPrint("ASR 停止: ${call.arguments}"); + int index = findMessageIndexById(_latestUserMessageId!); + if (index == -1) { + return; + } + final message = _messages[index]; + if (message.text.isEmpty) { + removeMessageById(_latestUserMessageId!); + return; + } + if (_asrCompleter != null && !_asrCompleter!.isCompleted) { + _asrCompleter!.complete(messages.last.text); + } + break; } - final message = _messages[index]; - if (message.text.isEmpty) { - removeMessageById(_latestUserMessageId!); - return; - } - if (_asrCompleter != null && !_asrCompleter!.isCompleted) { - _asrCompleter!.complete(messages.last.text); - } - break; } }