Spaces:
Sleeping
Sleeping
| # app.py | |
| from app.gradio_app import build_demo | |
| from models.tts_router import cleanup_old_audio | |
| import os | |
| import huggingface_hub | |
| import urllib.request | |
| import tarfile | |
| import stat | |
| # --------------------------------------------------------------------- | |
| # Model helper | |
| # --------------------------------------------------------------------- | |
| def ensure_model(): | |
| """ | |
| Downloads the GGUF model into ./models if not already present. | |
| - LLAMACPP_MODEL_PATH must include the filename. | |
| - HF_MODEL_REPO must point to the Hugging Face repo. | |
| """ | |
| 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, HF_MODEL_REPO, HF_MODEL_FILE in .env") | |
| 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, | |
| ) | |
| print(f"[MODEL] Saved at {local_path}") | |
| return local_path | |
| # --------------------------------------------------------------------- | |
| # Piper helper | |
| # --------------------------------------------------------------------- | |
| def ensure_piper(): | |
| """ | |
| Ensure Piper binary and model are available. | |
| - Downloads a prebuilt Piper binary if not present. | |
| - Expects PIPER_MODEL already downloaded into ./models/piper/. | |
| """ | |
| piper_bin = os.getenv("PIPER_BIN", "piper") | |
| if os.path.isabs(piper_bin) and os.path.exists(piper_bin): | |
| print(f"[PIPER] Using existing binary at {piper_bin}") | |
| return piper_bin | |
| # place inside models/piper | |
| bin_dir = os.path.join("models", "piper") | |
| os.makedirs(bin_dir, exist_ok=True) | |
| desired_bin = os.path.join(bin_dir, "piper") | |
| if os.path.exists(desired_bin): | |
| print(f"[PIPER] Found at {desired_bin}") | |
| return desired_bin | |
| # download Linux prebuilt | |
| url = "https://github.com/rhasspy/piper/releases/download/v1.2.0/piper_linux_x86_64.tar.gz" | |
| tgz = os.path.join(bin_dir, "piper.tar.gz") | |
| print(f"[PIPER] Downloading from {url} …") | |
| urllib.request.urlretrieve(url, tgz) | |
| with tarfile.open(tgz, "r:gz") as tar: | |
| tar.extractall(bin_dir) | |
| os.remove(tgz) | |
| # find extracted binary | |
| for root, _, files in os.walk(bin_dir): | |
| if "piper" in files: | |
| candidate = os.path.join(root, "piper") | |
| os.chmod(candidate, os.stat(candidate).st_mode | stat.S_IEXEC) | |
| os.rename(candidate, desired_bin) | |
| break | |
| if not os.path.exists(desired_bin): | |
| raise RuntimeError("Piper binary not found after extraction") | |
| print(f"[PIPER] Installed at {desired_bin}") | |
| return desired_bin | |
| # --------------------------------------------------------------------- | |
| # Main | |
| # --------------------------------------------------------------------- | |
| def main(): | |
| # Clean up any old TTS files | |
| cleanup_old_audio(keep_latest=None) | |
| # Ensure model + piper | |
| ensure_model() | |
| ensure_piper() | |
| # Launch Gradio demo | |
| demo = build_demo() | |
| demo.launch(share=True) # On HF, share=True is ignored, but safe locally | |
| if __name__ == "__main__": | |
| main() |