Browse Source

fix(azure_speech): 改进音频捕获线程的异常处理和资源释放

添加线程优先级设置和更完善的异常处理逻辑
确保线程安全停止并释放资源
优化暂停状态下的CPU使用率
weicu
lxm 1 year ago
parent
commit
6f30df7cb0
  1. 98
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt

98
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrHelper.kt

@ -822,39 +822,77 @@ class AzureAsrHelper(private val context: Context) {
// 3. 单独封装线程启动逻辑
fun startCaptureThread() {
// 开始录音
audioRecord?.startRecording()
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 // 默认回退值
val buffer = ByteArray(bufferSize)
while (!Thread.interrupted() && audioRecord?.recordingState == AudioRecord.RECORDSTATE_RECORDING) {
if (!isPaused) {
// 读取音频
val bytesRead = audioRecord?.read(buffer, 0, buffer.size) ?: 0
if (bytesRead > 0) {
try {
// 确保之前的线程已停止
stopCaptureThread()
// 开始录音
audioRecord?.startRecording()
captureThread = Thread({
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO)
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
val buffer = ByteArray(bufferSize)
try {
while (!Thread.currentThread().isInterrupted &&
audioRecord?.recordingState == AudioRecord.RECORDSTATE_RECORDING) {
// 写入Azure流
pushAudioStream?.write(buffer)
// 保存录音
recordfile?.saveAudioDataToWav(buffer)
if (!isPaused) {
val bytesRead = audioRecord?.read(buffer, 0, buffer.size) ?: 0
if (bytesRead > 0) {
// 安全地写入Azure流
try {
pushAudioStream?.write(buffer)
recordfile?.saveAudioDataToWav(buffer)
} catch (e: Exception) {
Log.w(tag, "写入音频流失败: ${e.message}")
}
} else if (bytesRead < 0) {
Log.w(tag, "AudioRecord读取错误: $bytesRead")
break
}
} else {
Thread.sleep(10) // 暂停时短暂休眠
}
}
} catch (e: InterruptedException) {
Log.d(tag, "音频捕获线程被中断")
} catch (e: Exception) {
Log.e(tag, "音频捕获异常: ${e.message}", e)
}
}, "AudioCaptureThread")
captureThread?.start()
} catch (e: Exception) {
Log.e(tag, "启动音频捕获线程失败: ${e.message}", e)
throw e
}
}
private fun stopCaptureThread() {
captureThread?.let { thread ->
if (thread.isAlive) {
thread.interrupt()
try {
thread.join(500) // 等待最多500ms
} catch (e: InterruptedException) {
Log.w(tag, "等待音频线程结束被中断")
}
}
}.apply { start() }
}
captureThread = null
}
/**
@ -1050,4 +1088,4 @@ class AzureAsrHelper(private val context: Context) {
}
}
}
Loading…
Cancel
Save