|
|
|
@ -69,7 +69,9 @@ class AgentServiceImpl: NSObject { |
|
|
|
// 用途:解决 start 异步、stop 先于 onSessionStarted 到来时被忽略的问题 |
|
|
|
private var isStartingRecognition: Bool = false |
|
|
|
private var stopRequestedDuringStart: Bool = false |
|
|
|
|
|
|
|
//是否保留最终结果 |
|
|
|
private var isKeepResult = true; |
|
|
|
|
|
|
|
var currsessionId: String = "" |
|
|
|
var language: String = "" |
|
|
|
private var serverurl = "" |
|
|
|
@ -354,6 +356,8 @@ class AgentServiceImpl: NSObject { |
|
|
|
|
|
|
|
if self.isRecognizing && !self.isSpeaking && !self.isAiStreaming { |
|
|
|
os_log("空闲检测触发自动停止,模式: %{public}@", log: self.logger, type: .info, self.currentRecognitionMode) |
|
|
|
// 关闭编码器 (设备侧) |
|
|
|
BleService.shared.closeCodec() |
|
|
|
self.stopRecognition() |
|
|
|
self.sendEvent(name: "auto_stop", data: [ |
|
|
|
"reason": "idle_timeout", |
|
|
|
@ -377,6 +381,14 @@ class AgentServiceImpl: NSObject { |
|
|
|
} |
|
|
|
} |
|
|
|
func startRecognition(useBle: Bool = false, mode: String = "normal") -> Bool { |
|
|
|
// 接收到唤醒信号,打开编码器 (设备侧) |
|
|
|
print("ai启动语音\(useBle))") |
|
|
|
var openResult = false // 添加openResult变量定义 |
|
|
|
if useBle{ |
|
|
|
isKeepResult = false |
|
|
|
// 捕获openEncoder的返回值 |
|
|
|
openResult = BleService.shared.openEncoder() // 正确捕获返回值 |
|
|
|
} |
|
|
|
if !isInitialized { |
|
|
|
sendError("服务未初始化", code: "NOT_INITIALIZED") |
|
|
|
return false |
|
|
|
@ -387,14 +399,11 @@ class AgentServiceImpl: NSObject { |
|
|
|
sendError("无麦克风权限", code: "PERMISSION_DENIED") |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
stopTts(); |
|
|
|
if isRecognizing { |
|
|
|
stopRecognition() |
|
|
|
} |
|
|
|
|
|
|
|
// 接收到唤醒信号,打开编码器 (设备侧) |
|
|
|
let openResult = BleService.shared.openEncoder() |
|
|
|
} |
|
|
|
stopRecognition() |
|
|
|
stopTts() |
|
|
|
|
|
|
|
|
|
|
|
os_log("🎙️ 尝试打开编码器结果: %@", log: logger, type: .info, openResult ? "成功" : "失败") |
|
|
|
wasMusicPlayingBeforeRecognition = MusicService.shared.isPlaying |
|
|
|
|
|
|
|
@ -417,7 +426,7 @@ class AgentServiceImpl: NSObject { |
|
|
|
|
|
|
|
// 新增:标记为"启动中",用于允许 stop 在启动未完成时也能生效 |
|
|
|
isStartingRecognition = true |
|
|
|
|
|
|
|
|
|
|
|
print("ai启动语音=\(audioSourceType)=\(useBle)") |
|
|
|
guard let success = azureAsrHelper?.startContinuousRecognition( |
|
|
|
// callback: self, |
|
|
|
@ -428,7 +437,9 @@ class AgentServiceImpl: NSObject { |
|
|
|
sendError("启动语音识别失败", code: "RECOGNITION_START_ERROR") |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
if(useBle){ |
|
|
|
isKeepResult = true |
|
|
|
} |
|
|
|
// 根据模式启动相应的空闲检测(此处 guard isRecognizing,会在 onSessionStarted 中再次启动) |
|
|
|
startIdleCheckForMode(mode: mode) |
|
|
|
|
|
|
|
@ -450,6 +461,7 @@ class AgentServiceImpl: NSObject { |
|
|
|
/// 特性: |
|
|
|
/// 1) 即便处于"启动中"(isStartingRecognition)也会打印日志并尝试停止 |
|
|
|
/// 2) 如果底层尚未完全进入可停止状态,记录一次待停止请求,待会话启动后立即停止 |
|
|
|
print("停止识别语音,isRecognizing=\(isRecognizing),isStartingRecognition=\(isStartingRecognition)") |
|
|
|
if !(isRecognizing || isStartingRecognition) { |
|
|
|
// 既不在识别中,也不在启动中,视为幂等处理 |
|
|
|
return true |
|
|
|
@ -473,8 +485,6 @@ class AgentServiceImpl: NSObject { |
|
|
|
MusicService.shared.resume() |
|
|
|
} |
|
|
|
|
|
|
|
// 关闭编码器 (设备侧) |
|
|
|
BleService.shared.closeCodec() |
|
|
|
// 重置识别模式 |
|
|
|
currentRecognitionMode = "normal" |
|
|
|
|
|
|
|
@ -492,7 +502,7 @@ class AgentServiceImpl: NSObject { |
|
|
|
return false |
|
|
|
} |
|
|
|
guard let audioStream = azureAsrHelper?.audioStream else { |
|
|
|
os_log("音频流未初始化", log: logger,type: .error) |
|
|
|
os_log("AI音频流未初始化", log: logger,type: .error) |
|
|
|
return false |
|
|
|
} |
|
|
|
audioStream.saveAudioDataTo(data: audioData) |
|
|
|
@ -1055,6 +1065,8 @@ private func jsonToString(_ json: [String: Any]) -> String? { |
|
|
|
// 如果正在识别,需要先停止 |
|
|
|
let wasRecognizing = isRecognizing |
|
|
|
if wasRecognizing { |
|
|
|
// 关闭编码器 (设备侧) |
|
|
|
BleService.shared.closeCodec() |
|
|
|
_ = stopRecognition() |
|
|
|
} |
|
|
|
|
|
|
|
@ -1229,6 +1241,8 @@ private func jsonToString(_ json: [String: Any]) -> String? { |
|
|
|
func dispose() -> Bool { |
|
|
|
print("ai释放资源") |
|
|
|
if isRecognizing { |
|
|
|
// 关闭编码器 (设备侧) |
|
|
|
BleService.shared.closeCodec() |
|
|
|
stopRecognition() |
|
|
|
} |
|
|
|
|
|
|
|
@ -1390,6 +1404,8 @@ class ChatApiStreamCallback: StreamCallback { |
|
|
|
print("onFunctionCall=functionCall\(functionCall)") |
|
|
|
|
|
|
|
if (name == "exit_interaction") { |
|
|
|
// 关闭编码器 (设备侧) |
|
|
|
BleService.shared.closeCodec() |
|
|
|
agentService.stopRecognition() |
|
|
|
} |
|
|
|
|
|
|
|
@ -1515,9 +1531,6 @@ extension AgentServiceImpl: BleService.Callback { |
|
|
|
|
|
|
|
|
|
|
|
func onWakeupSignalReceived() { |
|
|
|
stopTts() |
|
|
|
|
|
|
|
stopRecognition() |
|
|
|
|
|
|
|
startRecognition(useBle: true, mode: "ble_wakeup") |
|
|
|
} |
|
|
|
@ -1717,7 +1730,7 @@ class AudioPlayer { |
|
|
|
|
|
|
|
extension AgentServiceImpl: AzureAsrHelper.ContinuousRecognizeCallback { |
|
|
|
func onResult(_ text: String, _ detectedLanguage: String) { |
|
|
|
if !text.isEmpty { |
|
|
|
if !text.isEmpty && isKeepResult { |
|
|
|
var data: [String: Any] = ["text": text] |
|
|
|
if !detectedLanguage.isEmpty { |
|
|
|
data["language"] = detectedLanguage |
|
|
|
@ -1736,7 +1749,7 @@ extension AgentServiceImpl: AzureAsrHelper.ContinuousRecognizeCallback { |
|
|
|
} |
|
|
|
|
|
|
|
func onRecognizing(_ recognizing: String, _ detectedLanguage: String) { |
|
|
|
if !recognizing.isEmpty { |
|
|
|
if !recognizing.isEmpty && isKeepResult { |
|
|
|
let previousHasSpeech = hasSpeechDetected |
|
|
|
hasSpeechDetected = true |
|
|
|
|
|
|
|
@ -1772,6 +1785,8 @@ extension AgentServiceImpl: AzureAsrHelper.ContinuousRecognizeCallback { |
|
|
|
// 新增:若在启动期间已经收到停止请求,则立即执行停止 |
|
|
|
if stopRequestedDuringStart { |
|
|
|
stopRequestedDuringStart = false |
|
|
|
// 关闭编码器 (设备侧) |
|
|
|
BleService.shared.closeCodec() |
|
|
|
_ = stopRecognition() |
|
|
|
} |
|
|
|
} |
|
|
|
|