diff --git a/package.json b/package.json index b3906629..44927c59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "imwald", - "version": "23.0.5", + "version": "23.0.6", "description": "Imwald — a user-friendly Nostr client focused on relay feed browsing, publications, and relay discovery", "private": true, "type": "module", diff --git a/scripts/download-piper-extra-voices.sh b/scripts/download-piper-extra-voices.sh index 6551fde1..f2b1e3e5 100644 --- a/scripts/download-piper-extra-voices.sh +++ b/scripts/download-piper-extra-voices.sh @@ -1,52 +1,6 @@ #!/usr/bin/env bash -# Download Piper ONNX voices from rhasspy/piper-voices (trinity read-aloud + extras). +# Download Piper ONNX voices — delegates to ensure-libretranslate-dirs.sh (single source of truth). # Usage: bash scripts/download-piper-extra-voices.sh [DEST_DIR] -# DEST_DIR defaults to repo/.local-piper-data (Wyoming --data-dir in docker-compose.dev.yml). -# Env: HF_BASE — override Hugging Face resolve base (default rhasspy/piper-voices/main). set -euo pipefail -_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" -if [[ "$(basename "$_SCRIPT_DIR")" == "scripts" ]]; then - ROOT="$(cd "$_SCRIPT_DIR/.." && pwd)" -else - ROOT="$_SCRIPT_DIR" -fi -DEST="${1:-${PIPER_DOWNLOAD_DIR:-$ROOT/.local-piper-data}}" -HF="${HF_BASE:-https://huggingface.co/rhasspy/piper-voices/resolve/main}" - -mkdir -p "$DEST" - -fetch_pair() { - local relpath="$1" - local base_name - base_name="$(basename "$relpath")" - local onnx="${DEST}/${base_name}.onnx" - local json="${DEST}/${base_name}.onnx.json" - if [[ -f "$onnx" && -f "$json" ]]; then - echo "Skip (exists): ${base_name}" - return 0 - fi - echo "Fetching ${base_name} ..." - curl -fsSL -o "$onnx" "${HF}/${relpath}.onnx" - curl -fsSL -o "$json" "${HF}/${relpath}.onnx.json" -} - -# --- Trinity UI locales (keep in sync with src/lib/trinity-languages.ts TRINITY_PIPER_VOICE) --- -fetch_pair "en/en_US/lessac/medium/en_US-lessac-medium" -fetch_pair "de/de_DE/thorsten/medium/de_DE-thorsten-medium" -fetch_pair "fr/fr_FR/siwis/medium/fr_FR-siwis-medium" -fetch_pair "es/es_ES/davefx/medium/es_ES-davefx-medium" -fetch_pair "ru/ru_RU/ruslan/medium/ru_RU-ruslan-medium" -fetch_pair "zh/zh_CN/huayan/medium/zh_CN-huayan-medium" -fetch_pair "pl/pl_PL/darkman/medium/pl_PL-darkman-medium" -fetch_pair "nl/nl_NL/mls/medium/nl_NL-mls-medium" -fetch_pair "cs/cs_CZ/jirka/medium/cs_CZ-jirka-medium" -fetch_pair "tr/tr_TR/dfki/medium/tr_TR-dfki-medium" - -# --- Read-aloud extras (EXTRA_READ_ALOUD_PIPER_VOICE + server voiceMap) --- -fetch_pair "ar/ar_JO/kareem/medium/ar_JO-kareem-medium" -fetch_pair "it/it_IT/paola/medium/it_IT-paola-medium" -fetch_pair "pt/pt_BR/cadu/medium/pt_BR-cadu-medium" - -# Japanese: no ja_* in rhasspy/piper-voices; app uses Chinese Piper for ja-related read-aloud. - -echo "Done. Piper files in ${DEST}. Restart piper-wyoming if it is already running." +__dir="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" +exec bash "$__dir/ensure-libretranslate-dirs.sh" --download-piper-only "$@" diff --git a/scripts/ensure-libretranslate-dirs.sh b/scripts/ensure-libretranslate-dirs.sh index 7db3479b..886591d4 100755 --- a/scripts/ensure-libretranslate-dirs.sh +++ b/scripts/ensure-libretranslate-dirs.sh @@ -1,22 +1,74 @@ #!/usr/bin/env bash # One-shot host prep for editor stack sidecars: # 1) LibreTranslate bind mount — dirs + ownership UID 1032 (official image user). -# 2) Piper ONNX voices — same set as scripts/download-piper-extra-voices.sh into: +# 2) Piper ONNX voices — trinity + read-aloud extras (rhasspy/piper-voices) into: # - ./.local-piper-data (dev compose bind mount), and # - Docker volume _piper-stack-data when it exists (docker-compose.prod.yml Wyoming /data). # -# Run: bash scripts/ensure-libretranslate-dirs.sh (or copy to repo root and ./ensure-libretranslate-dirs.sh) +# Piper download logic lives in this file so you can copy **only** this script to a server and run it +# from the repo root (still need curl, docker; full clone is easier: bash scripts/ensure-libretranslate-dirs.sh). +# +# Internal entry: bash ensure-libretranslate-dirs.sh --download-piper-only [DEST] +# (used by scripts/download-piper-extra-voices.sh — keep voice list in sync with trinity-languages.ts) # # Optional env: -# COMPOSE_PROJECT_NAME — Docker Compose project name (default: basename of repo dir), for volume jumble_piper-stack-data. -# SKIP_PIPER_VOICES=1 — only fix LibreTranslate permissions, do not download Piper (~hundreds of MB). +# COMPOSE_PROJECT_NAME — Docker Compose project name (default: basename of repo dir), for volume *_piper-stack-data. +# SKIP_PIPER_VOICES=1 — only fix LibreTranslate permissions, do not download Piper. +# HF_BASE — Hugging Face resolve base for Piper ONNX (default rhasspy/piper-voices/main). set -euo pipefail -_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" -if [[ "$(basename "$_SCRIPT_DIR")" == "scripts" ]]; then - ROOT="$(cd "$_SCRIPT_DIR/.." && pwd)" -else - ROOT="$_SCRIPT_DIR" + +_resolve_root() { + _SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" + if [[ "$(basename "$_SCRIPT_DIR")" == "scripts" ]]; then + ROOT="$(cd "$_SCRIPT_DIR/.." && pwd)" + else + ROOT="$_SCRIPT_DIR" + fi +} + +# Keep in sync with src/lib/trinity-languages.ts (TRINITY_PIPER_VOICE + EXTRA_READ_ALOUD_PIPER_VOICE) and server voiceMap. +download_piper_voices_to() { + local dest="${1:?destination directory}" + local hf="${HF_BASE:-https://huggingface.co/rhasspy/piper-voices/resolve/main}" + mkdir -p "$dest" + local relpath base_name onnx json + for relpath in \ + "en/en_US/lessac/medium/en_US-lessac-medium" \ + "de/de_DE/thorsten/medium/de_DE-thorsten-medium" \ + "fr/fr_FR/siwis/medium/fr_FR-siwis-medium" \ + "es/es_ES/davefx/medium/es_ES-davefx-medium" \ + "ru/ru_RU/ruslan/medium/ru_RU-ruslan-medium" \ + "zh/zh_CN/huayan/medium/zh_CN-huayan-medium" \ + "pl/pl_PL/darkman/medium/pl_PL-darkman-medium" \ + "nl/nl_NL/mls/medium/nl_NL-mls-medium" \ + "cs/cs_CZ/jirka/medium/cs_CZ-jirka-medium" \ + "tr/tr_TR/dfki/medium/tr_TR-dfki-medium" \ + "ar/ar_JO/kareem/medium/ar_JO-kareem-medium" \ + "it/it_IT/paola/medium/it_IT-paola-medium" \ + "pt/pt_BR/cadu/medium/pt_BR-cadu-medium" + do + base_name="$(basename "$relpath")" + onnx="${dest}/${base_name}.onnx" + json="${dest}/${base_name}.onnx.json" + if [[ -f "$onnx" && -f "$json" ]]; then + echo "Skip (exists): ${base_name}" + continue + fi + echo "Fetching ${base_name} …" + curl -fsSL -o "$onnx" "${hf}/${relpath}.onnx" + curl -fsSL -o "$json" "${hf}/${relpath}.onnx.json" + done + echo "Piper ONNX done → ${dest}" +} + +if [[ "${1:-}" == "--download-piper-only" ]]; then + shift + _resolve_root + download_piper_voices_to "${1:-${PIPER_DOWNLOAD_DIR:-$ROOT/.local-piper-data}}" + exit 0 fi + +_resolve_root PROJECT="${COMPOSE_PROJECT_NAME:-$(basename "$ROOT")}" PIPER_VOL="${PROJECT}_piper-stack-data" @@ -32,7 +84,7 @@ if [[ "${SKIP_PIPER_VOICES:-}" == "1" ]]; then fi echo "[ensure] Piper voices (bind mount .local-piper-data) …" -bash "$ROOT/scripts/download-piper-extra-voices.sh" "$ROOT/.local-piper-data" +download_piper_voices_to "$ROOT/.local-piper-data" if docker volume inspect "$PIPER_VOL" &>/dev/null; then echo "[ensure] Copying Piper voices into Docker volume ${PIPER_VOL} …"