HOWTO: build the Rudder desktop app on macOS or Windows, and what is not proven yet
This commit is contained in:
parent
ea151b9a56
commit
b7333ef970
1 changed files with 164 additions and 0 deletions
164
documentation/HOWTO-build-the-desktop-app.md
Normal file
164
documentation/HOWTO-build-the-desktop-app.md
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# HOWTO: build the Rudder desktop app (macOS / Windows)
|
||||
|
||||
Rudder (`plugin-designs/rudder-voice`) is voice-to-text that runs on your own computer: a web UI plus a
|
||||
local engine (`backend/rudder-engine`, Go) that drives NVIDIA's NeMo-Speech.cpp speech server. The
|
||||
desktop app is a Tauri window around the built web tree, with the engine started as a **sidecar**.
|
||||
|
||||
This page is written for an agent following it cold. **Read "What is proven" first**: most of the
|
||||
desktop path has never been run by anyone, and the steps say so where that is the case.
|
||||
|
||||
## What is proven, and what is not
|
||||
|
||||
| Piece | State |
|
||||
|---|---|
|
||||
| The web tree (`bun run build` → `public/dx-maps/`) | Proven. Every landing builds it. |
|
||||
| The generic Tauri shell (`deployment/src-tauri/`) | Exists. It opens the Research Gallery, builds only a Linux `.deb`, and has never been packaged on macOS or Windows. |
|
||||
| The engine on Linux (`bun run dev`, laptop mic) | Proven. |
|
||||
| The engine taking the **webview's** microphone (`RUDDER_AUDIO=browser`) | Proven on Linux: audio streamed over `/api/rudder/stream` came back as the full test sentence. |
|
||||
| The engine **compiling** for macOS (arm64, x86_64) and Windows (x86_64) | Proven by cross-compiling. It has **never been run** on either. |
|
||||
| The engine accepting a WebSocket from the Tauri webview (`tauri://localhost`, `http://tauri.localhost`) | Proven against a running engine; another site's origin is refused. |
|
||||
| NeMo-Speech.cpp runtime for macOS / Windows | Published by NVIDIA (release v0.1.0: `macos-aarch64-cpu`, `macos-aarch64-metal`, `macos-x86_64-cpu`, `windows-x86_64-cpu` / `-cuda` / `-vulkan`). **Never run here.** |
|
||||
| Rudder as a sidecar, first-run model download, installer | **Not built.** Steps 5–8 below are the work to do. |
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
Both platforms:
|
||||
|
||||
- **Bun** (the repo's package manager and script runner): https://bun.sh
|
||||
- **Go 1.22 or newer** (the engine).
|
||||
- **Rust** (stable) via https://rustup.rs, then the Tauri CLI, which the repo already pins as a dev
|
||||
dependency (`@tauri-apps/cli` 2.x, run through `bun run tauri:build`).
|
||||
- About 2 GB of free disk space (the speech model is 742 MB) and 2 GB of free RAM while it runs.
|
||||
|
||||
macOS:
|
||||
|
||||
- Xcode Command Line Tools: `xcode-select --install`.
|
||||
|
||||
Windows:
|
||||
|
||||
- Microsoft C++ Build Tools ("Desktop development with C++").
|
||||
- WebView2 runtime (preinstalled on Windows 11).
|
||||
|
||||
Tauri's own prerequisite list is the reference if anything above is out of date:
|
||||
https://v2.tauri.app/start/prerequisites/
|
||||
|
||||
## 2. Get the repo and its packages
|
||||
|
||||
```bash
|
||||
git clone <your team's repo URL> dx-maps
|
||||
cd dx-maps
|
||||
bun install
|
||||
```
|
||||
|
||||
## 3. Build the web tree
|
||||
|
||||
```bash
|
||||
bun run build
|
||||
```
|
||||
|
||||
This writes `public/dx-maps/`, the tree every deployment serves, including
|
||||
`public/dx-maps/rudder-voice/`. The Tauri config points at that folder (`frontendDist`); it does **not**
|
||||
build it for you (`beforeBuildCommand` is deliberately empty; see `deployment/src-tauri/README.md`).
|
||||
**Build first, then package.**
|
||||
|
||||
## 4. Build the engine for this machine
|
||||
|
||||
Tauri expects a sidecar binary named with the target triple:
|
||||
|
||||
```bash
|
||||
# macOS, Apple Silicon
|
||||
cd backend/rudder-engine && go build -o ../../deployment/src-tauri/binaries/rudder-engine-aarch64-apple-darwin . && cd ../..
|
||||
# macOS, Intel
|
||||
cd backend/rudder-engine && go build -o ../../deployment/src-tauri/binaries/rudder-engine-x86_64-apple-darwin . && cd ../..
|
||||
# Windows (PowerShell)
|
||||
cd backend/rudder-engine; go build -o ..\..\deployment\src-tauri\binaries\rudder-engine-x86_64-pc-windows-msvc.exe .; cd ..\..
|
||||
```
|
||||
|
||||
`rustc -Vv` prints the exact triple (`host:` line) if unsure.
|
||||
|
||||
## 5. Make the Tauri shell start the engine (NOT BUILT: this is the work)
|
||||
|
||||
1. **Declare the sidecar** in `deployment/src-tauri/tauri.conf.json`:
|
||||
`"bundle": { "externalBin": ["binaries/rudder-engine"], "targets": ["dmg"] }` on macOS, or
|
||||
`["nsis"]` (or `["msi"]`) on Windows. Keep the file schema-pure: **no `//` comment keys**, Tauri
|
||||
rejects unknown fields. Run `bun run check:tauri` after editing it.
|
||||
2. **Add the shell plugin** (`tauri-plugin-shell`) to `deployment/src-tauri/Cargo.toml` and register it
|
||||
in `src/main.rs`, then spawn the sidecar at startup with these environment variables:
|
||||
- `RUDDER_AUDIO=browser`: the engine takes the **webview's** microphone. Its own recorders
|
||||
(`parec` / `pw-record` / `arecord`) exist only on Linux, so on macOS and Windows this is required.
|
||||
- `RUDDER_HOME=<the app's data directory>` (Tauri's `app_data_dir()`): where the runtime and model live.
|
||||
- `RUDDER_PORT=5193` (the default) or a free port you pass on to the page (step 6).
|
||||
Kill the sidecar when the window closes. On macOS and Windows the engine cannot ask the OS to kill
|
||||
its own speech server if the engine crashes (Linux-only feature), so the shell should own that.
|
||||
3. `src/main.rs` currently has no logic by design ("a window around the web tree"). Rudder is the first
|
||||
desktop plugin with a backend, so this is the first logic it gains; keep it to starting and
|
||||
stopping the sidecar.
|
||||
|
||||
## 6. Open Rudder, and tell it where the engine is (NOT BUILT)
|
||||
|
||||
The window opens `doxa-maps-spa/doxa-maps-spa/index.html` today. For a Rudder app, open Rudder's own
|
||||
page, `rudder-voice/rudder-voice/index.html`, and give the element the engine's **absolute** address:
|
||||
|
||||
```
|
||||
profile-config = {"apiBase": "http://127.0.0.1:5193/api/rudder"}
|
||||
```
|
||||
|
||||
A relative `/api/rudder` would resolve against `tauri://localhost` and reach nothing. How the page
|
||||
receives that config (a small wrapper page, a query parameter, or the shell injecting it) is not
|
||||
decided and not built; pick the smallest option and say which in your report. The engine already
|
||||
answers CORS for the Tauri origins and accepts their WebSocket.
|
||||
|
||||
## 7. The speech runtime and model on first run (NOT BUILT)
|
||||
|
||||
`backend/rudder-engine/setup-runtime.sh` is the reference: it pins the runtime (NeMo-Speech.cpp
|
||||
**0.1.0**) and the model (`nemotron-3.5-asr-streaming-0.6b.q8_0.gguf`, Hugging Face revision
|
||||
`ea30d66debe3`, ~742 MB) by SHA-256, and refuses a mismatch. It is **bash and Linux x86_64 only**, so on
|
||||
macOS and Windows the app must do the same on first run:
|
||||
|
||||
- Download the runtime for this platform from
|
||||
`https://github.com/NVIDIA/NeMo-Speech.cpp/releases/tag/v0.1.0`. Each asset has a published
|
||||
`.sha256` next to it; check it. On Apple Silicon, the **`macos-aarch64-metal`** build uses the GPU
|
||||
and should transcribe far faster than the CPU builds (unmeasured). On a server, the CPU build ran
|
||||
slower than real time.
|
||||
- Download the model from the URL and SHA-256 in `setup-runtime.sh`. Verify before use.
|
||||
- Put them under `RUDDER_HOME`: `bin/nemo-speech-0.1.0-<os>-<arch>-cpu/bin/nemo-speech[.exe]` and
|
||||
`models/<model file>`. The engine derives that runtime path for its own platform
|
||||
(`<os>` = `macos` / `windows`, `<arch>` = `aarch64` / `x86_64`). **Unverified:** the layout inside the
|
||||
macOS and Windows archives. If it differs, or you use the Metal build, set `RUDDER_NEMO_BIN` to the
|
||||
real path of the `nemo-speech` binary.
|
||||
- Show progress: the first start downloads ~750 MB and warms the model (~20 s on a laptop CPU).
|
||||
|
||||
## 8. Package
|
||||
|
||||
```bash
|
||||
bun run tauri:build
|
||||
```
|
||||
|
||||
Run it from the repo root. If the CLI cannot find the config, run `cargo tauri build` inside
|
||||
`deployment/src-tauri/` (untested either way on macOS/Windows).
|
||||
|
||||
The installer lands under `deployment/src-tauri/target/release/bundle/`: `dmg/` on macOS, `nsis/` or
|
||||
`msi/` on Windows.
|
||||
|
||||
- **macOS:** the webview needs `NSMicrophoneUsageDescription` in the app's `Info.plist` (Tauri: an
|
||||
`Info.plist` file next to `tauri.conf.json`), or the microphone request is refused silently. An
|
||||
unsigned app opens with right-click → Open the first time. Signing and notarising are only needed
|
||||
to give it to others.
|
||||
- **Windows:** WebView2 asks for microphone permission on first use.
|
||||
|
||||
## 9. Check it works
|
||||
|
||||
1. Launch the app. Rudder's status reads "Loading speech model…" and then **Ready**.
|
||||
2. Press **Record**, speak, and watch the words stream into the box. Press **Stop**: the last words
|
||||
still arrive.
|
||||
3. `http://127.0.0.1:5193/api/rudder/status` in a browser on the same machine shows
|
||||
`"engine":"ready"` and `"audio":"browser"`.
|
||||
|
||||
## Known gaps (untested; report what you find)
|
||||
|
||||
- Nothing in steps 5–8 has been run on macOS or Windows.
|
||||
- The macOS/Windows runtime archive layout, and whether the engine's derived path matches it.
|
||||
- The first-run download, including resuming an interrupted 742 MB download.
|
||||
- Mapbox basemaps in the Research Gallery need the token host to allow the Tauri origin
|
||||
(`deployment/src-tauri/README.md`). Rudder itself needs no token.
|
||||
- If the engine crashes, its speech server may keep running (and holding ~1 GB) until the app quits.
|
||||
Loading…
Reference in a new issue