Browse Source

上传多语言和性别设置

newdev_shunjiawei
liwei1dao 6 months ago
parent
commit
4dd1eb1dd7
  1. 4
      lib/data/models/user_Info.dart
  2. 26
      lib/data/services/language_manager.dart
  3. 3
      lib/modules/profile/controllers/profile_controller.dart
  4. 20
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureTtsHelper.kt

4
lib/data/models/user_Info.dart

@ -112,7 +112,7 @@ class User {
);
_instance = u;
Logger.i("User",
"初始化用户: uid=${u.uid}, name=${u.name}, viplv=${u.viplv}, vipexptime=${u.vipexptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}");
"初始化用户: uid=${u.uid}, name=${u.name}, gender=${u.gender}, viplv=${u.viplv}, vipexptime=${u.vipexptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}");
return u;
}
@ -149,7 +149,7 @@ class User {
);
_instance = u;
Logger.i("User",
"初始化用户(token): uid=${u.uid}, name=${u.name}, viplv=${u.viplv}, vipexptime=${u.vipexptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}");
"初始化用户(token): uid=${u.uid}, name=${u.name}, gender=${u.gender}, viplv=${u.viplv}, vipexptime=${u.vipexptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}");
return u;
}

26
lib/data/services/language_manager.dart

@ -534,14 +534,24 @@ class LanguageManager extends GetxService {
return languageInfo?.shortCode;
}
/// 根据 shortCode 获取性别适配的 TTS 音色(用于 findBestMatchingProvider)
String? _getGenderAwareTtsCode(String shortCode) {
final asrCode = _shortCodeToAsrCodeMap[shortCode];
if (asrCode == null) return null;
return _getVoiceByGender(_languageMap[asrCode]);
}
/// 根据用户性别获取对应的 TTS 语音名称
/// gender: 0=未设置(默认女声), 1=男, 2=女
String? _getVoiceByGender(LanguageInfo? info) {
if (info == null) return null;
try {
final gender = User.instance.gender;
return gender == 1 ? info.ttsVoiceNameMale : info.ttsVoiceName;
final voice = gender == 1 ? info.ttsVoiceNameMale : info.ttsVoiceName;
Logger.debug('TTS音色选择: gender=$gender, voice=$voice');
return voice;
} catch (_) {
Logger.debug('TTS音色选择: 用户未初始化,使用默认女声');
return info.ttsVoiceName;
}
}
@ -662,27 +672,31 @@ class LanguageManager extends GetxService {
for (final spec in ttsSpecs) {
if (spec['shortCode'] == sourceShortCode) {
sourceTransSpec["ttsCode"] = spec["ttsVoiceName"]!;
sourceTransSpec["ttsCode"] =
_getGenderAwareTtsCode(spec['shortCode']!) ?? spec["ttsVoiceName"]!;
}
if (spec['shortCode'] == targetShortCode) {
targetTransSpec["ttsCode"] = spec["ttsVoiceName"]!;
targetTransSpec["ttsCode"] =
_getGenderAwareTtsCode(spec['shortCode']!) ?? spec["ttsVoiceName"]!;
}
}
} else if (provider == SpeechServiceType.alibaba) {
final ttsSpecs = _getTtsSpecs(provider);
for (final spec in ttsSpecs) {
if (spec['shortCode'] == sourceShortCode) {
sourceTransSpec["ttsCode"] = spec["ttsVoiceName"]!;
sourceTransSpec["ttsCode"] =
_getGenderAwareTtsCode(spec['shortCode']!) ?? spec["ttsVoiceName"]!;
}
if (spec['shortCode'] == targetShortCode) {
targetTransSpec["ttsCode"] = spec["ttsVoiceName"]!;
targetTransSpec["ttsCode"] =
_getGenderAwareTtsCode(spec['shortCode']!) ?? spec["ttsVoiceName"]!;
}
}
}
final providerString = _providerStringFromType(provider);
Logger.info(
'Found best provider: $providerString for $sourceShortCode -> $targetShortCode');
'Found best provider: $providerString for $sourceShortCode -> $targetShortCode, sourceTts=${sourceTransSpec["ttsCode"]}, targetTts=${targetTransSpec["ttsCode"]}');
return BestProviderResult(
providerString, sourceTransSpec, targetTransSpec);
}

3
lib/modules/profile/controllers/profile_controller.dart

@ -261,6 +261,9 @@ class ProfileController extends GetxController {
if (u != null) {
u.name = response['name'] ?? u.name;
u.avatar = response['avatar'] ?? u.avatar;
if (response['gender'] != null) {
u.gender = response['gender'] as int? ?? u.gender;
}
}
});

20
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureTtsHelper.kt

@ -418,8 +418,9 @@ class AzureTtsHelper(private val context: Context) : ITtsService {
private fun warmupSynthesizer() {
try {
// 使用极短文本进行预热
val lang = getLanguageFromVoice(currentVoice)
val warmupSsml = """
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="zh-CN">
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="$lang">
<voice name="$currentVoice">
<prosody rate="$currentRate" pitch="$currentPitch" volume="0%">
.
@ -500,11 +501,12 @@ class AzureTtsHelper(private val context: Context) : ITtsService {
}
// 4. 构造简化的SSML文档,减少嵌套层级
val lang = getLanguageFromVoice(currentVoice)
return """
<speak version="1.0"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:mstts="https://www.w3.org/2001/mstts"
xml:lang="zh-CN">
xml:lang="$lang">
<voice name="$currentVoice">
<mstts:express-as style="cheerful">
<prosody rate="$currentRate" pitch="$currentPitch" volume="$currentVolume">
@ -516,6 +518,14 @@ class AzureTtsHelper(private val context: Context) : ITtsService {
""".trimIndent()
}
/**
* 从语音名称中提取语言代码,如 "tr-TR-AhmetNeural" -> "tr-TR"
*/
private fun getLanguageFromVoice(voiceName: String): String {
val parts = voiceName.split("-")
return if (parts.size >= 2) "${parts[0]}-${parts[1]}" else DEFAULT_LANGUAGE
}
/**
* 生成优化的SSML(减少复杂度提升速度)
*/
@ -530,9 +540,11 @@ class AzureTtsHelper(private val context: Context) : ITtsService {
.replace(Regex("[😀-🟿]+"), "") // 简化表情符号移除
.trim()
val currentLanguage = getLanguageFromVoice(currentVoice)
if(enableVoiceFlocking) {
return """
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xml:lang="zh-CN">
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xml:lang="$currentLanguage">
<voice name="DragonLatestNeural">
<mstts:ttsembedding speakerProfileId="$speakerProfileId">
$processedText
@ -542,7 +554,7 @@ class AzureTtsHelper(private val context: Context) : ITtsService {
""".trimIndent()
} else {
return """
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="zh-CN">
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="$currentLanguage">
<voice name="$currentVoice">
<prosody rate="$currentRate" pitch="$currentPitch" volume="$currentVolume">
$processedText

Loading…
Cancel
Save