Elliot Seeds

Note · Smart Home

Giving an Echo Dot a new brain

Ditching a Gemini-lobotomised Google Home for a rooted Echo Dot running EchoLocal, Home Assistant, local Parakeet speech-to-text, Piper TTS, and fast Cerebras MCP tools.

Abstract editorial line artwork for “Giving an Echo Dot a new brain”. Decorative cover, no text.

Google’s recent push forcing Gemini onto Google Home speakers somehow made them dumber than a bag of rocks at the two things I actually ask a smart speaker to do every day: set a timer and add something to my shopping list.

I figured I could build something better, keep every stage of the pipeline under my own control, and wire it directly into my own tools. Rather than cobbling together a custom microphone array, I took a second-generation Echo Dot (good mics, physical volume buttons, and an LED ring you can see across the room), rooted it with EchoLocal, and replaced Amazon’s software with a lightweight Go daemon that speaks the native ESPHome API to Home Assistant.

The puck stays in the room doing on-device wake-word detection and rendering native kitchen-timer countdowns on its LED ring, while my home server handles speech recognition, tool calls and voice replies.

The four-stage voice pipeline: a rooted Echo Dot running EchoLocal, local Parakeet speech-to-text and Piper text-to-speech over Wyoming, Home Assistant local intents paired with Cerebras inference, and MCP tools for EV charging, daily budget, shopping list and multi-room music.

Replacing Whisper with Parakeet for local speech-to-text

A voice assistant feels broken if it pauses for two seconds before doing anything. I started with faster-whisper on my server’s CPU, but Whisper pads every audio clip to a fixed 30-second encoder window, so even a two-word command took 1.4 to 2.2 seconds to transcribe.

Switching the Wyoming speech-to-text container to NVIDIA Parakeet TDT 0.6B (onnx-asr) cut transcription time to 0.15 to 0.30 seconds on the same CPU, with better accuracy on British English.

For replies, text-to-speech runs locally on Piper (en_GB-alba-medium). Because LLM responses often include raw numbers like £17.50 that sound clumsy when read character by character, I wrapped Piper in a small streaming speech normaliser. It rewrites currency and clock times chunk by chunk without breaking sentence-by-sentence audio streaming, so the Echo starts speaking as soon as the first sentence is ready.

Local intents first, Cerebras + MCP for everything else

Home Assistant checks local intents before touching an LLM. Routine commands like setting a timer, turning lights off or changing volume resolve in 0.00 seconds on the box, and native timers drive the Echo Dot’s LED countdown and local alarm directly.

When a request does need an LLM, waiting on a slow cloud model ruins the turn. I pointed Home Assistant’s conversation agent at Cerebras for sub-second inference and connected it to the MCP servers and scripts I’d already built for my other projects:

  • Shopping list: telling it to add something to the shopping list puts it straight into Google Keep, alongside the weekly staples predicted from my receipts.
  • EV charger watch and car telemetry: I can ask it to watch a busy street charger and alert me when it frees up, or check where I parked, what my last trip cost, and how much battery is left.
  • Daily budget: asking what I can spend today queries my Monzo safe-spend API and reads back the allowance.
  • Multi-room music: a custom Lyrion MCP server fuzzy-matches tracks, albums, playlists or genres and starts playback on the right room’s Squeezebox player.

Two room-level annoyances we had to fix

Running a voice assistant in an actual room exposed two hardware problems that had nothing to do with the LLM.

First, if my office Mac was playing music, the Echo struggled to hear me after the wake word. We ran a lightweight Go MQTT daemon (mac2mqtt) on the Mac and wired a Home Assistant automation to the Echo satellite’s state: the instant the Dot wakes up to listen, the Mac ducks its volume to 50% (unless it’s already quieter), waits until the voice turn and any follow-up finish, and restores the original level.

Second, the wake word initially fired mid-conversation when nobody had said “Alexa”. Reading the device’s inference logs showed that real wake words hit a probability peak of 1.00, while false triggers from room chatter sat between 0.85 and 0.88. Raising the wake-word sensitivity threshold from 0.74 to 0.90 in Home Assistant eliminated the phantom wakes overnight.

All notes · Elliot Seeds