$ show OHF-Voice/linux-voice-assistant
This repository implements a Linux-based voice satellite for Home Assistant, acting as a local voice assistant that connects to Home Assistant via the ESPHome protocol (aioesphomeapi). The application runs as a Python asyncio service, handling wake word detection using TensorFlow Lite models (MicroWakeWord and OpenWakeWord), audio input via the soundcard library, audio output via libmpv, and optional WebRTC noise suppression/gain. It also provides a WebSocket-based Peripheral API (port 6055) that allows external hardware controllers (LED rings, buttons, HAT boards) to register entities and receive real-time state events. The system is deployed via Docker with docker-compose and includes example peripheral implementations for devices like the ReSpeaker HATs, Jabra Speak 410, and Satellite1 HAT. The architecture is modular, with separate modules for the ESPHome API server (api_server.py), core voice pipeline protocol (satellite.py), entity management (entity.py), wake word loading (wake_word.py), audio playback (player/libmpv.py), and peripheral integration (peripheral_api.py). The application is configured via environment variables and command-line arguments, with preferences persisted to a JSON file. The codebase includes unit tests for most modules, CI/CD workflows, and a Docker build pipeline. External dependencies include aioesphomeapi, websockets, soundcard, python-mpv, webrtc-noise-gain, pymicro-wakeword, pyopen-wakeword, and zeroconf. Key data flows: Microphone audio is captured, optionally processed by WebRTC for noise suppression and gain, then fed into wake word detection. Upon wake word detection, the voice pipeline sends audio to Home Assistant for speech recognition and intent handling. Responses (TTS, media) are received and played via MPV. The Peripheral API allows external hardware to send button events and receive state changes (e.g., listening, thinking, muted). The system supports multiple wake words, stop word detection, timers, and media playback with playlist support.
The LLM identified 5 files worth highlighting for reuse:
Defines an abstract AudioPlayer interface with methods play, pause, resume, stop, and a PlayerState enum (IDLE, LOADING, PLAYING, PAUSED, STOPPING, ERROR). This is a clean, reusable pattern for any audio playback system. It is fully decoupled from the rest of the codebase and can be extracted into a new project with minimal modification.
Implements WebRTCProcessor for real-time noise suppression and automatic gain control on 16-bit PCM audio frames. It wraps the webrtc-noise-gain library with a buffering mechanism and configurable gain/NS levels. The component is self-contained, handles frame buffering and processing, and can be reused in any audio pipeline requiring noise reduction.
Provides a WebSocket server (port 6055) that allows external hardware controllers to register entities (lights, buttons) and receive real-time state events from the voice assistant. The protocol uses a clean JSON schema with events (voice pipeline, timer, media, error) and commands (start_listening, mute, volume, timer, button events). This is a well-designed, reusable integration pattern for adding physical controls to any voice assistant.
Implements HomeAssistantZeroconf, a helper that registers an _esphomelib._tcp mDNS service with device properties (name, manufacturer, model, etc.). It uses the zeroconf library and is easily reusable for any project needing mDNS advertisement of a Home Assistant-compatible device.
Handles discovery and loading of wake word models from JSON configuration files and TFLite model files. Supports both MicroWakeWord and OpenWakeWord engines, multiple active wake words, sensitivity settings, and stop word detection. The module is modular, testable, and can be extracted for use in other voice assistant projects requiring local wake word detection.