ow
This commit is contained in:
commit
597b88d075
37 files changed
+3943
No files matched your search
@@ -0,0 +1,317 @@
|
||||
using SherpaOnnx;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace CloudBuilder.Topshelf.Utility
|
||||
{
|
||||
public static class SaveAudioToFileHelper
|
||||
{
|
||||
private static OfflineTts fanchenTTs = null;
|
||||
private static OfflineTts sherpaTTs = null;
|
||||
private static OfflineTts theresaTTs = null;
|
||||
private static OfflineTts meloTTs = null;
|
||||
private static OfflineTts icefallTTs = null;
|
||||
private static OfflineTts matchaTTs = null;
|
||||
private static OfflineTts eulaTTs = null;
|
||||
public static void InitConfig()
|
||||
{
|
||||
OfflineTtsConfig config;
|
||||
OfflineTtsGeneratedAudio audio;
|
||||
int numThreads = 4;
|
||||
if (fanchenTTs == null)
|
||||
{
|
||||
config = new OfflineTtsConfig();
|
||||
config.Model.Vits.Model = "tts-models/vits-zh-hf-fanchen-C/vits-zh-hf-fanchen-C.onnx";
|
||||
config.Model.Vits.Tokens = "tts-models/vits-zh-hf-fanchen-C/tokens.txt";
|
||||
config.Model.Vits.Lexicon = "tts-models/vits-zh-hf-fanchen-C/lexicon.txt";
|
||||
config.RuleFars = "tts-models/vits-zh-hf-fanchen-C/number.fst,tts-models/vits-zh-hf-fanchen-C/phone.fst";
|
||||
config.Model.NumThreads = numThreads;
|
||||
//187
|
||||
fanchenTTs = new OfflineTts(config);
|
||||
|
||||
config = new OfflineTtsConfig();
|
||||
config.Model.Vits.Model = "tts-models/sherpa-onnx-vits-zh-ll/model.onnx";
|
||||
config.Model.Vits.Tokens = "tts-models/sherpa-onnx-vits-zh-ll/tokens.txt";
|
||||
config.Model.Vits.Lexicon = "tts-models/sherpa-onnx-vits-zh-ll/lexicon.txt";
|
||||
config.RuleFars = "tts-models/sherpa-onnx-vits-zh-ll/number.fst,tts-models/sherpa-onnx-vits-zh-ll/phone.fst";
|
||||
config.Model.NumThreads = numThreads;
|
||||
//多人音质最好(0 - 4)
|
||||
sherpaTTs = new OfflineTts(config);
|
||||
|
||||
config = new OfflineTtsConfig();
|
||||
config.Model.Vits.Model = "tts-models/vits-zh-hf-theresa/theresa.onnx";
|
||||
config.Model.Vits.Tokens = "tts-models/vits-zh-hf-theresa/tokens.txt";
|
||||
config.Model.Vits.Lexicon = "tts-models/vits-zh-hf-theresa/lexicon.txt";
|
||||
config.RuleFars = "tts-models/vits-zh-hf-theresa/number.fst,tts-models/vits-zh-hf-theresa/phone.fst";
|
||||
config.Model.NumThreads = numThreads;
|
||||
//804
|
||||
theresaTTs = new OfflineTts(config);
|
||||
|
||||
config = new OfflineTtsConfig();
|
||||
config.Model.Vits.Model = "tts-models/vits-melo-tts-zh_en/model.onnx";
|
||||
config.Model.Vits.Tokens = "tts-models/vits-melo-tts-zh_en/tokens.txt";
|
||||
config.Model.Vits.Lexicon = "tts-models/vits-melo-tts-zh_en/lexicon.txt";
|
||||
config.RuleFars = "tts-models/vits-melo-tts-zh_en/number.fst,tts-models/vits-melo-tts-zh_en/phone.fst";
|
||||
config.Model.NumThreads = numThreads;
|
||||
//1
|
||||
meloTTs = new OfflineTts(config);
|
||||
|
||||
config = new OfflineTtsConfig();
|
||||
config.Model.Vits.Model = "tts-models/vits-icefall-zh-aishell3/model.onnx";
|
||||
config.Model.Vits.Tokens = "tts-models/vits-icefall-zh-aishell3/tokens.txt";
|
||||
config.Model.Vits.Lexicon = "tts-models/vits-icefall-zh-aishell3/lexicon.txt";
|
||||
config.RuleFars = "tts-models/vits-icefall-zh-aishell3/number.fst,tts-models/vits-icefall-zh-aishell3/phone.fst";
|
||||
config.Model.NumThreads = numThreads;
|
||||
//中文、32 个不同说话人,最快
|
||||
icefallTTs = new OfflineTts(config);
|
||||
|
||||
config = new OfflineTtsConfig();
|
||||
config.Model.Vits.Model = "tts-models/vits-zh-hf-eula/eula.onnx";
|
||||
config.Model.Vits.Tokens = "tts-models/vits-zh-hf-eula/tokens.txt";
|
||||
config.Model.Vits.Lexicon = "tts-models/vits-zh-hf-eula/lexicon.txt";
|
||||
config.RuleFars = "tts-models/vits-zh-hf-eula/number.fst,tts-models/vits-zh-hf-eula/phone.fst";
|
||||
config.Model.NumThreads = numThreads;
|
||||
|
||||
eulaTTs = new OfflineTts(config);
|
||||
|
||||
config = new OfflineTtsConfig();
|
||||
config.Model.Matcha.AcousticModel = "tts-models/matcha-icefall-zh-baker/model-steps-3.onnx";
|
||||
config.Model.Matcha.Vocoder = "tts-models/matcha-icefall-zh-baker/vocos-22khz-univ.onnx";
|
||||
config.Model.Matcha.Tokens = "tts-models/matcha-icefall-zh-baker/tokens.txt";
|
||||
config.Model.Matcha.Lexicon = "tts-models/matcha-icefall-zh-baker/lexicon.txt";
|
||||
config.RuleFars = "tts-models/matcha-icefall-zh-baker/number.fst,tts-models/matcha-icefall-zh-baker/phone.fst";
|
||||
config.Model.NumThreads = numThreads;
|
||||
//1
|
||||
matchaTTs = new OfflineTts(config);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void AudioToFile(ChineseTtsVoice actorName, string text, string saveFilePath)
|
||||
{
|
||||
InitConfig();
|
||||
int sid = 0;
|
||||
OfflineTtsGeneratedAudio audio;
|
||||
switch (actorName)
|
||||
{
|
||||
case ChineseTtsVoice.Fanchen10:
|
||||
case ChineseTtsVoice.Fanchen110:
|
||||
case ChineseTtsVoice.Fanchen6:
|
||||
case ChineseTtsVoice.Fanchen15:
|
||||
case ChineseTtsVoice.Fanchen2:
|
||||
case ChineseTtsVoice.Fanchen20:
|
||||
case ChineseTtsVoice.Fanchen14:
|
||||
case ChineseTtsVoice.Fanchen36:
|
||||
sid = actorName.GetSidId();
|
||||
audio = fanchenTTs.Generate(text, 1.0f, sid);
|
||||
break;
|
||||
case ChineseTtsVoice.Sherpa0:
|
||||
case ChineseTtsVoice.Sherpa1:
|
||||
case ChineseTtsVoice.Sherpa2:
|
||||
case ChineseTtsVoice.Sherpa3:
|
||||
case ChineseTtsVoice.Sherpa4:
|
||||
sid = actorName.GetSidId();
|
||||
audio = sherpaTTs.Generate(text, 1.0f, sid);
|
||||
break;
|
||||
case ChineseTtsVoice.Melo:
|
||||
sid = actorName.GetSidId();
|
||||
audio = meloTTs.Generate(text, 1.0f, sid);
|
||||
break;
|
||||
case ChineseTtsVoice.Eula:
|
||||
sid = actorName.GetSidId();
|
||||
audio = eulaTTs.Generate(text, 1.0f, sid);
|
||||
break;
|
||||
case ChineseTtsVoice.Theresa:
|
||||
sid = actorName.GetSidId();
|
||||
audio = theresaTTs.Generate(text, 1.0f, sid);
|
||||
break;
|
||||
case ChineseTtsVoice.Aaishe1:
|
||||
case ChineseTtsVoice.Aaishe6:
|
||||
case ChineseTtsVoice.Aaishe14:
|
||||
case ChineseTtsVoice.Aaishe15:
|
||||
case ChineseTtsVoice.Aaishe18:
|
||||
case ChineseTtsVoice.Aaishe10:
|
||||
sid = actorName.GetSidId();
|
||||
audio = icefallTTs.Generate(text, 1.0f, sid);
|
||||
break;
|
||||
default:
|
||||
sid = actorName.GetSidId();
|
||||
audio = matchaTTs.Generate(text, 1.0f, sid);
|
||||
break;
|
||||
}
|
||||
|
||||
// --- 4. 保存音频 ---
|
||||
audio.SaveToWaveFile(saveFilePath);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 微软Edge TTS中文语音音色枚举
|
||||
/// 对应官方Neural语音标识,覆盖港澳台及大陆各地区音色
|
||||
/// </summary>
|
||||
public enum ChineseTtsVoice
|
||||
{
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆) 娇柔(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 喜佳(女性)-0")]
|
||||
Sherpa0,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 柔美(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 柔美(女性)-2")]
|
||||
Sherpa2,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 知性(男性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 知性(男性)-4")]
|
||||
Sherpa4,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 知青(男性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 知青(男性)-3")]
|
||||
Sherpa3,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 中青(男性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 中青(男性)-1")]
|
||||
Sherpa1,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 爱莎(女性)- 文件小速度快
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 爱莎(女性)-6")]
|
||||
Aaishe6,
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 爱莎(女性)- 文件小速度快
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 爱莎(女性)-14")]
|
||||
Aaishe14,
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 爱莎(女性)- 文件小速度快
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 爱莎(女性)-18")]
|
||||
Aaishe18,
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 云健(男性)- 文件小速度快
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 云健(男性)-10")]
|
||||
Aaishe10,
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 爱莎(女性)- 文件小速度快
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 爱莎(女性)-1")]
|
||||
Aaishe1,
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 云健(男性)- 文件小速度快
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 云健(男性)-15")]
|
||||
Aaishe15,
|
||||
|
||||
/// 普通话(中国大陆) 云阳(男性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 云阳(男性)-10")]
|
||||
Fanchen10,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆) 云阳(男性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 云阳(男性)-110")]
|
||||
Fanchen110,
|
||||
/// 普通话(中国大陆) 喜佳(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 云夏(女性)-6")]
|
||||
Fanchen6,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆) 云阳(男性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 云阳(男性)-15")]
|
||||
Fanchen15,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆) 喜佳(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 喜佳(女性)-2")]
|
||||
Fanchen2,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆) 喜佳(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 喜佳(女性)-14")]
|
||||
Fanchen14,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆) 喜佳(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 喜佳(女性)-20")]
|
||||
Fanchen20,
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆) 喜佳(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 喜佳(女性)-36")]
|
||||
Fanchen36,
|
||||
|
||||
/// <summary>
|
||||
/// 粤语(香港)- 女性(男性)- 文件大
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("粤语(香港) 梅隆 (女性)-0")]
|
||||
Melo,
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 神精女(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 神精女(女性)-0")]
|
||||
Eula,
|
||||
|
||||
/// <summary>
|
||||
/// 普通话(中国大陆)- 小神精女(女性)
|
||||
/// </summary>
|
||||
[System.ComponentModel.Description("普通话(中国大陆) 小神精女(女性)-27")]
|
||||
Theresa,
|
||||
}
|
||||
|
||||
public static class ChineseTtsVoiceExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取枚举值对应的Description特性值
|
||||
/// </summary>
|
||||
/// <param name="voice">语音枚举值</param>
|
||||
/// <returns>描述字符串(无特性时返回枚举名称)</returns>
|
||||
public static int GetSidId(this ChineseTtsVoice voice)
|
||||
{
|
||||
// 获取枚举成员的特性
|
||||
var field = voice.GetType().GetField(voice.ToString());
|
||||
var attribute = field?.GetCustomAttribute<DescriptionAttribute>();
|
||||
|
||||
// 有特性返回描述,无则返回枚举名
|
||||
return Convert.ToInt32(attribute?.Description.Split('-')[1] ?? "0");
|
||||
}
|
||||
}
|
||||
|
||||
public static class EnumHelper
|
||||
{
|
||||
// 枚举转字符串
|
||||
public static string ToEnumString<T>(T value) where T : Enum
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
// 字符串转枚举
|
||||
public static T ToEnum<T>(string str) where T : struct, Enum
|
||||
{
|
||||
return Enum.TryParse<T>(str, out var result) ? result : default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using CloudBuilder.Core.DatabaseAccessor.Entity;
|
||||
using CloudBuilder.Topshelf.Python;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudBuilder.Topshelf.Utility
|
||||
{
|
||||
public class SegmenterHelper
|
||||
{
|
||||
public List<string> Cut(string text, Hanlp2 hanlp)
|
||||
{
|
||||
return hanlp.GetTokFine(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user