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>
116 lines
3.5 KiB
Markdown
116 lines
3.5 KiB
Markdown
# Letting people off-site watch
|
|
|
|
**Optional.** Everything works on the building's WiFi without any of this. Read
|
|
on only if you want people on cell data, or watching from home, to follow along.
|
|
|
|
Because each campus runs its own copy, this is a per-campus decision — you can
|
|
publish one campus and not another.
|
|
|
|
---
|
|
|
|
## The easy way: Cloudflare Tunnel
|
|
|
|
Free, needs no port forwarding, no firewall changes, no certificate, and no
|
|
static IP. It runs on the same Mac as the app.
|
|
|
|
1. **Install cloudflared**
|
|
|
|
```bash
|
|
brew install cloudflared
|
|
```
|
|
|
|
No Homebrew on that Mac? Download the `cloudflared-darwin-arm64.tgz` binary
|
|
from Cloudflare's releases page and drop it in `/usr/local/bin`.
|
|
|
|
2. **Log in and create the tunnel**
|
|
|
|
```bash
|
|
cloudflared tunnel login
|
|
cloudflared tunnel create translate-main
|
|
```
|
|
|
|
3. **Point a hostname at the app**
|
|
|
|
```bash
|
|
cloudflared tunnel route dns translate-main translate.watersmedia.org
|
|
```
|
|
|
|
4. **Run it**
|
|
|
|
```bash
|
|
cloudflared tunnel run --url http://127.0.0.1:3100 translate-main
|
|
```
|
|
|
|
To keep it running after a reboot, `sudo cloudflared service install`.
|
|
|
|
5. **Tell the app its public name**
|
|
|
|
Operator page → **Public address** → `https://translate.watersmedia.org` →
|
|
Save. That is what the QR code encodes, so it must be the public name or the
|
|
code only works for people already on your WiFi.
|
|
|
|
WebSockets pass through Cloudflare tunnels with nothing extra to configure,
|
|
which is the main reason this is the lower-risk option.
|
|
|
|
For a second campus, repeat with its own name — `translate-north`,
|
|
`north.translate.watersmedia.org`.
|
|
|
|
---
|
|
|
|
## The other way: your existing nginx proxy
|
|
|
|
You already run a reverse proxy at `10.1.1.4` fronting `check.watersmedia.org`,
|
|
with split-horizon DNS. It can front this too, though it means the traffic goes
|
|
through the NAS network to reach the booth Mac.
|
|
|
|
Add a DNS record for `translate.watersmedia.org` — public to your WAN address,
|
|
internal to `10.1.1.4` — and a server block. Copy the one that already serves
|
|
the checklist app, change the name, and point it at the **booth Mac**, not the
|
|
NAS:
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name translate.watersmedia.org;
|
|
|
|
ssl_certificate /path/to/fullchain.pem;
|
|
ssl_certificate_key /path/to/privkey.pem;
|
|
|
|
location / {
|
|
proxy_pass http://10.6.3.222:3100; # the booth Mac
|
|
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
|
|
# ---- required: captions ride a WebSocket ----
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# A sermon is long and mostly silent between sentences. Without this the
|
|
# proxy closes the caption socket after 60s of quiet and every phone in
|
|
# the room reconnects at once.
|
|
proxy_read_timeout 3600s;
|
|
proxy_send_timeout 3600s;
|
|
}
|
|
}
|
|
```
|
|
|
|
This has one real drawback the tunnel does not: the booth Mac needs a fixed
|
|
address on the network, or the proxy breaks the next time DHCP moves it.
|
|
|
|
---
|
|
|
|
## Checking it worked
|
|
|
|
```bash
|
|
curl -s https://translate.watersmedia.org/healthz
|
|
```
|
|
|
|
Should return `{"ok":true,…}`. Then open the page on a phone **with WiFi turned
|
|
off** — that is the real test. If the page loads but captions never appear, the
|
|
WebSocket headers are missing.
|