#!/usr/bin/env python3 """生成 ChatTTS 本地预设说话人(sample_random_speaker,走 GPU)。""" from __future__ import annotations import json import sys from datetime import datetime from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) import torch from config import CHATTTS_MODEL_DIR from tts_service import get_chattts_instance, reset_chattts_instance from voice_presets import ( DEFAULT_MANIFEST, MANIFEST_PATH, PRESETS_DIR, VOICES_DIR, ensure_manifest, ) def main() -> None: ensure_manifest() PRESETS_DIR.mkdir(parents=True, exist_ok=True) try: from whisper_service import reset_whisper_model reset_whisper_model() except Exception: pass reset_chattts_instance() chat, err = get_chattts_instance() if chat is None: raise SystemExit(f"ChatTTS 加载失败: {err}") if not hasattr(chat, "sample_random_speaker"): raise SystemExit("当前 ChatTTS 版本不支持 sample_random_speaker") presets = DEFAULT_MANIFEST["presets"] print(f"[INFO] 生成 {len(presets)} 个预设音色 → {PRESETS_DIR}") for item in presets: pid = item["id"] label = item["label"] out_path = PRESETS_DIR / f"{pid}.pt" spk_emb = chat.sample_random_speaker() payload = { "version": 1, "preset": True, "id": pid, "label": label, "spk_emb": spk_emb, "spk_smp": None, "txt_smp": "", "created_at": datetime.now().isoformat(), "source": "ChatTTS.sample_random_speaker", } torch.save(payload, out_path) print(f" [OK] {label} → {out_path.name}") manifest = json.loads(MANIFEST_PATH.read_text(encoding="utf-8")) manifest["generated_at"] = datetime.now().isoformat() manifest["chattts_model"] = str(CHATTTS_MODEL_DIR) MANIFEST_PATH.write_text( json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8", ) print("[OK] 全部预设音色生成完成") if __name__ == "__main__": main()