install.sh
Rama master · réplica de lectura del repositorio original.
#!/usr/bin/env bash
# Hearthwave native install — run once on a fresh Debian/Ubuntu machine.
# Creates a Python venv at .venv/, installs all deps, and validates the setup.
#
# Usage:
# bash install.sh # full install (small.en + large-v3-turbo)
# bash install.sh --no-models # skip model download (copy Models/ manually)
# bash install.sh --final-model distil-large-v3 # stage a different two-tier
# # final-pass model
# bash install.sh --final-model none # skip the final-pass model (single-pass RX)
# bash install.sh --dev # also install test deps (pytest, httpx)
set -euo pipefail
MODELS=true
DEV=false
# Two-tier final-pass model staged by default. whisper_model_final="auto" (the
# fresh-install default) resolves to the best staged model, and its preference
# order puts large-v3-turbo first — so staging turbo here is what makes "auto"
# resolve to anything at all on a new install.
FINAL_MODEL="large-v3-turbo"
while [[ $# -gt 0 ]]; do
case "$1" in
--no-models) MODELS=false; shift ;;
--dev) DEV=true; shift ;;
--final-model)
[[ $# -lt 2 ]] && { echo "Error: --final-model requires a value." >&2; exit 1; }
FINAL_MODEL="$2"; shift 2 ;;
*) echo "Unknown argument: $1" >&2; exit 1 ;;
esac
done
# "none"/"off" (and "") mean: single-pass RX, stage no final model.
[[ "$FINAL_MODEL" == "none" || "$FINAL_MODEL" == "off" ]] && FINAL_MODEL=""
# ── 1. System packages ───────────────────────────────────────────────────────
echo "==> Installing system packages..."
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends \
python3 \
python3-venv \
python3-pip \
build-essential \
gcc \
libportaudio2 \
libsndfile1 \
espeak-ng \
espeak-ng-data \
pulseaudio-utils \
curl \
ca-certificates
# Node.js 20 (LTS) via NodeSource — skip if already at v18+.
NODE_MAJOR=$(node --version 2>/dev/null | grep -oP '(?<=v)\d+' || echo 0)
if [ "$NODE_MAJOR" -lt 18 ]; then
echo "==> Installing Node.js 20 (LTS)..."
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
else
echo "==> Node.js $(node --version) already installed, skipping."
fi
# ── 2. Frontend dependencies ─────────────────────────────────────────────────
echo "==> Installing frontend npm packages (MUI, React, Vite, …)..."
(cd frontend && npm ci)
# ── 3. Docker image cache (optional but speeds up first `docker compose up`) ──
if command -v docker &>/dev/null; then
echo "==> Pulling Docker base images..."
docker compose pull --quiet 2>/dev/null || true
docker compose -f docker-compose.yml -f docker-compose.dev.yml pull --quiet 2>/dev/null || true
fi
# ── 4. Python virtual environment ───────────────────────────────────────────
echo "==> Creating Python venv at .venv/ ..."
python3 -m venv .venv
source .venv/bin/activate
echo "==> Installing Python packages (this will take a few minutes)..."
pip install --upgrade pip --quiet
if $DEV; then
pip install -r backend/requirements.txt -r backend/requirements-dev.txt
echo " Test deps installed — run the suite with: cd backend && python -m pytest"
else
pip install -r backend/requirements.txt
fi
# ── 5. Models ────────────────────────────────────────────────────────────────
if $MODELS; then
if [[ -n "$FINAL_MODEL" ]]; then
echo "==> Downloading Whisper STT models (small.en ~464 MB + ${FINAL_MODEL} ~1.6 GB)..."
python bootstrap_models.py --model small.en "$FINAL_MODEL"
echo " whisper_model_final=\"auto\" (new-install default) picks this up automatically."
echo " If data/config.json has whisper_model_final=\"\" (explicit off), set it to \"auto\""
echo " or \"${FINAL_MODEL}\" to enable the two-tier pass."
else
echo "==> Downloading Whisper STT model (small.en, ~464 MB)..."
python bootstrap_models.py --model small.en
fi
echo "==> Downloading Piper TTS voices..."
mkdir -p Voices
python - <<'PYEOF'
import os, shutil
from huggingface_hub import hf_hub_download
REPO = "rhasspy/piper-voices"
VOICES = [
"en/en_US/ryan/high/en_US-ryan-high.onnx",
"en/en_US/ryan/high/en_US-ryan-high.onnx.json",
"en/en_US/amy/medium/en_US-amy-medium.onnx",
"en/en_US/amy/medium/en_US-amy-medium.onnx.json",
"en/en_US/arctic/medium/en_US-arctic-medium.onnx",
"en/en_US/arctic/medium/en_US-arctic-medium.onnx.json",
"en/en_US/hfc_female/medium/en_US-hfc_female-medium.onnx",
"en/en_US/hfc_female/medium/en_US-hfc_female-medium.onnx.json",
"en/en_US/kathleen/low/en_US-kathleen-low.onnx",
"en/en_US/kathleen/low/en_US-kathleen-low.onnx.json",
"en/en_US/kristin/medium/en_US-kristin-medium.onnx",
"en/en_US/kristin/medium/en_US-kristin-medium.onnx.json",
"en/en_US/lessac/high/en_US-lessac-high.onnx",
"en/en_US/lessac/high/en_US-lessac-high.onnx.json",
"en/en_US/libritts/high/en_US-libritts-high.onnx",
"en/en_US/libritts/high/en_US-libritts-high.onnx.json",
]
for path in VOICES:
name = os.path.basename(path)
out = os.path.join("Voices", name)
if os.path.exists(out):
print(f" {name} already present, skipping.")
continue
print(f" Downloading {name}...")
cached = hf_hub_download(REPO, path)
shutil.copy2(os.path.realpath(cached), out)
print(f" {name} done.")
PYEOF
fi
# ── 6. Data directory ────────────────────────────────────────────────────────
mkdir -p data/journals
# Drop directory for installable 3rd-party plugins (loaded from /data/plugins).
mkdir -p data/plugins
if [ ! -f data/config.json ]; then
echo "==> Copying seed config..."
if [ -f data/config.json.example ]; then
cp data/config.json.example data/config.json
else
echo " (no data/config.json.example found — you must create data/config.json manually)"
echo " Minimum required fields: callsign, voice"
fi
fi
# ── 7. Validate ──────────────────────────────────────────────────────────────
echo ""
echo "==> Validating install..."
python -c "import sounddevice; print(' sounddevice OK')"
python -c "import faster_whisper; print(' faster-whisper OK')"
python -c "import piper; print(' piper-tts OK')"
python -c "import silero_vad; print(' silero-vad OK')"
python -c "import numpy; print(' numpy OK')"
python -c "import huggingface_hub; print(' huggingface_hub OK')"
echo ""
echo "Done. To start the server:"
echo " source .venv/bin/activate"
echo " uvicorn backend.server:app --host 0.0.0.0 --port 8765"
echo ""
echo "Edit data/config.json to set your callsign, audio devices, and voice."