From 103edd5260be926fd02bcfa748c76ec1ff6498d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B4=94=E6=B0=B8=E4=BA=AE?= <702625325@qq.com> Date: Sat, 1 Mar 2025 14:21:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20GSVI=20tts=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20#545=20#351?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- astrbot/core/config/default.py | 9 ++++ astrbot/core/provider/manager.py | 2 + .../core/provider/sources/gsvi_tts_source.py | 48 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 astrbot/core/provider/sources/gsvi_tts_source.py diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index 7296bc06e..f95c2fe59 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -608,6 +608,15 @@ CONFIG_METADATA_2 = { "edge-tts-voice": "zh-CN-XiaoxiaoNeural", "timeout": 20, }, + "GSVI_TTS(API)": { + "id": "gsvi_tts", + "type": "gsvi_tts_api", + "api_base": "http://127.0.0.1/5000", + "character": "", + "emotion": "default", + "enable": False, + "timeout": 20, + }, "FishAudio_TTS(API)": { "id": "fishaudio_tts", "type": "fishaudio_tts_api", diff --git a/astrbot/core/provider/manager.py b/astrbot/core/provider/manager.py index 6232695fc..546198094 100644 --- a/astrbot/core/provider/manager.py +++ b/astrbot/core/provider/manager.py @@ -154,6 +154,8 @@ class ProviderManager(): from .sources.openai_tts_api_source import ProviderOpenAITTSAPI as ProviderOpenAITTSAPI case "edge_tts": from .sources.edge_tts_source import ProviderEdgeTTS as ProviderEdgeTTS + case "gsvi_tts_api": + from .sources.gsvi_tts_source import ProviderGSVITTS as ProviderGSVITTS case "fishaudio_tts_api": from .sources.fishaudio_tts_api_source import ProviderFishAudioTTSAPI as ProviderFishAudioTTSAPI except (ImportError, ModuleNotFoundError) as e: diff --git a/astrbot/core/provider/sources/gsvi_tts_source.py b/astrbot/core/provider/sources/gsvi_tts_source.py new file mode 100644 index 000000000..1a84865a7 --- /dev/null +++ b/astrbot/core/provider/sources/gsvi_tts_source.py @@ -0,0 +1,48 @@ +import uuid +import os +import aiohttp +import urllib.parse +from ..provider import TTSProvider +from ..entites import ProviderType +from ..register import register_provider_adapter + + +@register_provider_adapter("gsvi_tts_api", "GSVI TTS API", provider_type=ProviderType.TEXT_TO_SPEECH) +class ProviderGSVITTS(TTSProvider): + def __init__( + self, + provider_config: dict, + provider_settings: dict, + ) -> None: + super().__init__(provider_config, provider_settings) + self.api_base = provider_config.get("api_base", "http://127.0.0.1:5000") + self.character = provider_config.get("character") + self.emotion = provider_config.get("emotion") + self.format = provider_config.get("format") + + async def get_audio(self, text: str) -> str: + path = f'data/temp/gsvi_tts_{uuid.uuid4()}.{self.format or "wav"}' + params = {"text": text} + + if self.character: + params["character"] = self.character + if self.emotion: + params["emotion"] = self.emotion + + query_parts = [] + for key, value in params.items(): + encoded_value = urllib.parse.quote(str(value)) + query_parts.append(f"{key}={encoded_value}") + + url = f"{self.api_base}/tts?{'&'.join(query_parts)}" + + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + if response.status == 200: + with open(path, 'wb') as f: + f.write(await response.read()) + else: + error_text = await response.text() + raise Exception(f"GSVI TTS API 请求失败,状态码: {response.status},错误: {error_text}") + + return path \ No newline at end of file