From cbe94b84fca63a49957d3542b1dc09ccddb6767d Mon Sep 17 00:00:00 2001 From: AkkoYK <69787631+AkkoYK@users.noreply.github.com> Date: Fri, 22 Aug 2025 16:55:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BA=20FishAudio=20TTS=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=8F=AF=E9=80=89=E7=9A=84=20reference=5Fid=20?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E6=8C=87=E5=AE=9A=E5=8A=9F=E8=83=BD=20(#2513?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 移除TTS提供商:FishAudio TTS的角色名称查询机制,改为直接使用参考模型ID /// 修改内容 /// - 移除复杂的角色查询逻辑 删除了 get_reference_id_by_character 方法 移除了通过角色名称搜索模型ID的API调用逻辑 - 简化配置字段 将 fishaudio-tts-character 字段替换为 fishaudio-tts-reference-id 设置默认值为可莉的模型ID:626bb6d3f3364c9cbc3aa6a67300a664 - 优化代码结构 直接在初始化时获取reference_id 简化请求生成逻辑,直接使用配置的模型ID /// 修改原因 /// 避免同名冲突:不同模型可能使用相同的角色名称,导致获取错误的模型 提高性能:移除了额外的API查询步骤,减少延迟 增强可靠性:用户直接指定准确的模型ID,避免搜索失败的情况 简化维护:减少了代码复杂度,降低维护成本 /// 新的使用方式 /// 用户需要从 FishAudio 模型的详情页面/URL 中获取具体的模型ID(如 626bb6d3f3364c9cbc3aa6a67300a664),并在配置中直接填入 fishaudio-tts-reference-id 字段。 这个修改使得FishAudio TTS的配置更加直观和可靠,同时提升了系统的整体性能。 * Refactor: 添加FishAudio TTS reference_id格式验证 添加ID格式验证逻辑,防止无效的reference_id调用API失败。 验证32位十六进制格式并提供详细错误提示。 * Feat: 添加FishAudio TTS可选reference_id配置实现向前兼容 新增可选的reference_id字段,优先使用直接ID,未配置时回退到角色名称查询。 保持完全向前兼容,现有配置无需修改。 --- astrbot/core/config/default.py | 6 +++ .../sources/fishaudio_tts_api_source.py | 40 +++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index 70122a282..528e8f899 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -971,6 +971,7 @@ CONFIG_METADATA_2 = { "api_key": "", "api_base": "https://api.fish.audio/v1", "fishaudio-tts-character": "可莉", + "fishaudio-tts-reference-id": "", "timeout": "20", }, "阿里云百炼 TTS(API)": { @@ -1564,6 +1565,11 @@ CONFIG_METADATA_2 = { "type": "string", "hint": "fishaudio TTS 的角色。默认为可莉。更多角色请访问:https://fish.audio/zh-CN/discovery", }, + "fishaudio-tts-reference-id": { + "description": "reference_id", + "type": "string", + "hint": "fishaudio TTS 的参考模型ID(可选)。如果填入此字段,将直接使用模型ID而不通过角色名称查询。例如:626bb6d3f3364c9cbc3aa6a67300a664。更多模型请访问:https://fish.audio/zh-CN/discovery,进入模型详情界面后可复制模型ID", + }, "whisper_hint": { "description": "本地部署 Whisper 模型须知", "type": "string", diff --git a/astrbot/core/provider/sources/fishaudio_tts_api_source.py b/astrbot/core/provider/sources/fishaudio_tts_api_source.py index c0cf044b8..893f27463 100644 --- a/astrbot/core/provider/sources/fishaudio_tts_api_source.py +++ b/astrbot/core/provider/sources/fishaudio_tts_api_source.py @@ -1,5 +1,6 @@ import os import uuid +import re import ormsgpack from pydantic import BaseModel, conint from httpx import AsyncClient @@ -24,8 +25,8 @@ class ServeTTSRequest(BaseModel): # 参考音频 references: list[ServeReferenceAudio] = [] # 参考模型 ID - # 例如 https://fish.audio/m/7f92f8afb8ec43bf81429cc1c9199cb1/ - # 其中reference_id为 7f92f8afb8ec43bf81429cc1c9199cb1 + # 例如 https://fish.audio/m/626bb6d3f3364c9cbc3aa6a67300a664/ + # 其中reference_id为 626bb6d3f3364c9cbc3aa6a67300a664 reference_id: str | None = None # 对中英文文本进行标准化,这可以提高数字的稳定性 normalize: bool = True @@ -44,6 +45,7 @@ class ProviderFishAudioTTSAPI(TTSProvider): ) -> None: super().__init__(provider_config, provider_settings) self.chosen_api_key: str = provider_config.get("api_key", "") + self.reference_id: str = provider_config.get("fishaudio-tts-reference-id", "") self.character: str = provider_config.get("fishaudio-tts-character", "可莉") self.api_base: str = provider_config.get( "api_base", "https://api.fish-audio.cn/v1" @@ -81,11 +83,43 @@ class ProviderFishAudioTTSAPI(TTSProvider): return item["_id"] return None + def _validate_reference_id(self, reference_id: str) -> bool: + """ + 验证reference_id格式是否有效 + + Args: + reference_id: 参考模型ID + + Returns: + bool: ID是否有效 + """ + if not reference_id or not reference_id.strip(): + return False + + # FishAudio的reference_id通常是32位十六进制字符串 + # 例如: 626bb6d3f3364c9cbc3aa6a67300a664 + pattern = r'^[a-fA-F0-9]{32}$' + return bool(re.match(pattern, reference_id.strip())) + async def _generate_request(self, text: str) -> dict: + # 向前兼容逻辑:优先使用reference_id,如果没有则使用角色名称查询 + if self.reference_id and self.reference_id.strip(): + # 验证reference_id格式 + if not self._validate_reference_id(self.reference_id): + raise ValueError( + f"无效的FishAudio参考模型ID: '{self.reference_id}'. " + f"请确保ID是32位十六进制字符串(例如: 626bb6d3f3364c9cbc3aa6a67300a664)。" + f"您可以从 https://fish.audio/zh-CN/discovery 获取有效的模型ID。" + ) + reference_id = self.reference_id.strip() + else: + # 回退到原来的角色名称查询逻辑 + reference_id = await self._get_reference_id_by_character(self.character) + return ServeTTSRequest( text=text, format="wav", - reference_id=await self._get_reference_id_by_character(self.character), + reference_id=reference_id, ) async def get_audio(self, text: str) -> str: