From 0a31525e306f08566a51156023185c339bdcc1ec Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Tue, 9 Sep 2025 11:25:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=89=E5=8D=93=E9=80=9A?= =?UTF-8?q?=E8=AF=9D=E7=BF=BB=E8=AF=91=E9=A2=91=E7=B9=81=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E5=A5=94=E6=BA=83=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../azure_speech/AzureAsrToAsr.kt | 130 +++++++++++------- 1 file changed, 80 insertions(+), 50 deletions(-) diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt index 8aebb37a8..bc154fe05 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt @@ -475,26 +475,57 @@ class IntegratedSpeechTranslationService( } /** - * 停止连续语音翻译 + * 停止连续语音翻译(非阻塞) + * 在 IO 线程内顺序停止识别器、录音线程与文件,并对翻译/合成收尾增加统一超时保护,避免阻塞主线程与潜在 ANR。 */ fun stopContinuousTranslation() { try { - recognizer?.stopContinuousRecognitionAsync() - audioProcessor?.stopRecording() - recordfile1!!.closeFile(true) + Log.d(TAG, "停止连续语音翻译-开始") + // 先标记识别关闭,避免后续流程继续入队处理 serviceState.isRecognizing.set(false) - // 等待当前处理完成 - while (serviceState.isTranslating.get() || serviceState.isSynthesizing.get()) { - Thread.sleep(100) - } - Log.d(TAG, "停止连续语音翻译") + // 在 IO 线程中做真实的停止动作,避免阻塞主线程 + launch(Dispatchers.IO) { + // 1) 停止识别器:等待短超时,避免卡住 + try { + recognizer?.stopContinuousRecognitionAsync() + ?.get(1500, java.util.concurrent.TimeUnit.MILLISECONDS) + } catch (t: Throwable) { + Log.w(TAG, "停止识别器超时或失败", t) + } + + // 2) 停止录音线程(打断并短等待退出) + runCatching { audioProcessor?.stopRecording() } + .onFailure { Log.w(TAG, "停止录音失败", it) } + + // 3) 关闭录音文件(若开启过录音) + runCatching { recordfile1?.closeFile(true) } + .onFailure { Log.w(TAG, "关闭录音文件失败", it) } + + // 4) 等待翻译/合成收尾,整体不超过 2s + val start = System.currentTimeMillis() + while ((serviceState.isTranslating.get() || serviceState.isSynthesizing.get()) + && System.currentTimeMillis() - start < 2000 + ) { + delay(100) + } + if (serviceState.isTranslating.get() || serviceState.isSynthesizing.get()) { + Log.w(TAG, "等待翻译/合成完成超时,强制标记结束") + } + + // 5) 统一落幕:确保状态关闭 + serviceState.isTranslating.set(false) + serviceState.isSynthesizing.set(false) + + Log.d(TAG, "停止连续语音翻译-完成") + } } catch (e: Exception) { Log.e(TAG, "停止翻译失败", e) eventCallback?.onError("Service", "停止失败: ${e.message}") } } + /** * 处理翻译和合成流程 */ @@ -1184,58 +1215,57 @@ fun getSupportedLanguages(): List { } /** - * 改进的资源释放方法 + * 安全释放音频处理器资源 + * 添加更强的异常处理和超时保护 */ fun dispose() { try { Log.d(TAG, "开始释放音频处理器资源...") - // 1. 停止运行标志 - isRunning.set(false) + // 1. 设置停止标志 + if (!isRunning.compareAndSet(true, false)) { + Log.d(TAG, "音频处理器已停止,跳过释放") + return + } - // 2. 中断处理线程 - processingThread?.let { thread -> - if (thread.isAlive) { + // 1) 安全停止处理线程 + processingThread?.let { thread -> + if (thread.isAlive) { + try { thread.interrupt() - try { - // 等待线程结束,最多等待2秒 - thread.join(2000) - if (thread.isAlive) { - Log.w(TAG, "音频处理线程未能正常结束") - } else { - Log.d(TAG, "音频处理线程已结束") - } - } catch (e: InterruptedException) { - Log.w(TAG, "等待音频处理线程结束时被中断") - Thread.currentThread().interrupt() + thread.join(500) + if (thread.isAlive) { + Log.w(TAG, "音频处理线程未在500ms内结束") + // 不强制杀死,交由系统回收,但继续清理资源 + } else { + Log.d(TAG, "音频处理线程已正常结束") } + } catch (e: InterruptedException) { + Log.w(TAG, "等待线程结束时被中断", e) + Thread.currentThread().interrupt() + } catch (e: Exception) { + Log.e(TAG, "停止处理线程时发生异常", e) } } - processingThread = null - - // 3. 关闭音频流 - try { - pushAudioStream?.close() - pushAudioStream = null - Log.d(TAG, "音频流已关闭") - } catch (e: Exception) { - Log.e(TAG, "关闭音频流失败", e) - } - - // 4. 清理音频队列 - try { - val remainingData = audioQueue.size - audioQueue.clear() - Log.d(TAG, "音频队列已清理,丢弃 $remainingData 个数据包") - } catch (e: Exception) { - Log.e(TAG, "清理音频队列失败", e) - } - - Log.d(TAG, "音频处理器资源释放完成") - - } catch (e: Exception) { - Log.e(TAG, "释放音频处理器资源时发生异常", e) } + processingThread = null + + // 2) 关闭输入流 + try { + pushAudioStream?.close() + } catch (t: Throwable) { + Log.w(TAG, "关闭 PushAudioInputStream 时异常", t) + } finally { + pushAudioStream = null + } + + // 3) 清空队列 + audioQueue.clear() + + Log.d(TAG, "音频处理器资源释放完成") + } catch (e: Exception) { + Log.e(TAG, "释放音频处理器资源失败", e) + } } } }