Files
voice.sori.studio/backend/app/config.py
zenn 7101fdcd65 Initial commit: Korean voice-cloning TTS prototype
FastAPI backend, web UI, CosyVoice3/F5-TTS setup scripts, and handoff docs for GPU PC continuation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 13:36:37 +09:00

66 lines
2.4 KiB
Python

from __future__ import annotations
from functools import lru_cache
from pathlib import Path
import yaml
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
ROOT = Path(__file__).resolve().parents[2]
class AppSettings(BaseSettings):
model_config = SettingsConfigDict(
env_file=str(ROOT / ".env"),
env_file_encoding="utf-8",
extra="ignore",
)
tts_model: str = Field(default="cosyvoice", validation_alias="TTS_MODEL")
host: str = Field(default="0.0.0.0", validation_alias="TTS_HOST")
port: int = Field(default=8000, validation_alias="TTS_PORT")
samples_dir: Path = Field(default=ROOT / "samples")
outputs_dir: Path = Field(default=ROOT / "outputs" / "api")
uploads_dir: Path = Field(default=ROOT / "backend" / "data" / "uploads")
default_ref_audio: str | None = Field(default=None, validation_alias="TTS_REF_AUDIO")
default_ref_text: str | None = Field(default=None, validation_alias="TTS_REF_TEXT")
cosyvoice_model_dir: Path = Field(default=ROOT / "models" / "Fun-CosyVoice3-0.5B")
cosyvoice_prompt_prefix: str = (
"You are a helpful assistant.<|endofprompt|>"
)
chunk_max_chars: int = 120
@lru_cache
def get_settings() -> AppSettings:
yaml_path = ROOT / "config" / "settings.yaml"
data: dict = {}
if yaml_path.is_file():
with open(yaml_path, encoding="utf-8") as f:
raw = yaml.safe_load(f) or {}
data["tts_model"] = raw.get("default_model", "cosyvoice")
gen = raw.get("generation") or {}
data["chunk_max_chars"] = gen.get("chunk_max_chars", 120)
cv = raw.get("cosyvoice") or {}
if cv.get("model_dir"):
data["cosyvoice_model_dir"] = ROOT / cv["model_dir"]
if cv.get("prompt_prefix"):
data["cosyvoice_prompt_prefix"] = cv["prompt_prefix"]
srv = raw.get("server") or {}
data["host"] = srv.get("host", "0.0.0.0")
data["port"] = srv.get("port", 8000)
paths = raw.get("paths") or {}
if paths.get("samples_dir"):
data["samples_dir"] = ROOT / paths["samples_dir"]
if paths.get("outputs_dir"):
data["outputs_dir"] = ROOT / paths["outputs_dir"] / "api"
if paths.get("uploads_dir"):
data["uploads_dir"] = ROOT / paths["uploads_dir"]
return AppSettings(**{k: v for k, v in data.items() if v is not None})
def project_root() -> Path:
return ROOT