|
|
|
@ -41,6 +41,11 @@ public class AzureAsrHelper: NSObject { |
|
|
|
private var lastAudioStartTime: Int64 = 0 |
|
|
|
private let audioOperationDebounceInterval: Int64 = 500 // 500毫秒防抖间隔 |
|
|
|
private var audioStartWorkItem: DispatchWorkItem? |
|
|
|
// 串行队列和状态标记,用于顺序控制音频启动/停止,避免竞态 |
|
|
|
private let audioOpQueue = DispatchQueue(label: "com.azure.speech.audio.operations") |
|
|
|
private var isAudioStarting = false |
|
|
|
private var isAudioStarted = false |
|
|
|
private var pendingStopRequest = false |
|
|
|
|
|
|
|
// 状态管理 |
|
|
|
private var _isContinuousRecognitionActive = false |
|
|
|
@ -269,9 +274,27 @@ public class AzureAsrHelper: NSObject { |
|
|
|
|
|
|
|
os_log("开始异步启动音频录制", log: self.log, type: .info) |
|
|
|
|
|
|
|
// 在后台队列执行耗时的音频启动操作 |
|
|
|
DispatchQueue.global(qos: .userInitiated).async { |
|
|
|
// 使用串行队列,保证与 stop 顺序执行,避免竞态 |
|
|
|
self.audioOpQueue.async { [weak self] in |
|
|
|
guard let self = self else { |
|
|
|
DispatchQueue.main.async { completion(false) } |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 准备启动 |
|
|
|
self.isAudioStarting = true |
|
|
|
self.pendingStopRequest = false // 启动前清空旧的停止请求 |
|
|
|
let success = self.performAudioStart(audioSourceType: audioSourceType, audioDataCallback: audioDataCallback) |
|
|
|
self.isAudioStarting = false |
|
|
|
self.isAudioStarted = success |
|
|
|
|
|
|
|
// 如果启动过程中有 stop 请求,立即顺序停止,确保麦克风不会被重新“开启” |
|
|
|
if self.pendingStopRequest { |
|
|
|
self.pendingStopRequest = false |
|
|
|
_ = self.performAudioStop() |
|
|
|
self.isAudioStarted = false |
|
|
|
os_log("启动完成后检测到待停止请求,已立即停止音频", log: self.log, type: .info) |
|
|
|
} |
|
|
|
|
|
|
|
// 回到主队列执行完成回调 |
|
|
|
DispatchQueue.main.async { |
|
|
|
@ -318,9 +341,18 @@ public class AzureAsrHelper: NSObject { |
|
|
|
private func stopAudioRecordAsync(completion: @escaping (Bool) -> Void) { |
|
|
|
os_log("开始立即停止音频录制", log: log, type: .info) |
|
|
|
|
|
|
|
// 在后台队列执行耗时的音频停止操作 |
|
|
|
DispatchQueue.global(qos: .userInitiated).async { |
|
|
|
// 在串行队列顺序执行停止,避免与启动并发导致的竞态 |
|
|
|
audioOpQueue.async { [weak self] in |
|
|
|
guard let self = self else { |
|
|
|
DispatchQueue.main.async { completion(false) } |
|
|
|
return |
|
|
|
} |
|
|
|
// 若启动过程中收到停止请求,记录标记,启动完成后会立即停止 |
|
|
|
if self.isAudioStarting { |
|
|
|
self.pendingStopRequest = true |
|
|
|
} |
|
|
|
let success = self.performAudioStop() |
|
|
|
self.isAudioStarted = false |
|
|
|
|
|
|
|
// 回到主队列执行完成回调 |
|
|
|
DispatchQueue.main.async { |
|
|
|
@ -333,7 +365,7 @@ public class AzureAsrHelper: NSObject { |
|
|
|
* 执行音频停止操作 |
|
|
|
*/ |
|
|
|
private func performAudioStop() -> Bool { |
|
|
|
do { |
|
|
|
do { |
|
|
|
audioStream?.stopMicrophoneCapture() |
|
|
|
os_log("音频录制停止成功", log: log, type: .info) |
|
|
|
return true |
|
|
|
|