Skip to content

Skip wake word scoring while a pipeline/response is active - #404

Open
jbeta4711 wants to merge 3 commits into
OHF-Voice:mainfrom
jbeta4711:fix/skip-wakeword-scoring-during-response
Open

jbeta4711 wants to merge 3 commits into
OHF-Voice:mainfrom
jbeta4711:fix/skip-wakeword-scoring-during-response

Conversation

@jbeta4711

Copy link
Copy Markdown

Summary

  • Satellite.wakeup() already ignores wake word detections while self._pipeline_active is True (logged as "Ignoring wake word - pipeline already active"), but the wake word models keep running inference on every audio frame during that window regardless, including throughout TTS playback.
  • On hardware without working AEC, a satellite's own TTS output reliably scores as a near-certain match for its own wake word (residual echo picked up by the mic) - in real-world testing I saw probabilities of 0.9+ throughout entire responses, well above the configured threshold.
  • wakeup() correctly catches this today, but only after the fact. There's also a narrow window right after REFRACTORY_SECONDS elapses mid-response (before _pipeline_active clears) where a fresh detection depends entirely on that one guard.
  • This moves the check to the source: skip wake word scoring for the primary wake words while a pipeline/response is already active, matching the intent already documented in satellite.py:

    "When TTS is playing, keep _pipeline_active = True to block false wake word detections from speaker audio feedback."

  • Stop word detection is a separate code path and is unaffected - it still needs to run while a response is in progress.

Test plan

  • ./script/lint_black, ./script/lint_isort, ./script/lint_flake8 clean on the changed file (couldn't run the full ./script/tests suite locally - missing libmpv-dev system dependency in my sandbox, not something I could install there)
  • Deployed to 5 real satellites (Raspberry Pi, ReSpeaker 2-Mic HAT) running microWakeWord, confirmed no probability-log lines for the primary wake words during active playback afterwards, containers stayed healthy
  • Would appreciate a maintainer/CI run of the full test suite given I couldn't run it myself

🤖 Filed with the help of Claude Code, reviewed and approved by me before submission.

Satellite.wakeup() already ignores detections while self._pipeline_active
is True ("Ignoring wake word - pipeline already active"), but the
underlying wake word models still run inference on every audio frame
during that window, including throughout TTS playback.

On hardware without working AEC, the device's own TTS output reliably
scores as a near-certain match for its own wake word (residual echo
picked up by the mic) - observed probabilities of 0.9+ throughout entire
responses in real-world testing. wakeup() catches this correctly today,
but only after the fact, and there's a narrow window right after
REFRACTORY_SECONDS elapses (mid-response, before _pipeline_active clears)
where a fresh detection depends entirely on that guard.

This skips wake word scoring for the primary wake words at the source
instead, matching the intent already documented in satellite.py:
"When TTS is playing, keep _pipeline_active = True to block false wake
word detections from speaker audio feedback." Stop word detection is
unaffected (separate code path, needed while a response is in progress).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants