ow
This commit is contained in:
parent
44ed43516e
commit
996bb243df
@ -240,7 +240,7 @@ namespace CloudBuilder.AI.Service
|
||||
repositoryAiChapterEntity.InsertNow(data.AiChapters);
|
||||
|
||||
if (data.AiSentences == null || data.AiSentences.Count() == 0) return data;
|
||||
repositoryAiSentenceEntity.InsertNow(data.AiSentences);
|
||||
repositoryAiSentenceEntity.InsertNow(data.AiSentences);
|
||||
|
||||
return FindByKey(key);
|
||||
}
|
||||
@ -337,9 +337,13 @@ namespace CloudBuilder.AI.Service
|
||||
|
||||
private string PackTtsParameters(string voice, string save_path, string bookId, string chapterId)
|
||||
{
|
||||
//速度快,音质差
|
||||
//task:TtsTask book_id:B000008 chapter_id:3 speed:1 voice:Sherpa2 actor:韩立 actor_voice:Sherpa1 save_path:D:\\Net8\\FileServer\\Backup\\DmsFile\\voice
|
||||
//速度慢,音质好
|
||||
//task:SoVITSTtsTask book_id:B000011 chapter_id:3 save_path:D:\\Net8\\FileServer\\Backup\\DmsFile\\voice
|
||||
//非必要参数 voice:MIDDLE_AGED_FEMALE5 actor:韩立 actor_voice:YOUNG_MALE2
|
||||
List<string> para = new List<string>();
|
||||
para.Add("task:" + "TtsTask");
|
||||
para.Add("task:" + "SoVITSTtsTask");
|
||||
para.Add("book_id:" + bookId);
|
||||
para.Add("chapter_id:" + chapterId);
|
||||
para.Add("voice:" + voice);
|
||||
|
||||
@ -31,14 +31,6 @@ namespace CloudBuilder.AI.Entity
|
||||
public string PersonName { get; set; }
|
||||
[Column("actor_name")]
|
||||
public string? ActorName { get; set; }
|
||||
[Column("gender")]
|
||||
public string? Gender { get; set; }
|
||||
[Column("sentiment")]
|
||||
public string? Sentiment { get; set; }
|
||||
[Column("sound_file_path")]
|
||||
public string? SoundFilePath { get; set; }
|
||||
[Column("status")]
|
||||
public string? Status { get; set; }
|
||||
|
||||
public const string CREATED_DATETIME = "CreatedDatetime";
|
||||
public const string CREATED_BY = "CreatedBy";
|
||||
@ -48,13 +40,9 @@ namespace CloudBuilder.AI.Entity
|
||||
public const string BOOK_ID = "BookId";
|
||||
public const string PERSON_NAME = "PersonName";
|
||||
public const string ACTOR_NAME = "ActorName";
|
||||
public const string GENDER = "Gender";
|
||||
public const string SENTIMENT = "Sentiment";
|
||||
public const string SOUND_FILE_PATH = "SoundFilePath";
|
||||
public const string STATUS = "Status";
|
||||
|
||||
public const string DB_NAME_AI_BOOK_PERSON = "ai_book_person";
|
||||
public const string DB_NAME_FIELDS="created_datetime,created_by,updated_datetime,updated_by,person_id,book_id,person_name,actor_name,gender,sentiment,sound_file_path,status";
|
||||
public const string DB_NAME_FIELDS="created_datetime,created_by,updated_datetime,updated_by,person_id,book_id,person_name,actor_name";
|
||||
|
||||
public const string DB_CREATED_DATETIME = "created_datetime";
|
||||
public const string DB_CREATED_BY = "created_by";
|
||||
@ -64,10 +52,6 @@ namespace CloudBuilder.AI.Entity
|
||||
public const string DB_BOOK_ID = "book_id";
|
||||
public const string DB_PERSON_NAME = "person_name";
|
||||
public const string DB_ACTOR_NAME = "actor_name";
|
||||
public const string DB_GENDER = "gender";
|
||||
public const string DB_SENTIMENT = "sentiment";
|
||||
public const string DB_SOUND_FILE_PATH = "sound_file_path";
|
||||
public const string DB_STATUS = "status";
|
||||
|
||||
|
||||
public static AiBookPersonEntity GetInstance()
|
||||
@ -95,10 +79,6 @@ namespace CloudBuilder.AI.Entity
|
||||
this.BookId = source.BookId;
|
||||
this.PersonName = source.PersonName;
|
||||
this.ActorName = source.ActorName;
|
||||
this.Gender = source.Gender;
|
||||
this.Sentiment = source.Sentiment;
|
||||
this.SoundFilePath = source.SoundFilePath;
|
||||
this.Status = source.Status;
|
||||
|
||||
if (includeSystemFields)
|
||||
{
|
||||
|
||||
@ -97,9 +97,11 @@ namespace CloudBuilder.AI.Utility
|
||||
// 复姓列表
|
||||
private static readonly HashSet<string> CompoundSurnames = new HashSet<string>
|
||||
{
|
||||
"欧阳","太史","端木","上官","司马","东方","独孤","南宫",
|
||||
"万俟","闻人","夏侯","诸葛","尉迟","公羊","赫连","澹台",
|
||||
"皇甫","宗政","濮阳","公冶","太叔","申屠","公孙","慕容"
|
||||
"游竺", "权逯", "盖益", "桓公", "万俟", "司马", "上官", "欧阳",
|
||||
"夏侯", "诸葛", "闻人", "东方", "赫连", "皇甫", "尉迟", "公羊",
|
||||
"澹台", "公冶", "宗政", "濮阳", "淳于", "单于", "太叔", "申屠",
|
||||
"公孙", "仲孙", "轩辕", "令狐", "钟离", "宇文", "长孙", "慕容",
|
||||
"司徒", "司空"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -18,7 +18,7 @@ namespace CloudBuilder.AI.Utility
|
||||
// 动态生成的正则表达式(匹配所有配置的引号类型)
|
||||
private Regex _dynamicQuotePattern;
|
||||
// 引号内必须包含的结尾标点集合
|
||||
private readonly string _endPunctuations = "?!。,;:、……~·";
|
||||
private readonly string _endPunctuations = "?!.,;:?!。,;:、……~·";
|
||||
|
||||
/// <summary>
|
||||
/// 默认构造函数:初始化常用成对引号(中文、英文、直角引号)
|
||||
@ -48,47 +48,31 @@ namespace CloudBuilder.AI.Utility
|
||||
/// <summary>
|
||||
/// 初始化动态正则:根据配置的成对引号生成匹配规则
|
||||
/// </summary>
|
||||
//private void InitDynamicRegex()
|
||||
//{
|
||||
// if (_quotePairs.Count == 0)
|
||||
// {
|
||||
// // 空配置时生成空正则,避免匹配任何内容
|
||||
// _dynamicQuotePattern = new Regex(@"^$", RegexOptions.Compiled);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // 步骤1:转义所有引号(避免正则特殊字符冲突),拼接左/右引号匹配组
|
||||
// string escapedLeftQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.LeftQuote)));
|
||||
// string escapedRightQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.RightQuote)));
|
||||
// // 步骤2:转义标点集合,避免正则解析错误
|
||||
// string escapedPunctuations = Regex.Escape(_endPunctuations);
|
||||
|
||||
// // 步骤3:构建动态正则表达式
|
||||
// // 分组说明:
|
||||
// // ?<left>:匹配配置的任意左引号
|
||||
// // ?<content>:匹配引号内的内容(必须以指定标点结尾)
|
||||
// // ?<right>:匹配配置的任意右引号
|
||||
// string regexPattern = $@"(?<left>{escapedLeftQuotes})(?<content>.+?[{escapedPunctuations}])(?<right>{escapedRightQuotes})";
|
||||
// _dynamicQuotePattern = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.Singleline);
|
||||
//}
|
||||
|
||||
private void InitDynamicRegex()
|
||||
{
|
||||
if (_quotePairs.Count == 0)
|
||||
{
|
||||
// 空配置时生成空正则,避免匹配任何内容
|
||||
_dynamicQuotePattern = new Regex(@"^$", RegexOptions.Compiled);
|
||||
return;
|
||||
}
|
||||
|
||||
// 步骤1:转义所有引号(避免正则特殊字符冲突),拼接左/右引号匹配组
|
||||
string escapedLeftQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.LeftQuote)));
|
||||
string escapedRightQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.RightQuote)));
|
||||
// 步骤2:转义标点集合,避免正则解析错误
|
||||
string escapedPunctuations = Regex.Escape(_endPunctuations);
|
||||
|
||||
// ✅ 修复:移除必须以标点结尾的限制,匹配任意引号内容
|
||||
string regexPattern = $@"(?<left>{escapedLeftQuotes})(?<content>.+?)(?<right>{escapedRightQuotes})";
|
||||
|
||||
// 步骤3:构建动态正则表达式
|
||||
// 分组说明:
|
||||
// ?<left>:匹配配置的任意左引号
|
||||
// ?<content>:匹配引号内的内容(必须以指定标点结尾)
|
||||
// ?<right>:匹配配置的任意右引号
|
||||
string regexPattern = $@"(?<left>{escapedLeftQuotes})(?<content>.+?[{escapedPunctuations}])(?<right>{escapedRightQuotes})";
|
||||
_dynamicQuotePattern = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.Singleline);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 核心分割方法:按配置的成对引号分割文本,结果无引号字符
|
||||
/// </summary>
|
||||
@ -182,15 +166,12 @@ namespace CloudBuilder.AI.Utility
|
||||
/// <returns>true=包含对话,false=纯旁白/空文本</returns>
|
||||
public bool IsDialogue(string text)
|
||||
{
|
||||
// 1. 处理空文本/NULL,直接返回false
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return false;
|
||||
|
||||
// 2. 文本预处理:去空格、统一全角/半角引号
|
||||
string cleanedText = text.Trim();
|
||||
// 替换全角空格为半角,避免干扰判断
|
||||
cleanedText = Regex.Replace(cleanedText, @" ", " ");
|
||||
// 统一引号格式(中文弯引号、直引号 → 标准双引号)
|
||||
// 统一引号
|
||||
cleanedText = cleanedText.Replace("“", "\"")
|
||||
.Replace("”", "\"")
|
||||
.Replace("〝", "\"")
|
||||
@ -200,17 +181,34 @@ namespace CloudBuilder.AI.Utility
|
||||
.Replace("‘", "'")
|
||||
.Replace("’", "'");
|
||||
|
||||
// 3. 核心判断规则:
|
||||
var hasQuote = Regex.IsMatch(cleanedText, @""".+?""") ||
|
||||
Regex.IsMatch(cleanedText, @"[::,,]\s*"""); // 冒号/逗号+引号(说话标记)
|
||||
// 1. 存在说话引导标记(冒号/逗号 + 引号)
|
||||
bool hasDialogueTag = Regex.IsMatch(cleanedText, @"[::,,]\s*""");
|
||||
|
||||
var hasSingleQuote = Regex.IsMatch(cleanedText, @"'[^']+'");
|
||||
// 2. 提取所有双引号内容,逐个判断是否为有效对话
|
||||
var quotedMatches = Regex.Matches(cleanedText, @"""(?<content>.*?)""");
|
||||
bool hasValidDialogue = false;
|
||||
foreach (Match m in quotedMatches)
|
||||
{
|
||||
string content = m.Groups["content"].Value.Trim();
|
||||
if (string.IsNullOrEmpty(content)) continue;
|
||||
|
||||
// 4. 排除仅含引号符号的无效情况(修复:只匹配替换后的符号)
|
||||
var onlyQuote = Regex.IsMatch(cleanedText, @"^\s*[""']{1,2}\s*$");
|
||||
// 规则A:包含典型对话结尾标点
|
||||
bool endsWithDialogPunct = Regex.IsMatch(content, @"[。!??!…\.~~、,,]$");
|
||||
// 规则B:长度至少4个字符(或按中文字数算)
|
||||
bool isLongEnough = content.Length >= 4;
|
||||
|
||||
// 最终判断
|
||||
return (hasQuote || hasSingleQuote) && !onlyQuote;
|
||||
if (endsWithDialogPunct || isLongEnough)
|
||||
{
|
||||
hasValidDialogue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 单引号内容同理(可省略或同逻辑)
|
||||
|
||||
// 最终:有说话标记 或 存在有效对话内容,且不是“仅由引号符号组成”
|
||||
bool onlyQuote = Regex.IsMatch(cleanedText, @"^\s*[""']{1,2}\s*$");
|
||||
return (hasDialogueTag || hasValidDialogue) && !onlyQuote;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,12 +183,12 @@ namespace CloudBuilder.AI.Utility
|
||||
// -------------------- 常用组合快捷方法 --------------------
|
||||
public static SoVITSTtsVoice GetRandomElderlyMale() => GetRandomByGenderAndAge("男性", "老年人");
|
||||
public static SoVITSTtsVoice GetRandomElderlyFemale() => GetRandomByGenderAndAge("女性", "老年人");
|
||||
public static SoVITSTtsVoice GetRandomMiddleAgedMale() => GetRandomByGenderAndAge("男性", "中年");
|
||||
public static SoVITSTtsVoice GetRandomMiddleAgedFemale() => GetRandomByGenderAndAge("女性", "中年");
|
||||
public static SoVITSTtsVoice GetRandomYoungMale() => GetRandomByGenderAndAge("男性", "青年");
|
||||
public static SoVITSTtsVoice GetRandomYoungFemale() => GetRandomByGenderAndAge("女性", "青年");
|
||||
public static SoVITSTtsVoice GetRandomChildMale() => GetRandomByGenderAndAge("男性", "儿童");
|
||||
public static SoVITSTtsVoice GetRandomChildFemale() => GetRandomByGenderAndAge("女性", "儿童");
|
||||
public static SoVITSTtsVoice GetRandomMiddleAgedMale() => GetRandomByGenderAndAge("男性", "男中年");
|
||||
public static SoVITSTtsVoice GetRandomMiddleAgedFemale() => GetRandomByGenderAndAge("女性", "女中年");
|
||||
public static SoVITSTtsVoice GetRandomYoungMale() => GetRandomByGenderAndAge("男性", "男青年");
|
||||
public static SoVITSTtsVoice GetRandomYoungFemale() => GetRandomByGenderAndAge("女性", "女青年");
|
||||
public static SoVITSTtsVoice GetRandomChildMale() => GetRandomByGenderAndAge("男性", "男儿童");
|
||||
public static SoVITSTtsVoice GetRandomChildFemale() => GetRandomByGenderAndAge("女性", "女儿童");
|
||||
|
||||
// -------------------- 排除指定音色的扩展(可选)--------------------
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user