This commit is contained in:
owenchen committed 2026-06-04 08:16:49 +08:00
1 parent 39494fb5c3
commit 871de41ba5
9 files changed
+259 -49

No files matched your search

+35 -8
View File
@@ -17,7 +17,7 @@ using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CloudBuilder.Topshelf.Task.TTS
{
//task:TtsTask book_id:B000008 voice:Sherpa2 actor:韩立 actor_voice:Sherpa1 save_path:D:\\Net8\\FileServer\\Backup\\DmsFile\\voice
//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:TtsTask voice:Sherpa2 save_path:D:\\Net8\\FileServer\\Backup\\DmsFile\\voice\\20260528112739.mp3 text:二愣子睁大着双眼,直直望着茅草和烂泥糊成的黑屋顶,身上盖着的旧棉被,已呈深黄色,看不出原来的本来面目,还若有若无的散发着淡淡的霉味。
public class TtsTask : IScheduleTask
{
@@ -38,7 +38,11 @@ namespace CloudBuilder.Topshelf.Task.TTS
if (bodyDict.ContainsKey("book_id"))
bookId = bodyDict["book_id"];
AiSentenceViewEntity[] ents = repository.DetachedEntities.Where(x => x.BookId == bookId).OrderBy(x => x.ChapterId).ThenBy(x => x.ParagraphId).ThenBy(x => x.SentenceIndex).ToArray();
string chapterId = string.Empty;
if (bodyDict.ContainsKey("chapter_id"))
chapterId = bodyDict["chapter_id"];
AiSentenceViewEntity[] ents = repository.DetachedEntities.Where(x => x.BookId == bookId && (string.IsNullOrEmpty(chapterId) || x.ChapterId == Convert.ToInt32(chapterId))).OrderBy(x => x.ChapterId).ThenBy(x => x.ParagraphId).ThenBy(x => x.SentenceIndex).ToArray();
if (ents == null || ents.Length == 0) return;
@@ -55,10 +59,15 @@ namespace CloudBuilder.Topshelf.Task.TTS
if (bodyDict.ContainsKey("save_path"))
save_path = bodyDict["save_path"];
GenerateAndMergeChapterAudio(ents, actor, actor_voice, voice, save_path);
float speed = 1.0f;
if (bodyDict.ContainsKey("speed"))
speed = Convert.ToSingle(bodyDict["speed"]);
GenerateAndMergeChapterAudio(ents, speed, actor, actor_voice, voice, save_path);
}
public void GenerateAndMergeChapterAudio(AiSentenceViewEntity[] ents, string actor, string actor_voice, string mainVoice, string save_path)
public void GenerateAndMergeChapterAudio(AiSentenceViewEntity[] ents, float speed, string actor, string actor_voice, string mainVoice, string save_path)
{
// 1. 按 BookId + ChapterId 分组(关键!)
var chapterGroups = ents
@@ -69,7 +78,7 @@ namespace CloudBuilder.Topshelf.Task.TTS
int totalLines = ents.Count();
int processedLines = 0; // 已处理行数计数器
UpdateProgress(processedLines, totalLines);
Dictionary<string, string> personMapping = new Dictionary<string, string>();
foreach (var chapter in chapterGroups)
{
string bookId = chapter.Key.BookId;
@@ -85,9 +94,27 @@ namespace CloudBuilder.Topshelf.Task.TTS
if (ent.DialogueIndc == YesNoPolicy.YES)
{
if (ent.PersonName == actor)
voice = actor_voice;
{
if (personMapping.ContainsKey(ent.PersonName))
voice = personMapping[ent.PersonName];
else
{
voice = actor_voice;
personMapping.Add(ent.PersonName, voice);
}
}
else
voice = AI.Policy.ChineseTtsVoiceRandom.GetRandom().ToString();
{
if (!string.IsNullOrEmpty(ent.PersonName) && personMapping.ContainsKey(ent.PersonName))
voice = personMapping[ent.PersonName];
else
{
voice = AI.Policy.ChineseTtsVoiceRandom.GetRandom(80).ToString();
personMapping.Add(ent.PersonName, voice);
}
}
}
else
{
@@ -102,7 +129,7 @@ namespace CloudBuilder.Topshelf.Task.TTS
string filePath = Path.Combine(save_path, fileName);
// 生成音频
SaveAudioToFileHelper.AudioToFile(EnumHelper.ToEnum<ChineseTtsVoice>(voice), ent.Content, filePath);
SaveAudioToFileHelper.AudioToFile(EnumHelper.ToEnum<ChineseTtsVoice>(voice), speed, ent.Content, filePath);
tempMp3List.Add(filePath); // 加入合并列表