Browse Source

feat(语音服务): 在设置语音识别语言时同步更新TTS语言

添加TTS语言同步功能,当设置ASR支持的语言时自动更新TTS语音角色
完善语言映射表,支持多种语言的语音角色配置
newdev_shunjiawei
lxm 1 year ago
parent
commit
68d7bb7033
  1. 122
      local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt
  2. 169
      local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift

122
local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt

@ -1113,7 +1113,7 @@ object AgentService : CoroutineScope {
}
/**
* 设置支持的语音识别语言
* 设置支持的语音识别语言,同时更新TTS语言设置
*/
fun setSupportedLanguages(languages: List<String>): Boolean {
if (!isInitialized) {
@ -1132,28 +1132,35 @@ object AgentService : CoroutineScope {
Log.i(TAG, "设置支持的语言: ${languages.joinToString(", ")}")
// 重新初始化ASR服务以应用新的语言设置
val success = azureAsrHelper?.initialize(
val asrSuccess = azureAsrHelper?.initialize(
subscriptionKey = this.azureSpeechKey,
region = this.azureSpeechRegion,
supportedLanguages = languages.toTypedArray(),
audioSourceType = audioSourceType
) ?: false
if (success) {
Log.i(TAG, "语言设置更新成功")
// 同时更新TTS语言设置
val ttsSuccess = updateTtsLanguage(languages.first()) // 使用第一个语言作为TTS语言
val overallSuccess = asrSuccess && ttsSuccess
if (overallSuccess) {
Log.i(TAG, "ASR和TTS语言设置更新成功")
sendEvent("languages_updated", mapOf(
"languages" to languages,
"status" to "success"
"status" to "success",
"asr_success" to asrSuccess,
"tts_success" to ttsSuccess
))
} else {
Log.e(TAG, "语言设置更新失败")
Log.e(TAG, "语言设置更新失败 - ASR: $asrSuccess, TTS: $ttsSuccess")
sendEvent("error", mapOf(
"code" to "LANGUAGE_UPDATE_FAILED",
"message" to "语言设置更新失败"
"message" to "语言设置更新失败 - ASR: $asrSuccess, TTS: $ttsSuccess"
))
}
success
overallSuccess
} catch (e: Exception) {
Log.e(TAG, "设置支持语言异常: ${e.message}")
sendEvent("error", mapOf(
@ -1164,6 +1171,105 @@ object AgentService : CoroutineScope {
}
}
/**
* 更新TTS语言设置
*
* @param languageCode ASR语言代码,如 "zh-CN", "en-US"
* @return 是否更新成功
*/
private fun updateTtsLanguage(languageCode: String): Boolean {
return try {
Log.i(TAG, "更新TTS语言设置: $languageCode")
// 根据ASR语言代码映射到对应的TTS语音角色
val voiceName = getTtsVoiceNameByAsrCode(languageCode)
if (voiceName.isNotEmpty()) {
// 设置TTS语音角色
val success = ttsService?.setVoice(voiceName) ?: false
if (success) {
Log.i(TAG, "TTS语音角色设置成功: $voiceName")
} else {
Log.w(TAG, "TTS语音角色设置失败: $voiceName")
}
success
} else {
Log.w(TAG, "未找到语言代码 $languageCode 对应的TTS语音角色")
false
}
} catch (e: Exception) {
Log.e(TAG, "更新TTS语言设置异常: ${e.message}")
false
}
}
/**
* 根据ASR语言代码获取对应的TTS语音角色名称
* 与LanguageManager中的映射保持一致
*
* @param asrCode ASR语言代码,如 "zh-CN", "en-US"
* @return TTS语音角色名称
*/
private fun getTtsVoiceNameByAsrCode(asrCode: String): String {
return when (asrCode) {
// 中文相关
"zh-CN" -> "zh-CN-XiaoxiaoNeural"
"zh-TW" -> "zh-TW-HsiaoChenNeural"
"zh-HK" -> "zh-HK-HiuMaanNeural"
// 英语相关
"en-US" -> "en-US-AriaNeural"
// 亚洲语言
"ja-JP" -> "ja-JP-NanamiNeural"
"ko-KR" -> "ko-KR-SunHiNeural"
"th-TH" -> "th-TH-PremwadeeNeural"
"vi-VN" -> "vi-VN-HoaiMyNeural"
"id-ID" -> "id-ID-GadisNeural"
"hi-IN" -> "hi-IN-SwaraNeural"
"ms-MY" -> "ms-MY-YasminNeural"
"bn-IN" -> "bn-IN-TanishaaNeural"
"ta-IN" -> "ta-IN-PallaviNeural"
"te-IN" -> "te-IN-ShrutiNeural"
"mr-IN" -> "mr-IN-AarohiNeural"
"ur-IN" -> "ur-IN-GulNeural"
"tr-TR" -> "tr-TR-EmelNeural"
"fa-IR" -> "fa-IR-DilaraNeural"
// 欧洲语言
"fr-FR" -> "fr-FR-DeniseNeural"
"es-ES" -> "es-ES-ElviraNeural"
"pt-BR" -> "pt-BR-FranciscaNeural"
"it-IT" -> "it-IT-ElsaNeural"
"de-DE" -> "de-DE-KatjaNeural"
"ru-RU" -> "ru-RU-SvetlanaNeural"
"pl-PL" -> "pl-PL-AgnieszkaNeural"
"nl-NL" -> "nl-NL-ColetteNeural"
"sv-SE" -> "sv-SE-SofieNeural"
"cs-CZ" -> "cs-CZ-VlastaNeural"
"el-GR" -> "el-GR-AthinaNeural"
"ro-RO" -> "ro-RO-AlinaNeural"
"hu-HU" -> "hu-HU-NoemiNeural"
"uk-UA" -> "uk-UA-PolinaNeural"
"da-DK" -> "da-DK-ChristelNeural"
"fi-FI" -> "fi-FI-NooraNeural"
"nb-NO" -> "nb-NO-IselinNeural"
"hr-HR" -> "hr-HR-GabrijelaNeural"
"ca-ES" -> "ca-ES-JoanaNeural"
// 阿拉伯语和非洲语言
"ar-EG" -> "ar-EG-SalmaNeural"
"sw-KE" -> "sw-KE-ZuriNeural"
else -> {
Log.w(TAG, "未支持的语言代码: $asrCode,使用默认英语语音")
"en-US-AriaNeural"
}
}
}
/**
* 保存聊天消息
*/

169
local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift

@ -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 {

Loading…
Cancel
Save