Files
javis/javis-slave/RASPBERRY_PI.md
T
2026-09-21 21:44:00 +02:00

6.4 KiB

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)

# 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

    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:

    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

    .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

    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 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

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