84 lines
6.1 KiB
C#
84 lines
6.1 KiB
C#
using Flurl;
|
||
using Flurl.Http;
|
||
using ModelContextProtocol.Server;
|
||
using System.ComponentModel;
|
||
using System.ComponentModel.DataAnnotations;
|
||
|
||
namespace GLMSearch.Tool
|
||
{
|
||
[McpServerToolType]
|
||
public class Speech2
|
||
{
|
||
//SpeechGenerate
|
||
[McpServerTool(Name = "SpeechGenerate"),
|
||
Description("生成语音,并返回链接;在返回后应该输出一个 markdown 超链接 ,以播放语音;")]
|
||
public static string SpeechGenerate(
|
||
[Description("需要转换的文本,注意 这里传入的是播报的文本,请输入常规的文本格式而不是富文本;最终的语音播报会是这个文本所以需要注意不要传入富文本或无法播放的符号等"), Required] string input,
|
||
[Description("The voice to use (see Available Voices); 请务必从以下语音中选择: [\r\n \"zh-CN-XiaoxiaoNeural\",\r\n \"zh-CN-YunxiNeural\",\r\n \"zh-CN-YunjianNeural\",\r\n \"zh-CN-XiaoyiNeural\",\r\n \"zh-CN-YunyangNeural\",\r\n \"zh-CN-XiaochenNeural\",\r\n \"zh-CN-XiaochenMultilingualNeural\",\r\n \"zh-CN-XiaohanNeural\",\r\n \"zh-CN-XiaomengNeural\",\r\n \"zh-CN-XiaomoNeural\",\r\n \"zh-CN-XiaoqiuNeural\",\r\n \"zh-CN-XiaorouNeural\",\r\n \"zh-CN-XiaoruiNeural\",\r\n \"zh-CN-XiaoshuangNeural\",\r\n \"zh-CN-XiaoxiaoDialectsNeural\",\r\n \"zh-CN-XiaoxiaoMultilingualNeural\",\r\n \"zh-CN-XiaoyanNeural\",\r\n \"zh-CN-XiaoyouNeural\",\r\n \"zh-CN-XiaoyuMultilingualNeural\",\r\n \"zh-CN-XiaozhenNeural\",\r\n \"zh-CN-YunfengNeural\",\r\n \"zh-CN-YunhaoNeural\",\r\n \"zh-CN-YunjieNeural\",\r\n \"zh-CN-YunxiaNeural\",\r\n \"zh-CN-YunyeNeural\",\r\n \"zh-CN-YunyiMultilingualNeural\",\r\n \"zh-CN-YunzeNeural\",\r\n \"zh-CN-YunfanMultilingualNeural\",\r\n \"zh-CN-YunxiaoMultilingualNeural\",\r\n \"zh-CN-guangxi-YunqiNeural\",\r\n \"zh-CN-henan-YundengNeural\",\r\n \"zh-CN-liaoning-XiaobeiNeural\",\r\n \"zh-CN-liaoning-YunbiaoNeural\",\r\n \"zh-CN-shaanxi-XiaoniNeural\",\r\n \"zh-CN-shandong-YunxiangNeural\",\r\n \"zh-CN-sichuan-YunxiNeural\"\r\n]\r\n. Default: zh-CN-XiaoxiaoNeural "), Required] string voice = "zh-CN-XiaoxiaoNeural",
|
||
[Description("Can be used to guide voice emotion or style;请务必从以下选择:[\r\n \"advertisement-upbeat\",\r\n \"affectionate\",\r\n \"angry\",\r\n \"assistant\",\r\n \"calm\",\r\n \"chat\",\r\n \"chat-casual\",\r\n \"cheerful\",\r\n \"customerservice\",\r\n \"depressed\",\r\n \"disgruntled\",\r\n \"documentary-narration\",\r\n \"embarrassed\",\r\n \"empathetic\",\r\n \"envious\",\r\n \"excited\",\r\n \"fearful\",\r\n \"friendly\",\r\n \"gentle\",\r\n \"livecommercial\",\r\n \"lyrical\",\r\n \"narration-professional\",\r\n \"narration-relaxed\",\r\n \"newscast\",\r\n \"newscast-casual\",\r\n \"poetry-reading\",\r\n \"sad\",\r\n \"serious\",\r\n \"sorry\",\r\n \"sports-commentary\",\r\n \"sports-commentary-excited\",\r\n \"story\",\r\n \"whispering\"\r\n]\r\n Default: newscast"), Required] string instructions = "newscast",
|
||
[Description("The format of the audio response. Supported formats: audio-16khz-32kbitrate-mono-mp3 \tMP3格式,16kHz, 32kbps\r\naudio-16khz-64kbitrate-mono-mp3 \tMP3格式,16kHz, 64kbps\r\naudio-16khz-128kbitrate-mono-mp3 \tMP3格式,16kHz, 128kbps\r\naudio-24khz-48kbitrate-mono-mp3 \tMP3格式,24kHz, 48kbps\r\naudio-24khz-96kbitrate-mono-mp3 \tMP3格式,24kHz, 96kbps\r\naudio-24khz-160kbitrate-mono-mp3 \tMP3格式,24kHz, 160kbps\r\nriff-16khz-16bit-mono-pcm \tWAV格式,16kHz\r\nriff-24khz-16bit-mono-pcm \tWAV格式,24kHz. Defaults to audio-16khz-32kbitrate-mono-mp3.")]
|
||
string responseFormat = "audio-16khz-32kbitrate-mono-mp3")
|
||
{
|
||
var payload = new
|
||
{
|
||
t = input,//要转换的文本(需要进行URL编码)
|
||
v = voice,
|
||
s = instructions, // Mapped to "prompt" parameter in API
|
||
o = responseFormat
|
||
};
|
||
var filteredPayload = new System.Collections.Generic.Dictionary<string, object>();
|
||
foreach (var prop in payload.GetType().GetProperties())
|
||
{
|
||
var value = prop.GetValue(payload);
|
||
if (value != null)
|
||
{
|
||
filteredPayload[prop.Name] = value;
|
||
}
|
||
}
|
||
var response = "http://148.135.77.70:8010/tts"
|
||
.SetQueryParams(filteredPayload).GetAsync().GetAwaiter().GetResult();
|
||
if (response != null)
|
||
{
|
||
// 1. 获取应用程序基目录(适用于控制台/Windows服务)
|
||
string baseDir = AppContext.BaseDirectory;
|
||
|
||
// 2. 向上查找直到找到项目根目录(根据实际项目结构调整)
|
||
var projectRoot = FindProjectRoot(baseDir);
|
||
|
||
// 3. 创建tts目录(放在项目根目录下的wwwroot/tts中)
|
||
string ttsDir = Path.Combine(projectRoot, "wwwroot", "tts");
|
||
Directory.CreateDirectory(ttsDir);
|
||
// 4. 生成文件名和路径
|
||
string fileName = $"{Guid.NewGuid()}.mp3";
|
||
string filePath = Path.Combine(ttsDir, fileName);
|
||
using (var stream = response.GetStreamAsync().GetAwaiter().GetResult())
|
||
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||
{
|
||
stream.CopyTo(fileStream);
|
||
}
|
||
string publicUrl = $"https://search.mcp.shizhuoran.top/tts/{fileName}";
|
||
return publicUrl;
|
||
}
|
||
return "";
|
||
}
|
||
|
||
private static string FindProjectRoot(string startPath)
|
||
{
|
||
var directory = new DirectoryInfo(startPath);
|
||
|
||
// 向上查找直到找到包含.csproj文件的目录
|
||
while (directory != null)
|
||
{
|
||
if (Directory.GetFiles(directory.FullName, "*.csproj").Length > 0)
|
||
{
|
||
return directory.FullName;
|
||
}
|
||
directory = directory.Parent;
|
||
}
|
||
|
||
// 如果找不到,返回原始路径
|
||
return startPath;
|
||
}
|
||
}
|
||
}
|