Spaces:
Build error
Build error
Download deploy.sh from radhapreetam/vani-speech-api: direct link, hf CLI and curl.
- Browser
- Download file 6.56 kB
-
https://huggingface.co/spaces/radhapreetam/vani-speech-api/resolve/main/deploy.sh
- Command line
-
hf download hf://spaces/radhapreetam/vani-speech-api/deploy.sh
-
curl -L -o deploy.sh https://huggingface.co/spaces/radhapreetam/vani-speech-api/resolve/main/deploy.sh
6.56 kB
| # --------------------------------------------------------------------------- | |
| # VANI Speech API β one-command deploy to Hugging Face Spaces. | |
| # | |
| # PURPOSE: create (or update) the Space, push this folder, wait for it to | |
| # build, then PROVE it is live by exercising the real endpoints over https | |
| # from outside β health, a real text-to-speech round trip, and a real | |
| # speech-to-text round trip using the audio that text-to-speech just produced. | |
| # | |
| # WHEN TO RUN: from RP's own terminal, which is the only shell with a Hugging | |
| # Face credential. Agent shells are not logged in (verified 2026-08-21: both | |
| # `hf repos create` and `hf upload` return 401 Unauthorized). | |
| # | |
| # WHEN NOT TO RUN: not from an agent session, and not as a scheduled job. | |
| # It is a deliberate, interactive deployment step. | |
| # | |
| # This script never asks for, prints, or stores a token. It only checks that | |
| # a credential is already present. | |
| # --------------------------------------------------------------------------- | |
| set -euo pipefail | |
| SPACE_ID="${VANI_SPACE_ID:-radhapreetam/vani-speech-api}" | |
| HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| SUB="$(echo "$SPACE_ID" | tr '/' '-' | tr '[:upper:]' '[:lower:]')" | |
| BASE="https://${SUB}.hf.space" | |
| say(){ printf '\n\033[1m== %s\033[0m\n' "$*"; } | |
| die(){ printf '\n\033[31mFAILED: %s\033[0m\n' "$*" >&2; exit 1; } | |
| # --- Gate 1: credential present (presence only, never the value) ------------ | |
| say "Gate 1/5 β checking you are logged in to Hugging Face" | |
| if ! WHO="$(hf auth whoami 2>&1)"; then | |
| die "Not logged in. Run 'hf auth login' yourself and paste your own token, then re-run this script. Never share the token." | |
| fi | |
| echo "Logged in as: $WHO" | |
| # --- Gate 2: the files we are about to ship are the ones we tested ---------- | |
| say "Gate 2/5 β checking the package is complete" | |
| for f in app.py requirements.txt SPACE_CARD.md packages.txt; do | |
| [ -f "$HERE/$f" ] || die "missing $f" | |
| done | |
| # On a Space, README.md is not documentation β its YAML frontmatter IS the | |
| # build configuration (sdk, sdk_version, app_file). The workspace automation | |
| # scripts/folder_readme.py rewrites README.md in every folder and would strip | |
| # that frontmatter, leaving a Space that cannot build. So README.md is | |
| # regenerated here, at upload time, from SPACE_CARD.md β which that automation | |
| # does not touch. | |
| cp "$HERE/SPACE_CARD.md" "$HERE/README.md" | |
| head -1 "$HERE/README.md" | grep -q '^---$' || die "SPACE_CARD.md has lost its YAML frontmatter β the Space will not build without it." | |
| grep -q '^app_file: app.py$' "$HERE/README.md" || die "Space card is missing 'app_file: app.py'." | |
| # Hugging Face rejects a Space whose short_description exceeds 60 characters, and it | |
| # only says so at UPLOAD time - after the repo has already been created. That cost a | |
| # real failed deploy on 2026-08-21 (61 characters, one over). Validate it HERE, before | |
| # anything is created, so the failure is cheap and self-explaining rather than a | |
| # mid-deploy error nobody can parse. | |
| _desc="$(sed -n 's/^short_description:[[:space:]]*//p' README.md | head -1)" | |
| _len=${#_desc} | |
| if [ "$_len" -gt 60 ]; then | |
| echo "STOP - short_description is ${_len} characters; Hugging Face allows 60." | |
| echo " Shorten it in SPACE_CARD.md (README.md is regenerated from it), then re-run." | |
| exit 1 | |
| fi | |
| echo "Space card regenerated from SPACE_CARD.md; frontmatter verified (short_description ${_len}/60)." | |
| grep -q "^mlx" "$HERE/requirements.txt" && die "requirements.txt contains an mlx package β those are Apple-silicon only and will not build on a Linux Space." | |
| python3 -c "import ast,sys; ast.parse(open('$HERE/app.py').read())" || die "app.py does not parse" | |
| echo "app.py parses; no Apple-silicon-only dependency present." | |
| # --- Gate 3: create the Space if it does not exist yet ---------------------- | |
| say "Gate 3/5 β ensuring the Space exists" | |
| if hf repos create "$SPACE_ID" --type space --sdk gradio 2>/dev/null; then | |
| echo "Created $SPACE_ID" | |
| else | |
| echo "$SPACE_ID already exists (or creation was declined) β continuing to upload." | |
| fi | |
| # --- Gate 4: upload ------------------------------------------------------- | |
| say "Gate 4/5 β uploading the package" | |
| hf upload "$SPACE_ID" "$HERE" . --repo-type space \ | |
| --exclude "__pycache__/*" --exclude "*.pyc" --exclude "DEPLOY.md" \ | |
| || die "upload failed" | |
| # --- Gate 5: prove it is actually live, from outside ----------------------- | |
| say "Gate 5/5 β proving it is live at $BASE (this includes a cold start; allow ~5 minutes)" | |
| echo "Waiting for /health to answer over https..." | |
| for i in $(seq 1 60); do | |
| if curl -fsS -m 15 "$BASE/health" >/tmp/vani_health.json 2>/dev/null; then | |
| echo "PROOF 1 β https health check answered from outside:"; cat /tmp/vani_health.json; echo; break | |
| fi | |
| printf '.'; sleep 15 | |
| [ "$i" -eq 60 ] && die "Space never answered /health. Open $BASE and read the build logs." | |
| done | |
| echo "Warming the models (first load downloads them)..." | |
| curl -fsS -m 900 -X POST "$BASE/warmup"; echo | |
| echo | |
| echo "PROOF 2 β real text in, real audio out:" | |
| curl -fsS -m 300 -X POST "$BASE/text-to-speech" \ | |
| -H 'Content-Type: application/json' \ | |
| -d '{"text":"Book the badminton court for Sunday morning."}' \ | |
| -o /tmp/vani_live.wav || die "text-to-speech failed" | |
| file /tmp/vani_live.wav | |
| echo | |
| echo "PROOF 3 β real audio in, real text out (feeding back the audio just generated):" | |
| curl -fsS -m 300 -X POST "$BASE/speech-to-text" \ | |
| -F "audio=@/tmp/vani_live.wav;type=audio/wav" || die "speech-to-text failed" | |
| echo | |
| echo | |
| echo "PROOF 4 β the page a stranger can open:" | |
| curl -fsS -m 30 -o /dev/null -w "GET %{url_effective} -> HTTP %{http_code}\n" "$BASE/" | |
| cat <<EOF | |
| =========================================================================== | |
| LIVE at: $BASE | |
| demo page $BASE/ | |
| health $BASE/health | |
| speech-to-text POST $BASE/speech-to-text (multipart, field "audio") | |
| text-to-speech POST $BASE/text-to-speech (JSON {"text": "..."}) | |
| Open $BASE/ in a browser and walk it once yourself β press and hold the | |
| button, say a sentence, and confirm the words appear. A browser is the only | |
| place the microphone permission prompt can actually be exercised. | |
| If the Space is PRIVATE, only you can open it. Make it public in | |
| Settings -> Change visibility before sending the link to anyone else. | |
| NEXT, SEPARATELY: the website page is prepared but NOT deployed. Review | |
| "Working Files/Vani/website_wiring/vani-demo.hosted.patch" | |
| and apply it to rp-website only when you want the live site to switch over. | |
| =========================================================================== | |
| EOF | |