Church Translate, as it runs at the campuses
Live sermon translation into 100+ languages, running entirely on one Mac per campus: audio in, voice detection, Whisper on the GPU, NLLB-200 in its own process, and a built-in web server the congregation reads from on their phones. No audio leaves the building. This is the source only. What used to sit beside it — 14 GB of speech and translation models, 8 GB of voice bundles, 6 GB of natural voices, the Electron caches, and the app data holding the operator PIN and every service transcript — is machine state and downloaded assets, and stays in the NAS backup where it belongs. The vendored node, cloudflared and Windows ffmpeg binaries are out too (533 MB, re-fetched for packaging); the browser-side runtime beside them is kept, so a checkout still serves the congregation page. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+70
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# One-time, per-Mac installer for the free local voices
|
||||
# (Kokoro and Qwen3-TTS, both via mlx-audio).
|
||||
# Bought once for $0: Apache-2.0 weights, runs entirely on this Mac.
|
||||
# The venv CANNOT be copied between machines — run this on each Mac.
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$HOME/Library/Application Support/Church Translate Local Voices"
|
||||
VENV="$DIR/venv"
|
||||
PORT="${1:-43111}"
|
||||
|
||||
echo "== Church Translate — local voices installer =="
|
||||
# macOS ships Python 3.9, which mlx-audio cannot use — so FIND a 3.10+ python
|
||||
# rather than assuming the one on PATH. Checked in order: uv-managed (this Mac
|
||||
# has them), Homebrew, versioned names on PATH, then plain python3.
|
||||
PY=""
|
||||
pick_py() {
|
||||
for c in "$@"; do
|
||||
[ -x "$c" ] || continue
|
||||
"$c" -c 'import sys; sys.exit(0 if sys.version_info >= (3,10) else 1)' 2>/dev/null && { PY="$c"; return 0; }
|
||||
done
|
||||
return 1
|
||||
}
|
||||
pick_py $(ls -d "$HOME/.local/share/uv/python/"*/bin/python3 2>/dev/null | sort -r) \
|
||||
/opt/homebrew/bin/python3.13 /opt/homebrew/bin/python3.12 /opt/homebrew/bin/python3.11 \
|
||||
/opt/homebrew/bin/python3 /usr/local/bin/python3 \
|
||||
"$(command -v python3.13 || true)" "$(command -v python3.12 || true)" \
|
||||
"$(command -v python3.11 || true)" "$(command -v python3 || true)" || {
|
||||
echo "No Python 3.10+ found. Install one, then re-run:"
|
||||
echo " brew install python@3.12 # or: xcode-select --install"
|
||||
exit 1
|
||||
}
|
||||
echo "using python: $PY ($("$PY" --version 2>&1))"
|
||||
|
||||
mkdir -p "$DIR"
|
||||
[ -d "$VENV" ] || "$PY" -m venv "$VENV"
|
||||
"$VENV/bin/pip" install --upgrade pip >/dev/null
|
||||
|
||||
# The exact dependency set, learned from consecutive boot failures:
|
||||
# mlx_audio.server needs uvicorn/fastapi/python-multipart; webrtcvad still
|
||||
# imports pkg_resources, which setuptools>=81 removed.
|
||||
"$VENV/bin/pip" install 'setuptools<81' mlx-audio uvicorn fastapi python-multipart webrtcvad
|
||||
|
||||
# Kokoro's text processing. mlx-audio ships the model code but not these, and
|
||||
# without them synthesis fails at the last step with an ImportError for
|
||||
# 'misaki' — after the 330MB model has already downloaded. espeakng-loader
|
||||
# carries its own libespeak-ng, so no Homebrew and nothing system-wide.
|
||||
"$VENV/bin/pip" install misaki phonemizer-fork espeakng-loader
|
||||
|
||||
echo "== prefetching the model (one-time download, ~2GB) =="
|
||||
"$VENV/bin/python3" - <<'PY'
|
||||
from huggingface_hub import snapshot_download
|
||||
snapshot_download('mlx-community/Qwen3-TTS-12Hz-1.7B-CustomVoice-8bit')
|
||||
print('model cached')
|
||||
PY
|
||||
|
||||
echo "== self-test: boot the server and synthesize one sentence =="
|
||||
"$VENV/bin/python3" -m mlx_audio.server --host 127.0.0.1 --port "$PORT" &
|
||||
SRV=$!
|
||||
trap 'kill $SRV 2>/dev/null' EXIT
|
||||
for i in $(seq 1 30); do curl -s -o /dev/null "http://127.0.0.1:$PORT/v1/models" && break; sleep 1; done
|
||||
OUT="$DIR/selftest.wav"
|
||||
curl -s -X POST "http://127.0.0.1:$PORT/v1/audio/speech" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"model":"mlx-community/Qwen3-TTS-12Hz-1.7B-CustomVoice-8bit","voice":"aiden","input":"The Lord bless you and keep you.","lang_code":"english","response_format":"wav","max_tokens":300,"temperature":0.2}' \
|
||||
-o "$OUT"
|
||||
head -c 4 "$OUT" | grep -q RIFF && echo "SELF-TEST OK — $OUT ($(stat -f%z "$OUT") bytes)" || { echo "SELF-TEST FAILED"; exit 1; }
|
||||
kill $SRV 2>/dev/null; trap - EXIT
|
||||
echo
|
||||
echo "Done. In Church Translate: Operator pane → Premium voices → 'Local (this Mac — free)'."
|
||||
Reference in New Issue
Block a user