import os from pathlib import Path from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() # Project root - can be overridden by environment variable PROJECT_ROOT = Path( os.getenv("PROJECT_ROOT", Path(__file__).parent.parent.parent) ).resolve() # Directory paths SPEAKER_DATA_BASE_DIR = Path( os.getenv("SPEAKER_DATA_BASE_DIR", str(PROJECT_ROOT / "speaker_data")) ) SPEAKER_SAMPLES_DIR = Path( os.getenv("SPEAKER_SAMPLES_DIR", str(SPEAKER_DATA_BASE_DIR / "speaker_samples")) ) SPEAKERS_YAML_FILE = Path( os.getenv("SPEAKERS_YAML_FILE", str(SPEAKER_DATA_BASE_DIR / "speakers.yaml")) ) # TTS temporary output path (used by DialogProcessorService) TTS_TEMP_OUTPUT_DIR = Path( os.getenv("TTS_TEMP_OUTPUT_DIR", str(PROJECT_ROOT / "tts_temp_outputs")) ) # Final dialog output path (used by Dialog router and served by main app) # These are stored within the 'backend' directory to be easily servable. DIALOG_OUTPUT_PARENT_DIR = PROJECT_ROOT / "backend" DIALOG_GENERATED_DIR = Path( os.getenv( "DIALOG_GENERATED_DIR", str(DIALOG_OUTPUT_PARENT_DIR / "tts_generated_dialogs") ) ) # Alias for clarity and backward compatibility DIALOG_OUTPUT_DIR = DIALOG_GENERATED_DIR # Server configuration HOST = os.getenv("HOST", "0.0.0.0") PORT = int(os.getenv("PORT", "8000")) RELOAD = os.getenv("RELOAD", "true").lower() == "true" # CORS configuration: determine allowed origins based on env & frontend binding _cors_env = os.getenv("CORS_ORIGINS", "") _frontend_host = os.getenv("FRONTEND_HOST") _frontend_port = os.getenv("FRONTEND_PORT") # If the dev server is bound to 0.0.0.0 (all interfaces), allow all origins if _frontend_host == "0.0.0.0": # dev convenience when binding wildcard CORS_ORIGINS = ["*"] elif _cors_env: # parse comma-separated origins, strip whitespace CORS_ORIGINS = [origin.strip() for origin in _cors_env.split(",") if origin.strip()] else: # default to allow all origins in development CORS_ORIGINS = ["*"] # Auto-include specific frontend origin when not using wildcard CORS if CORS_ORIGINS != ["*"] and _frontend_host and _frontend_port: _frontend_origin = f"http://{_frontend_host.strip()}:{_frontend_port.strip()}" if _frontend_origin not in CORS_ORIGINS: CORS_ORIGINS.append(_frontend_origin) # Device configuration DEVICE = os.getenv("DEVICE", "auto") # Concurrency configuration # Max number of concurrent TTS generation tasks per dialog request TTS_MAX_CONCURRENCY = int(os.getenv("TTS_MAX_CONCURRENCY", "3")) # Model idle eviction configuration # Enable/disable idle-based model eviction MODEL_EVICTION_ENABLED = os.getenv("MODEL_EVICTION_ENABLED", "true").lower() == "true" # Unload model after this many seconds of inactivity (0 disables eviction) MODEL_IDLE_TIMEOUT_SECONDS = int(os.getenv("MODEL_IDLE_TIMEOUT_SECONDS", "900")) # How often the reaper checks for idleness MODEL_IDLE_CHECK_INTERVAL_SECONDS = int(os.getenv("MODEL_IDLE_CHECK_INTERVAL_SECONDS", "60")) # Ensure directories exist SPEAKER_SAMPLES_DIR.mkdir(parents=True, exist_ok=True) TTS_TEMP_OUTPUT_DIR.mkdir(parents=True, exist_ok=True) DIALOG_GENERATED_DIR.mkdir(parents=True, exist_ok=True)