"""预置音色配置 — Phase 3 CosyVoice 集成. 定义系统预置的 CosyVoice 音色列表,不存数据库,以配置方式提供。 音色 ID 对应阿里云 CosyVoice 模型中的真实音色名。 参考: https://help.aliyun.com/zh/model-studio/cosyvoice-voice-list """ from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True, slots=True) class PresetVoice: """预置音色定义。 Attributes: voice_id: CosyVoice 模型音色名(如 longxiaochun_v3) name: 中文展示名 description: 音色描述 gender: 性别(male/female) language: 语言代码(如 zh-CN) preview_url: 预览音频 URL(可选) tags: 标签列表 """ voice_id: str name: str description: str gender: str language: str = "zh-CN" preview_url: str = "" tags: list[str] | None = None def to_dict(self) -> dict: """序列化为字典。""" return { "voice_id": self.voice_id, "name": self.name, "description": self.description, "gender": self.gender, "language": self.language, "preview_url": self.preview_url, "tags": self.tags or [], } # 预置音色列表(阿里云 CosyVoice 真实可用音色) PRESET_VOICES: list[PresetVoice] = [ PresetVoice( voice_id="longxiaochun_v3", name="龙小淳", description="温柔女声,适合情感类内容", gender="female", language="zh-CN", tags=["温柔", "女声", "情感"], ), PresetVoice( voice_id="longxiaoxia_v3", name="龙小夏", description="知性女声,适合新闻播报", gender="female", language="zh-CN", tags=["知性", "女声", "播报"], ), PresetVoice( voice_id="longxiaochen_v3", name="龙小晨", description="磁性男声,适合有声书", gender="male", language="zh-CN", tags=["磁性", "男声", "有声书"], ), PresetVoice( voice_id="longyue_v3", name="龙悦", description="甜美女声,适合广告配音", gender="female", language="zh-CN", tags=["甜美", "女声", "广告"], ), PresetVoice( voice_id="longshu_v3", name="龙书", description="沉稳男声,适合教育讲解", gender="male", language="zh-CN", tags=["沉稳", "男声", "教育"], ), PresetVoice( voice_id="longjing_v3", name="龙静", description="优雅女声,适合纪录片解说", gender="female", language="zh-CN", tags=["优雅", "女声", "纪录片"], ), PresetVoice( voice_id="longbo_v3", name="龙博", description="浑厚男声,适合科技类内容", gender="male", language="zh-CN", tags=["浑厚", "男声", "科技"], ), PresetVoice( voice_id="longtian_v3", name="龙甜", description="活泼女声,适合短视频配音", gender="female", language="zh-CN", tags=["活泼", "女声", "短视频"], ), ] def get_preset_voices() -> list[PresetVoice]: """获取所有预置音色。""" return PRESET_VOICES def get_preset_voice_by_id(voice_id: str) -> PresetVoice | None: """根据 voice_id 获取预置音色。""" for voice in PRESET_VOICES: if voice.voice_id == voice_id: return voice return None def is_preset_voice(voice_id: str) -> bool: """判断是否为预置音色。""" return get_preset_voice_by_id(voice_id) is not None