129 lines
7.2 KiB
Markdown
129 lines
7.2 KiB
Markdown
# 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.** |
|
|
| `bun run desktop:build rudder-voice` on **Linux** | Proven: produced `Rudder_0.1.0_amd64.deb` (8.8 MB) holding the app and the `rudder-engine` sidecar side by side. The app has **not been launched** from it yet (no display on the build box). |
|
|
| The shell starting and stopping the engine sidecar | Built (`deployment/src-tauri/src/main.rs`), compiled into that installer; not yet run. |
|
|
| First-run model download | **Not built.** Run `setup-runtime.sh` into the app's data folder by hand (step 7). |
|
|
|
|
## 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. No web build needed
|
|
|
|
`desktop:build` builds the one plugin it packages; `bun run build` (the web tree) is not a prerequisite.
|
|
|
|
## 4. Build the app: one command
|
|
|
|
```bash
|
|
bun run desktop:build rudder-voice
|
|
```
|
|
|
|
It packages ONE plugin whose `<profile>.meta.json` `"targets"` include `desktop` (see
|
|
`skills/plugin-designer/references/targets.md`), and nothing in `public/` or the committed tree changes:
|
|
|
|
1. the plugin is built into `.desktop/rudder-voice/`, with a one-element page that gives it the engine's
|
|
address (`apiBase: http://127.0.0.1:5193/api/rudder`);
|
|
2. its `"backend"` (`backend/rudder-engine`) is built for this machine as
|
|
`deployment/src-tauri/binaries/rudder-engine-<target triple>` (Tauri's sidecar naming);
|
|
3. `tauri build` runs with a `--config` override (the window opens that page, the app is named from the
|
|
meta label, the engine is bundled); `tauri.conf.json` is not edited.
|
|
|
|
The first run compiles Tauri's dependencies (several minutes, about 2 GB under
|
|
`deployment/src-tauri/target/`); later runs reuse it.
|
|
|
|
The shell (`deployment/src-tauri/src/main.rs`) starts the bundled `rudder-engine` with
|
|
`RUDDER_AUDIO=browser` (the webview captures the mic; the engine's own recorders are Linux-only) and
|
|
`RUDDER_HOME=<the app's data folder>/rudder`, and stops it when the app quits. The engine accepts the
|
|
webview's origins (`tauri://localhost`, `http://tauri.localhost`).
|
|
|
|
## 5. The speech runtime and model (first run, still by hand)
|
|
|
|
`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).
|
|
|
|
## 6. Where the installer lands
|
|
|
|
`desktop:build` prints the path. 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.
|
|
|
|
## 7. 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)
|
|
|
|
- `desktop:build` has run on Linux only; the app it produced has not been launched yet. Nothing has 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.
|