Spaces:
Sleeping
Sleeping
| # app.py | |
| from app.gradio_app import build_demo | |
| from models.tts_router import cleanup_old_audio | |
| import os | |
| import shutil | |
| import stat | |
| import huggingface_hub | |
| from shutil import which | |
| # ----------------------------- | |
| # Model: ensure GGUF is present | |
| # ----------------------------- | |
| def ensure_model() -> str: | |
| """ | |
| Download the GGUF model into ./models if not already present. | |
| Requires in environment: | |
| - LLAMACPP_MODEL_PATH (target path including filename) | |
| - HF_MODEL_REPO (e.g. Qwen/Qwen2.5-1.5B-Instruct-GGUF) | |
| - HF_MODEL_FILE (e.g. qwen2.5-1.5b-instruct-q4_k_m.gguf) | |
| """ | |
| model_path = os.getenv("LLAMACPP_MODEL_PATH") | |
| repo_id = os.getenv("HF_MODEL_REPO") | |
| filename = 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 filename: | |
| raise RuntimeError("Missing config: set LLAMACPP_MODEL_PATH and HF_MODEL_REPO (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 {filename} from {repo_id} …") | |
| local_path = huggingface_hub.hf_hub_download( | |
| repo_id=repo_id, | |
| filename=filename, | |
| local_dir=os.path.dirname(model_path), | |
| local_dir_use_symlinks=False, | |
| ) | |
| # If hf_hub_download wrote elsewhere (cache), move/rename into desired path | |
| if os.path.abspath(local_path) != os.path.abspath(model_path): | |
| shutil.copyfile(local_path, model_path) | |
| print(f"[MODEL] Ready at {model_path}") | |
| return model_path | |
| # --------------------------------------- | |
| # Piper: rely on the PyPI wheel (piper-tts) | |
| # --------------------------------------- | |
| # --- keep your existing imports --- | |
| import os | |
| from huggingface_hub import hf_hub_download | |
| def ensure_piper_voice(): | |
| """ | |
| Make sure the Piper voice model exists at PIPER_MODEL. | |
| Defaults to Amy-medium English if none specified. | |
| """ | |
| target_path = os.getenv("PIPER_MODEL", "models/piper/en_US-amy-medium.onnx") | |
| repo_id = os.getenv("PIPER_VOICE_REPO", "rhasspy/piper-voices") | |
| hf_file = os.getenv("PIPER_VOICE_FILE", | |
| "en/en_US/en_US-amy-medium.onnx") # path inside the repo | |
| # If already present, we're done. | |
| if os.path.exists(target_path): | |
| print(f"[PIPER] Voice model present: {target_path}") | |
| return target_path | |
| os.makedirs(os.path.dirname(target_path), exist_ok=True) | |
| print(f"[PIPER] Downloading voice {hf_file} from {repo_id} …") | |
| local = hf_hub_download( | |
| repo_id=repo_id, | |
| filename=hf_file, | |
| local_dir=os.path.dirname(target_path), | |
| local_dir_use_symlinks=False, | |
| ) | |
| # Move/rename to the exact target filename if the name differs | |
| if os.path.abspath(local) != os.path.abspath(target_path): | |
| import shutil | |
| shutil.copyfile(local, target_path) | |
| print(f"[PIPER] Voice ready at: {target_path}") | |
| return target_path | |
| # No PIPER_BIN provided → try PATH | |
| resolved = which("piper") | |
| if resolved: | |
| print(f"[PIPER] Found in PATH: {resolved}") | |
| return resolved | |
| print("[PIPER] Not found. Install via 'piper-tts' wheel in requirements.txt.") | |
| return None | |
| def log_env_for_audio(): | |
| print("[ENV] TTS_ENGINE =", os.getenv("TTS_ENGINE", "(unset)")) | |
| print("[ENV] PIPER_MODEL=", os.getenv("PIPER_MODEL", "(unset)")) | |
| print("[ENV] PIPER_BIN =", os.getenv("PIPER_BIN", "(unset)")) | |
| # ------------- | |
| # Application | |
| # ------------- | |
| def main(): | |
| # Log a few envs to help debug Spaces | |
| log_env_for_audio() | |
| # Clean runtime/audio on boot | |
| cleanup_old_audio(keep_latest=None) | |
| # Ensure model exists locally | |
| ensure_model() | |
| ensure_piper_voice() | |
| # Launch Gradio | |
| demo = build_demo() | |
| # On Spaces, share=True is ignored (safe locally) | |
| demo.launch(share=True) | |
| if __name__ == "__main__": | |
| main() |