Initial commit: Javis project

This commit is contained in:
Javis committed 2026-09-21 21:44:00 +02:00
commit 435c645f36
164 files changed
+35279

No files matched your search

+162
View File
@@ -0,0 +1,162 @@
# javis-slave on a Raspberry Pi
Turn a Raspberry Pi with a USB microphone and a speaker into a Javis satellite:
it detects the wake word locally, streams the utterance to the Javis master on
your LAN, and plays the spoken reply. No GPU, no models beyond the tiny
openWakeWord ONNX file.
## Hardware
| Part | Notes |
|------|-------|
| Raspberry Pi 3B+ / 4 / 5 / Zero 2 W | 64-bit Raspberry Pi OS (Bookworm or newer). Zero 2 W works headless; wake-word inference uses ~15 % of one core. |
| USB microphone or USB sound card + mic | Most USB mics only offer 44.1/48 kHz — the slave resamples to 16 kHz automatically. Conference-style mics (e.g. Jabra, Anker) give the best wake-word range. |
| Speaker | 3.5 mm jack, HDMI, USB DAC or an I²S HAT. |
| Optional: official 7" touch display | Use `setup-pi.sh --gui` for the same touch UI as the Surface build; brightness control works via `/sys/class/backlight`. |
## Install (5 minutes)
```bash
# On the Pi
git clone <your-repo> javis && cd javis/javis-slave # or scp the javis-slave folder
sudo ./setup-pi.sh # headless
# sudo ./setup-pi.sh --gui # with touch display
# add --with-vad for silero-vad end-pointing (pulls PyTorch, ~200 MB; RMS gate is used otherwise)
```
The script installs apt dependencies, creates `/opt/javis-slave/.venv`,
pre-downloads the wake-word models, grants the service user audio/backlight/power
permissions and installs a `systemd` unit (`javis-slave.service`, enabled but not
started).
## Configure & pair
1. **Pick audio devices**
```bash
cd /opt/javis-slave
export JAVIS_SLAVE_CONFIG_DIR=/opt/javis-slave/config
.venv/bin/python -m javis_slave --list-devices
```
Note the index of your mic (`max_input_channels > 0`) and speaker.
2. **Enable the API on the master** (`config.yaml`), then restart Javis:
```yaml
api:
enabled: true
host: 0.0.0.0
port: 8765
```
Open the **Devices** tab → *Generate pairing code*. The tab shows the
master's LAN address and the 6-digit code (valid 5 min, single use).
3. **Pair and test in the foreground**
```bash
.venv/bin/python -m javis_slave --headless \
--input-device 1 --output-device 0 \
--pair 192.168.1.10:8765 123456 --name Kueche
```
Say the wake word (default *hey jarvis*) — you should hear the ascending
two-tone chime, speak, and hear the reply. Device settings are persisted in
`$JAVIS_SLAVE_CONFIG_DIR/slave_config.json`. Stop with Ctrl+C.
4. **Run as a service**
```bash
sudo systemctl start javis-slave
journalctl -u javis-slave -f
```
Assign a room in the master's Devices tab (e.g. `Küche`); the slave picks it
up within a minute and every utterance is tagged with it for the LLM.
With `setup-pi.sh --gui` the system service stays disabled and the touch UI
autostarts in the desktop session instead (`~/.config/autostart/javis-slave.desktop`,
`--kiosk` = fullscreen, hidden cursor; Esc leaves fullscreen, F11 toggles).
Logs: `journalctl -u javis-slave` (service) and
`$JAVIS_SLAVE_CONFIG_DIR/logs/slave.log` (rotating, both modes).
## Audible feedback (no screen needed)
| Sound | Meaning |
|-------|---------|
| Two rising tones | Wake word heard — speak now |
| Two falling low tones | Something failed (master unreachable, mic error) |
| Spoken error phrase | The master received the request but its turn failed (STT/LLM); it sends its configured `agent.error_phrase` as speech |
## Remote control from the master
The slave runs a small HTTP control server on port 8766 (`/mcp/v1/...`) that
the [javis-slave-mcp](../javis-slave-mcp/README.md) server exposes as tools, so
you can say *"mach die Küche leiser"*. On Linux the endpoints map to:
| Endpoint | Backend |
|----------|---------|
| `/mcp/v1/volume/*` | `pactl` (PipeWire/Pulse) → falls back to `amixer` (ALSA) |
| `/mcp/v1/brightness/*` | `/sys/class/backlight/*/brightness` (udev rule from `setup-pi.sh`) |
| `/mcp/v1/power/*` | `systemctl suspend`, `shutdown` via a scoped sudoers entry |
| `/mcp/v1/mic/*`, `/status`, `/restart` | Engine mute / status / restart |
## CLI reference
```
javis-slave --headless service mode, no window
javis-slave --fullscreen | --kiosk GUI fullscreen / fullscreen + hidden cursor
javis-slave --pair HOST:PORT CODE --name N pair (works with and without --headless)
javis-slave --list-devices print sounddevice table
javis-slave --input-device N --output-device N --input-gain G --api-port P
persist settings and start
```
Environment: `JAVIS_SLAVE_CONFIG_DIR` overrides the config folder
(default `~/.javis-slave`).
## Troubleshooting
**No devices listed / "Error querying device"** — `sudo apt install libportaudio2`
and make sure the user is in the `audio` group (`groups`; log out/in after
`setup-pi.sh`).
**Mic opens at 48 kHz, wake word never fires** — normal; the log line
`mic started @ 48000Hz→16000Hz` confirms resampling is active. Raise
`--input-gain 2.0` if the level is low; check with `arecord -d 3 test.wav`.
Stereo-only USB cards are opened with both channels and mixed to mono.
**USB mic unplugged / stops delivering audio** — after ~2 minutes of silence
from the device the engine logs `reopening device` and re-opens it; if the
device is gone the engine start is retried every 10 s.
**"Master … not reachable"** — the master must have `api.enabled: true` and its
Windows firewall must allow inbound TCP 8765 (Javis is a Python process; allow
`python.exe` on private networks).
**Wake word too sensitive / not sensitive enough** — change
`wake_word.threshold` on the *master*; slaves pull it on the next config poll
(≤ 60 s).
**Reply is silent but text appears in the master's log** — the master's TTS has
no voice profile with reference clips; add one in the Voices tab. Playback
device problems show up as `speaker does not support … Hz` (auto-resampled) or
an ALSA error in `journalctl`.
**Service dies at boot** — USB audio may enumerate after the service starts;
`Restart=always` + `RestartSec=5` recover automatically. The engine also
retries every 10 s while the mic is unavailable.
**Pi Zero 2 W CPU load** — skip `--with-vad`; the RMS gate is much cheaper than
Silero on a single core. Keep only one wake-word model.
## Uninstall
```bash
sudo systemctl disable --now javis-slave
sudo rm /etc/systemd/system/javis-slave.service /etc/sudoers.d/javis-slave \
/etc/udev/rules.d/90-javis-backlight.rules
sudo rm -rf /opt/javis-slave
```