github wilbowes/EchoMuse v2.12.0
EchoMuse v2.12.0

4 hours ago

First device firmware since v2.11.0 (2026-08-09). Two changes need a moment of
your attention — the volume range and on-device wake word — and both are below.

Changing a wake word no longer kills the device

With on-device scoring running, changing a device's wake word crashed the
firmware. It restarted in about six seconds and worked afterwards, so it
mostly looked like a brief hiccup; the log line was a panic.

The fix for that then exposed a second fault, and both are needed here: with
the crash gone, the device stopped listening entirely after a wake word change
and stayed that way until the next voice turn — which could not happen,
because the wake word was dead. The crash had been accidentally repairing it
by restarting the process.

If you run owwOnDevice=shadow or on, this is the release you want.

⚠️ Volume above roughly three-quarters was distorting

The physical volume buttons could drive the codec's digital gain past the
point where it can only clip — measured at 65% distortion three presses above
the midpoint and 89% at maximum, with the output no longer getting any louder.
Stock Alexa never writes that control at all. This is the substance of every
report that EchoMuse sounded worse than stock when turned up. Found and
measured by @kdkavanagh.

The controller half shipped in 2.20.0; this completes it. The top of the
range is quieter than it was
, because what used to be above it was a square
wave. If you regularly ran a device near maximum you will hear the difference:
cleaner, and not as loud. The buttons now step about 4dB per press across the
audible range instead of spending presses near the bottom where nothing is
audible — silencing a device is the mute button's job.

On-device wake word can now trigger turns

owwOnDevice=on has existed in the controller but was greyed out for
everyone, because no released firmware announced that it could act on its own
detections. It can now. The device scores locally and starts the turn itself;
the controller keeps scoring alongside it so you can still see whether the two
agree.

This costs roughly 38% of one core on top of the mic pipeline, so enable it on
one device at a time. It needs the wake word assets installed — the controller
does that for you when you turn it on.

Also

  • Six shipped defaults corrected against measured field data (#144), so a
    fresh device starts closer to what the fleet actually runs.
  • Ambient light reports why there is no sensor rather than staying silent,
    which is what a support bundle needs to tell two different devices apart.
  • The build toolchain is now pinned by digest rather than a floating tag, so
    two releases cannot silently be compiled by different toolchains. This is
    the first release built through the pin; it was verified identical to what
    the floating tag resolved to.

Updating

Update one device first and let it come back before doing the rest. The A/B
slot system rolls back on its own if the new binary fails to start three
times, but watching one device is still cheaper than watching all of them.

What's Changed

  • docs: stop media does not stick, and that is what makes it safe by @wilbowes in #118
  • ci: dependency auditing, image scanning and an SBOM by @wilbowes in #125
  • docs: the ALS is second-sourced, and the bus listing never said otherwise by @wilbowes in #123
  • fix: a failed OTA no longer empties the rollback slot, and says what failed by @wilbowes in #124
  • security: zeroconf 0.148.0 -> 0.149.17 (three mDNS DoS advisories) by @wilbowes in #126
  • fix: onnxruntime-gpu 1.20.1 no longer exists on PyPI by @wilbowes in #131
  • docs: journal the OTA fixes and the supply-chain scanning work by @wilbowes in #132
  • Let the device trigger voice turns (owwOnDevice=on) by @wilbowes in #134
  • Pin the compiler base image by digest by @wilbowes in #135
  • build: drop esbuild from the runtime image by @bboe in #136
  • Measure the no-speech window from the first audio frame by @wilbowes in #142
  • docs: the RTT excursions were packet loss and TCP backoff all along by @wilbowes in #143
  • ci: trivy-action tags carry a v, so the release job never started by @wilbowes in #145
  • ci: trivy-action v0.28.0 is unusable, and pins by SHA now by @wilbowes in #146
  • ci: scan the digest that was pushed, and never fail a shipped release by @wilbowes in #148
  • docs: the jack fault is in no register, and rms cannot see DC by @wilbowes in #149
  • docs: a stock Dot drives the same speaker fine, so the jack fault is ours by @wilbowes in #151
  • docs: h2w reads the same on stock, so detection is not the difference by @wilbowes in #152
  • Correct six shipped defaults against measured field data by @wilbowes in #155
  • Ignore SQLite databases and untrack the committed one by @wilbowes in #156
  • Document that there is no telemetry, and name the one outbound connection by @wilbowes in #158
  • Package the controller as a Home Assistant add-on by @natecj in #122
  • Pin the add-on to 2.19.0, and fail the release when the pin is wrong by @wilbowes in #160
  • Actually add the SQLite ignore rules #156 was meant to add by @wilbowes in #161
  • Never advertise a guessed address: detect SERVER_IP, or refuse by @wilbowes in #169
  • Docs: the add-on, the corrected defaults, and the day in the journal by @wilbowes in #165
  • Add-on: Early Access release channel by @wilbowes in #172
  • CI: let govulncheck build itself on a newer toolchain by @wilbowes in #174
  • docs: catch up on the add-on's first install by @wilbowes in #175
  • Expose debug logging as an add-on option by @wilbowes in #179
  • Send the wake word phrase Home Assistant asks for by @wilbowes in #180
  • Release the turn when Home Assistant ends a run it never started by @wilbowes in #182
  • Hold the ring briefly when a turn ends instantly by @wilbowes in #183
  • Stop repeating the device label in every entity name by @wilbowes in #184
  • Cap volume at the codec's unity gain to stop the DAC clipping by @kdkavanagh in #177
  • dashboard: make Toggle honour disabled, not just style it by @kdkavanagh in #178
  • docs: catch up on the setup-dialog day by @wilbowes in #185
  • Deliver frames to the scorer that is actually installed by @wilbowes in #189
  • Focus the console when the tab opens by @wilbowes in #188
  • Stop the asset push shadowing its own accumulator by @wilbowes in #190
  • Stop a wake word change from killing the device by @wilbowes in #187
  • Serialise pipeline runs across a barge-in by @wilbowes in #194
  • Send AnnounceFinished when the announcement actually finishes by @wilbowes in #196
  • Fix two announcement faults found on hardware by @wilbowes in #199
  • Show Speaking on the dashboard by @wilbowes in #201
  • Cache downloaded firmware instead of re-fetching it per device by @wilbowes in #200
  • Never leave a device deaf because it lacks the model it was told to use by @wilbowes in #198
  • Align the Speaking tile to the device, not to the socket by @wilbowes in #202
  • Install a wake word model before switching the device onto it by @wilbowes in #204
  • Build the controller image on main, promote it on the tag by @wilbowes in #164

New Contributors

Full Changelog: v2.11.0...v2.12.0

Don't miss a new EchoMuse release

NewReleases is sending notifications on new releases.