Local-first voice bridge for Arbiter: ESP32 (or any client) speaks PCM in, Intercom runs whisper.cpp STT + Kokoro TTS, and Arbiter stays text + SSE in the middle.
ESP32 --HTTP PTT PCM--> Intercom --text/SSE--> arbiter --api
ESP32 <--chunked PCM--- Intercom <--text------/
Colocate Intercom on the same host as arbiter --api (default http://127.0.0.1:8080). Device tokens never see the Arbiter bearer.
The default agent is Arthur — a British voice assistant with full Arbiter tool access (config/arthur.agent.json).
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -jRequires C++20, CMake 3.20+, SQLite3, Threads. Fetches cpp-httplib and nlohmann/json.
cp config/intercom.example.json intercom.json
# set arbiter_token, paths to whisper-cli + model, kokoro binary + voice
./build/intercom --config intercom.jsonInstall speech tools separately (not vendored):
- whisper.cpp →
whisper-cli+ggml-base.en.bin - Kokoro →
kokoro-tts+ ONNX model and voices bundle
Fast-path (skips Arbiter):
curl -N -H "Authorization: Bearer dev-device-secret-change-me" \
-H "X-Device-Id: speaker-1" \
-H "Content-Type: application/json" \
-d '{"text":"what time is it"}' \
--output reply.pcm \
http://127.0.0.1:8090/v1/utterance/textPlay: ffplay -f s16le -ar 16000 -ac 1 reply.pcm
PCM utterance: see docs/api.md and docs/device.md.
Apache-2.0