""" 系统音色初始化脚本 初始化系统预置音色数据到数据库。 注意:此脚本用于初始化数据库,系统运行时所有音色数据均从数据库获取,不包含硬编码。 数据来源说明: - 当前版本:基于阿里云百炼平台CosyVoice模型的官方音色文档手动整理 - 未来版本:如果DashScope SDK提供获取系统音色的API,可改为从SDK同步 需求: 4.1 """ import sys from pathlib import Path # 添加项目根目录到路径 sys.path.insert(0, str(Path(__file__).parent.parent)) from app.database import SessionLocal from app.models.audio import SystemVoice # 系统预置音色数据 # 注意:此数据仅用于初始化数据库,系统运行时所有音色均从数据库获取 # 基于阿里云百炼平台CosyVoice模型的官方音色文档整理 # 如果DashScope SDK未来提供获取系统音色的API,可改为从SDK动态获取 SYSTEM_VOICES = [ # ==================== 社交陪伴类 ==================== { "voice_id": "longanyang", "name": "龙安洋", "trait": "阳光大男孩", "age": "20~30岁", "category": "社交陪伴", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longanhuan", "name": "龙安欢", "trait": "欢脱元气女", "age": "20~30岁", "category": "社交陪伴", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longanjing", "name": "龙安静", "trait": "温柔知性女", "age": "20~30岁", "category": "社交陪伴", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longanshu", "name": "龙安舒", "trait": "成熟稳重男", "age": "30~40岁", "category": "社交陪伴", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, # ==================== 客服类 ==================== { "voice_id": "longxiaoxia", "name": "龙小夏", "trait": "甜美客服女声", "age": "20~30岁", "category": "客服", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longlaotie", "name": "龙老铁", "trait": "亲切客服男声", "age": "30~40岁", "category": "客服", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, # ==================== 新闻播报类 ==================== { "voice_id": "longshuo", "name": "龙硕", "trait": "专业新闻男声", "age": "30~40岁", "category": "新闻播报", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longwan", "name": "龙婉", "trait": "专业新闻女声", "age": "30~40岁", "category": "新闻播报", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, # ==================== 有声书类 ==================== { "voice_id": "longyue", "name": "龙悦", "trait": "温暖讲述女声", "age": "30~40岁", "category": "有声书", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longcheng", "name": "龙城", "trait": "磁性讲述男声", "age": "30~40岁", "category": "有声书", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longshu", "name": "龙书", "trait": "儿童故事女声", "age": "20~30岁", "category": "有声书", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, # ==================== 短视频配音类 ==================== { "voice_id": "longxiaochun", "name": "龙小淳", "trait": "活泼解说女声", "age": "20~30岁", "category": "短视频配音", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longxiaobai", "name": "龙小白", "trait": "幽默解说男声", "age": "20~30岁", "category": "短视频配音", "languages": ["中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, # ==================== 多语言类 ==================== { "voice_id": "longjielidou", "name": "龙杰力豆", "trait": "英语男声", "age": "30~40岁", "category": "多语言", "languages": ["英文", "中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longmeimei", "name": "龙美美", "trait": "英语女声", "age": "20~30岁", "category": "多语言", "languages": ["英文", "中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longyuuko", "name": "龙优子", "trait": "日语女声", "age": "20~30岁", "category": "多语言", "languages": ["日文", "中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longtaro", "name": "龙太郎", "trait": "日语男声", "age": "30~40岁", "category": "多语言", "languages": ["日文", "中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longmina", "name": "龙美娜", "trait": "韩语女声", "age": "20~30岁", "category": "多语言", "languages": ["韩文", "中文(普通话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, # ==================== 方言类 ==================== { "voice_id": "longdongbei", "name": "龙东北", "trait": "东北话男声", "age": "30~40岁", "category": "方言", "languages": ["中文(东北话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longsichuan", "name": "龙四川", "trait": "四川话男声", "age": "30~40岁", "category": "方言", "languages": ["中文(四川话)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longminnan", "name": "龙闽南", "trait": "闽南语女声", "age": "30~40岁", "category": "方言", "languages": ["中文(闽南语)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, { "voice_id": "longyueyu", "name": "龙粤语", "trait": "粤语男声", "age": "30~40岁", "category": "方言", "languages": ["中文(粤语)"], "models": ["cosyvoice-v3-flash", "cosyvoice-v3-plus"], "ssml_support": True, "instruct_support": True, "timestamp_support": True }, # ==================== CosyVoice-v2 专用音色 ==================== { "voice_id": "longxiaochun_v2", "name": "龙小淳V2", "trait": "活泼解说女声", "age": "20~30岁", "category": "通用", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v2"], "ssml_support": True, "instruct_support": False, "timestamp_support": True }, { "voice_id": "longxiaoxia_v2", "name": "龙小夏V2", "trait": "甜美客服女声", "age": "20~30岁", "category": "通用", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v2"], "ssml_support": True, "instruct_support": False, "timestamp_support": True }, { "voice_id": "longlaotie_v2", "name": "龙老铁V2", "trait": "亲切客服男声", "age": "30~40岁", "category": "通用", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v2"], "ssml_support": True, "instruct_support": False, "timestamp_support": True }, { "voice_id": "longshuo_v2", "name": "龙硕V2", "trait": "专业新闻男声", "age": "30~40岁", "category": "通用", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v2"], "ssml_support": True, "instruct_support": False, "timestamp_support": True }, { "voice_id": "longwan_v2", "name": "龙婉V2", "trait": "专业新闻女声", "age": "30~40岁", "category": "通用", "languages": ["中文(普通话)", "英文"], "models": ["cosyvoice-v2"], "ssml_support": True, "instruct_support": False, "timestamp_support": True }, ] def init_system_voices(): """初始化系统音色数据""" db = SessionLocal() inserted = 0 updated = 0 try: for voice_data in SYSTEM_VOICES: # 检查是否已存在 existing = db.query(SystemVoice).filter( SystemVoice.voice_id == voice_data["voice_id"] ).first() if existing: # 更新现有记录 existing.name = voice_data["name"] existing.trait = voice_data["trait"] existing.age = voice_data["age"] existing.category = voice_data["category"] existing.languages = voice_data["languages"] existing.models = voice_data["models"] existing.ssml_support = voice_data["ssml_support"] existing.instruct_support = voice_data["instruct_support"] existing.timestamp_support = voice_data.get("timestamp_support", False) existing.is_active = True updated += 1 else: # 创建新记录 voice = SystemVoice( voice_id=voice_data["voice_id"], name=voice_data["name"], trait=voice_data["trait"], age=voice_data["age"], category=voice_data["category"], languages=voice_data["languages"], models=voice_data["models"], ssml_support=voice_data["ssml_support"], instruct_support=voice_data["instruct_support"], timestamp_support=voice_data.get("timestamp_support", False), is_active=True ) db.add(voice) inserted += 1 db.commit() print(f"系统音色初始化完成: 新增 {inserted} 条, 更新 {updated} 条, 共 {inserted + updated} 条") except Exception as e: db.rollback() print(f"系统音色初始化失败: {e}") raise finally: db.close() def list_system_voices(): """列出所有系统音色""" db = SessionLocal() try: voices = db.query(SystemVoice).filter(SystemVoice.is_active == True).all() print(f"\n当前系统音色列表 (共 {len(voices)} 个):") print("-" * 80) # 按分类分组显示 categories = {} for voice in voices: cat = voice.category or "未分类" if cat not in categories: categories[cat] = [] categories[cat].append(voice) for category, voice_list in sorted(categories.items()): print(f"\n【{category}】") for voice in voice_list: models_str = ", ".join(voice.models) if voice.models else "无" print(f" - {voice.voice_id}: {voice.name} ({voice.trait}) - 模型: {models_str}") print("-" * 80) finally: db.close() def clear_system_voices(): """清空所有系统音色(谨慎使用)""" db = SessionLocal() try: count = db.query(SystemVoice).delete() db.commit() print(f"已清空 {count} 条系统音色记录") except Exception as e: db.rollback() print(f"清空失败: {e}") raise finally: db.close() if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description="系统音色管理脚本") parser.add_argument( "action", choices=["init", "list", "clear"], nargs="?", default="init", help="操作类型: init(初始化), list(列表), clear(清空)" ) args = parser.parse_args() if args.action == "init": init_system_voices() elif args.action == "list": list_system_voices() elif args.action == "clear": confirm = input("确定要清空所有系统音色吗?(yes/no): ") if confirm.lower() == "yes": clear_system_voices() else: print("操作已取消")