# app.py from app.gradio_app import build_demo from models.tts_router import cleanup_old_audio import os import huggingface_hub # ---------------------------- # Model bootstrap (unchanged) # ---------------------------- def ensure_model(): model_path = os.getenv("LLAMACPP_MODEL_PATH") repo_id = os.getenv("HF_MODEL_REPO") file_name = os.getenv("HF_MODEL_FILE") or (os.path.basename(model_path) if model_path else None) if not model_path or not repo_id or not file_name: raise RuntimeError( "Missing config: set LLAMACPP_MODEL_PATH and HF_MODEL_REPO in .env (optionally HF_MODEL_FILE)." ) if os.path.exists(model_path): print(f"[MODEL] Found existing model at {model_path}") return model_path os.makedirs(os.path.dirname(model_path), exist_ok=True) print(f"[MODEL] Downloading {file_name} from {repo_id} …") local_path = huggingface_hub.hf_hub_download( repo_id=repo_id, filename=file_name, local_dir=os.path.dirname(model_path), local_dir_use_symlinks=False, ) print(f"[MODEL] Saved at {local_path}") return local_path # ---------------------------------------- # TTS bootstrap: prefer piper, safe fallback # ---------------------------------------- def ensure_tts_engine(): """ If TTS_ENGINE == 'piper' but we cannot find a working binary, automatically fall back to 'pyttsx3' so the Space still speaks. """ engine = os.getenv("TTS_ENGINE", "pyttsx3").strip().lower() if engine != "piper": print(f"[TTS] Using engine: {engine}") return # Check for an executable piper binary piper_bin = os.getenv("PIPER_BIN", "piper") piper_model = os.getenv("PIPER_MODEL") # should be set if you want piper def _is_exec(path): return os.path.isfile(path) and os.access(path, os.X_OK) found = False if os.path.isabs(piper_bin) and _is_exec(piper_bin): found = True else: # try PATH from shutil import which if which(piper_bin) is not None: found = True if not found or not piper_model or not os.path.exists(piper_model): # Fall back msg = [] if not found: msg.append(f"piper binary '{piper_bin}' not found") if not piper_model: msg.append("PIPER_MODEL not set") elif not os.path.exists(piper_model): msg.append(f"PIPER_MODEL not found on disk: {piper_model}") print("[TTS] Piper not available -> falling back to pyttsx3. (" + "; ".join(msg) + ")") os.environ["TTS_ENGINE"] = "pyttsx3" else: print(f"[TTS] Using Piper: bin={piper_bin}, model={piper_model}") def main(): # Clean up old TTS files on boot cleanup_old_audio(keep_latest=None) # Download model if needed ensure_model() # Make TTS robust on Spaces ensure_tts_engine() demo = build_demo() # Let HF handle host/port; expose a public link demo.launch(share=True) if __name__ == "__main__": main()