|
|
|
@ -879,53 +879,194 @@ private func jsonToString(_ json: [String: Any]) -> String? { |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 设置支持的语音识别语言 |
|
|
|
* |
|
|
|
* 设置支持的语音识别语言,同时更新TTS语言设置 |
|
|
|
* |
|
|
|
* @param languages 支持的语言列表,如 ["zh-CN", "en-US"] |
|
|
|
* @return 是否设置成功 |
|
|
|
*/ |
|
|
|
func setSupportedLanguages(_ languages: [String]) -> Bool { |
|
|
|
os_log("设置支持的语言: %{public}@", log: logger, type: .info, languages.joined(separator: ", ")) |
|
|
|
|
|
|
|
|
|
|
|
if !isInitialized { |
|
|
|
os_log("服务未初始化,无法设置语言", log: logger, type: .error) |
|
|
|
sendError("服务未初始化", code: "NOT_INITIALIZED") |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if languages.isEmpty { |
|
|
|
os_log("语言列表为空,使用默认语言", log: logger, type: .info) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 如果正在识别,需要先停止 |
|
|
|
let wasRecognizing = isRecognizing |
|
|
|
if wasRecognizing { |
|
|
|
_ = stopRecognition() |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 重新初始化ASR引擎,使用新的语言设置 |
|
|
|
guard let success = azureAsrHelper?.initialize( |
|
|
|
guard let asrSuccess = azureAsrHelper?.initialize( |
|
|
|
subscriptionKey: azureSpeechKey, |
|
|
|
region: azureSpeechRegion, |
|
|
|
supportedLanguages: languages, |
|
|
|
audioSourceType: .microphone |
|
|
|
), success else { |
|
|
|
), asrSuccess else { |
|
|
|
os_log("重新初始化ASR引擎失败", log: logger, type: .error) |
|
|
|
sendError("重新初始化ASR引擎失败", code: "ASR_INIT_ERROR") |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
os_log("成功设置支持的语言: %{public}@", log: logger, type: .info, languages.joined(separator: ", ")) |
|
|
|
|
|
|
|
|
|
|
|
// 同时更新TTS语言设置 |
|
|
|
let ttsSuccess = updateTtsLanguage(languages.first ?? "zh-CN") |
|
|
|
|
|
|
|
let overallSuccess = asrSuccess && ttsSuccess |
|
|
|
|
|
|
|
if overallSuccess { |
|
|
|
os_log("ASR和TTS语言设置更新成功: %{public}@", log: logger, type: .info, languages.joined(separator: ", ")) |
|
|
|
} else { |
|
|
|
os_log("语言设置更新失败 - ASR: %{public}@, TTS: %{public}@", log: logger, type: .error, String(asrSuccess), String(ttsSuccess)) |
|
|
|
} |
|
|
|
|
|
|
|
// 如果之前正在识别,重新开始 |
|
|
|
if wasRecognizing { |
|
|
|
_ = startRecognition() |
|
|
|
} |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
return overallSuccess |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 更新TTS语言设置 |
|
|
|
* |
|
|
|
* @param languageCode ASR语言代码,如 "zh-CN", "en-US" |
|
|
|
* @return 是否更新成功 |
|
|
|
*/ |
|
|
|
private func updateTtsLanguage(_ languageCode: String) -> Bool { |
|
|
|
os_log("更新TTS语言设置: %{public}@", log: logger, type: .info, languageCode) |
|
|
|
|
|
|
|
// 根据ASR语言代码映射到对应的TTS语音角色 |
|
|
|
let voiceName = getTtsVoiceNameByAsrCode(languageCode) |
|
|
|
|
|
|
|
if !voiceName.isEmpty { |
|
|
|
// 设置TTS语音角色 |
|
|
|
let success = azureTtsHelper?.setVoice(voiceName) ?? false |
|
|
|
|
|
|
|
if success { |
|
|
|
os_log("TTS语音角色设置成功: %{public}@", log: logger, type: .info, voiceName) |
|
|
|
} else { |
|
|
|
os_log("TTS语音角色设置失败: %{public}@", log: logger, type: .error, voiceName) |
|
|
|
} |
|
|
|
|
|
|
|
return success |
|
|
|
} else { |
|
|
|
os_log("未找到语言代码 %{public}@ 对应的TTS语音角色", log: logger, type: .error, languageCode) |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据ASR语言代码获取对应的TTS语音角色名称 |
|
|
|
* 与LanguageManager中的映射保持一致 |
|
|
|
* |
|
|
|
* @param asrCode ASR语言代码,如 "zh-CN", "en-US" |
|
|
|
* @return TTS语音角色名称 |
|
|
|
*/ |
|
|
|
private func getTtsVoiceNameByAsrCode(_ asrCode: String) -> String { |
|
|
|
switch asrCode { |
|
|
|
// 中文相关 |
|
|
|
case "zh-CN": |
|
|
|
return "zh-CN-XiaoxiaoNeural" |
|
|
|
case "zh-TW": |
|
|
|
return "zh-TW-HsiaoChenNeural" |
|
|
|
case "zh-HK": |
|
|
|
return "zh-HK-HiuMaanNeural" |
|
|
|
|
|
|
|
// 英语相关 |
|
|
|
case "en-US": |
|
|
|
return "en-US-AriaNeural" |
|
|
|
|
|
|
|
// 亚洲语言 |
|
|
|
case "ja-JP": |
|
|
|
return "ja-JP-NanamiNeural" |
|
|
|
case "ko-KR": |
|
|
|
return "ko-KR-SunHiNeural" |
|
|
|
case "th-TH": |
|
|
|
return "th-TH-PremwadeeNeural" |
|
|
|
case "vi-VN": |
|
|
|
return "vi-VN-HoaiMyNeural" |
|
|
|
case "id-ID": |
|
|
|
return "id-ID-GadisNeural" |
|
|
|
case "hi-IN": |
|
|
|
return "hi-IN-SwaraNeural" |
|
|
|
case "ms-MY": |
|
|
|
return "ms-MY-YasminNeural" |
|
|
|
case "bn-IN": |
|
|
|
return "bn-IN-TanishaaNeural" |
|
|
|
case "ta-IN": |
|
|
|
return "ta-IN-PallaviNeural" |
|
|
|
case "te-IN": |
|
|
|
return "te-IN-ShrutiNeural" |
|
|
|
case "mr-IN": |
|
|
|
return "mr-IN-AarohiNeural" |
|
|
|
case "ur-IN": |
|
|
|
return "ur-IN-GulNeural" |
|
|
|
case "tr-TR": |
|
|
|
return "tr-TR-EmelNeural" |
|
|
|
case "fa-IR": |
|
|
|
return "fa-IR-DilaraNeural" |
|
|
|
|
|
|
|
// 欧洲语言 |
|
|
|
case "fr-FR": |
|
|
|
return "fr-FR-DeniseNeural" |
|
|
|
case "es-ES": |
|
|
|
return "es-ES-ElviraNeural" |
|
|
|
case "pt-BR": |
|
|
|
return "pt-BR-FranciscaNeural" |
|
|
|
case "it-IT": |
|
|
|
return "it-IT-ElsaNeural" |
|
|
|
case "de-DE": |
|
|
|
return "de-DE-KatjaNeural" |
|
|
|
case "ru-RU": |
|
|
|
return "ru-RU-SvetlanaNeural" |
|
|
|
case "pl-PL": |
|
|
|
return "pl-PL-AgnieszkaNeural" |
|
|
|
case "nl-NL": |
|
|
|
return "nl-NL-ColetteNeural" |
|
|
|
case "sv-SE": |
|
|
|
return "sv-SE-SofieNeural" |
|
|
|
case "cs-CZ": |
|
|
|
return "cs-CZ-VlastaNeural" |
|
|
|
case "el-GR": |
|
|
|
return "el-GR-AthinaNeural" |
|
|
|
case "ro-RO": |
|
|
|
return "ro-RO-AlinaNeural" |
|
|
|
case "hu-HU": |
|
|
|
return "hu-HU-NoemiNeural" |
|
|
|
case "uk-UA": |
|
|
|
return "uk-UA-PolinaNeural" |
|
|
|
case "da-DK": |
|
|
|
return "da-DK-ChristelNeural" |
|
|
|
case "fi-FI": |
|
|
|
return "fi-FI-NooraNeural" |
|
|
|
case "nb-NO": |
|
|
|
return "nb-NO-IselinNeural" |
|
|
|
case "hr-HR": |
|
|
|
return "hr-HR-GabrijelaNeural" |
|
|
|
case "ca-ES": |
|
|
|
return "ca-ES-JoanaNeural" |
|
|
|
|
|
|
|
// 阿拉伯语和非洲语言 |
|
|
|
case "ar-EG": |
|
|
|
return "ar-EG-SalmaNeural" |
|
|
|
case "sw-KE": |
|
|
|
return "sw-KE-ZuriNeural" |
|
|
|
|
|
|
|
default: |
|
|
|
os_log("未支持的语言代码: %{public}@,使用默认英语语音", log: logger, type: .error, asrCode) |
|
|
|
return "en-US-AriaNeural" |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func dispose() -> Bool { |
|
|
|
print("ai释放资源") |
|
|
|
if isRecognizing { |
|
|
|
|