diff --git a/lib/modules/translation/controllers/translation_controller.dart b/lib/modules/translation/controllers/translation_controller.dart index 0ebed9187..877ddad5b 100644 --- a/lib/modules/translation/controllers/translation_controller.dart +++ b/lib/modules/translation/controllers/translation_controller.dart @@ -161,7 +161,7 @@ class TranslationController extends GetxController { } // 加载历史记录 - loadTranslationHistory(); + //loadTranslationHistory(); // 初始化服务 _initServices(); @@ -469,6 +469,7 @@ class TranslationController extends GetxController { isIntermediate: true, ); // 添加新项后滚动到底部 + translationHistory.add(newItem); _scrollToBottom(); } else { // 更新当前项 diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt index 919247837..a450c0d8a 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt @@ -80,7 +80,29 @@ class AzureAsrHelper(private val context: Context) { /** 使用外部提供的音频数据 */ EXTERNAL } - + /** + * 获取设备支持的最佳音频格式 + * 优先选择16000Hz,若不支持则降级到8000Hz + */ + private fun getOptimalAudioFormat(): AudioStreamFormat { + // 支持的采样率列表(按优先级排序) + val supportedSampleRates = intArrayOf(16000, 8000, 11025, 22050, 44100) + + // 查找设备支持的最佳采样率 + val sampleRate = supportedSampleRates.firstOrNull { rate -> + val bufferSize = AudioRecord.getMinBufferSize( + rate, + AudioFormat.CHANNEL_IN_MONO, + AudioFormat.ENCODING_PCM_16BIT + ) + bufferSize > 0 // 返回正值表示支持 + } ?: 16000 // 默认回退值 + + Log.i(tag, "使用采样率: ${sampleRate}Hz") + + // 创建对应的音频格式 + return AudioStreamFormat.getWaveFormatPCM(sampleRate.toLong(), 16, 1) + } /** * 初始化Azure语音服务 * @@ -106,7 +128,7 @@ class AzureAsrHelper(private val context: Context) { // 释放之前的资源 dispose() // 1. 创建可控制的音频流 - val format = AudioStreamFormat.getWaveFormatPCM(16000, 16, 1) + val format = getOptimalAudioFormat() audioStream = AudioInputStream.createPushStream(format) // 初始化音频管理器 audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager @@ -157,7 +179,7 @@ class AzureAsrHelper(private val context: Context) { // 录音文件类 recordfile = RecordFile; //进入界面手机麦克风就被占用,导致其他app无法使用麦克风,在开始录音再去申请 - // 创建识别器 + // // 创建识别器 // val setupSuccess = setupRecognizer() // if (setupSuccess) { // // 优化:初始化完成后进行预热 @@ -369,6 +391,8 @@ class AzureAsrHelper(private val context: Context) { audioRecord?.startRecording() startCaptureThread() // 再启动数据读取线程 isContinuousRecognitionActive = true +Log.d(tag, "识别器创建成功: ${recognizer != null}") +Log.d(tag, "开始识别任务: recognizeOnce 或 startContinuousRecognition 被调用") return true } catch (e: Exception) { @@ -705,8 +729,19 @@ class AzureAsrHelper(private val context: Context) { * 开始麦克风捕获 */ private fun initAudioRecord() { - // 设置音频参数 - val sampleRate = 16000 // 16kHz采样率(语音识别常用) + // 获取已确定的采样率 + val format = getOptimalAudioFormat() + val supportedSampleRates = intArrayOf(16000, 8000, 11025, 22050, 44100) + + // 查找设备支持的最佳采样率 + val sampleRate = supportedSampleRates.firstOrNull { rate -> + val bufferSize = AudioRecord.getMinBufferSize( + rate, + AudioFormat.CHANNEL_IN_MONO, + AudioFormat.ENCODING_PCM_16BIT + ) + bufferSize > 0 // 返回正值表示支持 + } ?: 16000 // 默认回退值 val channelConfig = AudioFormat.CHANNEL_IN_MONO // 单声道输入 val audioFormat = AudioFormat.ENCODING_PCM_16BIT // 16位PCM格式 @@ -732,35 +767,42 @@ class AzureAsrHelper(private val context: Context) { } // 3. 单独封装线程启动逻辑 - private fun startCaptureThread() { - captureThread = Thread { - // 循环条件确保录音已开始 - - val buffer = ByteArray(1024) // 4KB数据缓冲区 - while (!Thread.interrupted() && audioRecord?.recordingState == AudioRecord.RECORDSTATE_RECORDING) { - // 从麦克风读取数据 - val bytesRead = audioRecord?.read(buffer, 0, buffer.size) ?: 0 - - // 仅在未暂停时处理数据 - if (!isPaused && bytesRead > 0) { - // 写入音频流(可能是网络传输或本地处理) - audioStream?.write(buffer) - // 保存到WAV文件(如果启用了录制功能) - recordfile?.saveAudioDataToWav(buffer) - } - - // 暂停时短暂休眠以减少CPU占用 - if (isPaused) { - try { - Thread.sleep(50) - } catch (e: InterruptedException) { - break // 线程被中断时退出循环 - } - } + private fun startCaptureThread() { + captureThread = Thread { + // 根据实际采样率计算缓冲区大小 + val supportedSampleRates = intArrayOf(16000, 8000, 11025, 22050, 44100) + var bufferSize = 0 + // 查找设备支持的最佳采样率 + val sampleRate = supportedSampleRates.firstOrNull { rate -> + bufferSize = AudioRecord.getMinBufferSize( + rate, + AudioFormat.CHANNEL_IN_MONO, + AudioFormat.ENCODING_PCM_16BIT + ) + bufferSize > 0 // 返回正值表示支持 + } ?: 16000 // 默认回退值 + // (sampleRate * 0.032).toInt() * 2 // 32ms数据量 + + val buffer = ByteArray(bufferSize) + + while (!Thread.interrupted() && audioRecord?.recordingState == AudioRecord.RECORDSTATE_RECORDING) { + + // 读取音频 + val bytesRead = audioRecord?.read(buffer, 0, buffer.size) ?: 0 +Log.i("AzureASR", "AudioRecord state: ${audioRecord?.state}, recordingState: ${audioRecord?.recordingState}") +Log.i("AzureASR", "BytesRead = $bytesRead, buffer.isSilent = ${buffer.all { it == 0.toByte() }}") + + if (!isPaused && bytesRead > 0) { + + // 写入Azure流 + audioStream?.write(buffer) + + // 保存录音 + recordfile?.saveAudioDataToWav(buffer) } - - }.apply { start() } - } + } + }.apply { start() } +} /** * 停止麦克风捕获并释放所有相关资源