Skip to content

Conversation

@JarbasAl
Copy link
Member

@JarbasAl JarbasAl commented Nov 4, 2025

allow multiple plugins to perform checks on wake word audio, and discard the detection

this can be used to reduce false negatives, either with something like VAD, or with speaker verification.

config example

"listener": {
  "ww_verifiers": {
     "ovos-ww-verifier-silero": {"threshold": 0.1}
  },
  "vad_pre_wake_enabled": false
}

NOTE: usually you would enable either ovos-ww-verifier-silero or set "vad_pre_wake_enabled" true, not both

Summary by CodeRabbit

  • New Features

    • Introduced wake-word verification so only verified wake-word audio proceeds to callbacks and false triggers are reduced; added dynamic loading and reporting of verifier plugins.
  • Documentation

    • Added README example and guidance for configuring wake-word verifier plugins and related settings.
  • Chores

    • Bumped several plugin dependency versions for compatibility (plugin manager, VAD, microphone, STT, wake-word plugins).

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

Adds wake-word verifier plugin support: service loads verifier plugins and passes instances to HotwordContainer; HotwordContainer exposes a verify method; the voice loop aggregates hotword audio and gates detections through verify. Dependency pins and README verifier config were updated.

Changes

Cohort / File(s) Summary
Service — plugin loading
ovos_dinkum_listener/service.py
Discover and instantiate configured wake-word verifier plugins, log missing/failed/disabled plugins, and instantiate HotwordContainer with verifiers= list.
Hotword container & verifier API
ovos_dinkum_listener/voice_loop/hotwords.py
HotwordContainer.__init__ now accepts verifiers: Optional[List[HotWordVerifier]], adds verifiers attribute and verify(self, ww_audio: bytes) -> bool; replaces guarded get_sound_duration import with direct import.
Voice loop integration
ovos_dinkum_listener/voice_loop/voice_loop.py
Aggregate hotword chunks into hotword_audio_bytes, call hotwords.verify(...), discard detections on verification failure, and call listenword_audio_callback only after successful verification.
Requirements (extras)
requirements/extras.txt
Bump plugin package versions (e.g., ovos-stt-plugin-server, ovos-vad-plugin-silero, ovos-microphone-plugin-sounddevice, ovos-ww-plugin-vosk, ovos_ww_plugin_precise_onnx).
Requirements (core)
requirements/requirements.txt, requirements/linux.txt
Raise minimum ovos-plugin-manager to >=2.1.0,<3.0.0; bump ovos-microphone-plugin-alsa requirement in requirements/linux.txt.
Documentation
README.md
Add ww_verifiers configuration example (plugin, threshold, enabled flag) and a note about not enabling it with vad_pre_wake_enabled.

Sequence Diagram(s)

sequenceDiagram
    participant HW as Hotword Detector
    participant VL as Voice Loop
    participant HC as HotwordContainer
    participant VER as Verifier Plugins
    participant CB as Callbacks

    HW->>VL: hotword detected (chunks)
    VL->>VL: aggregate hotword_audio_bytes

    rect rgb(235,244,255)
    Note over VL,HC: Verification gate (new)
    VL->>HC: verify(hotword_audio_bytes)
    HC->>VER: iterate verifiers
    VER-->>HC: pass / fail
    alt any fails
        HC-->>VL: False
        VL->>VL: discard detection
    else all pass
        HC-->>VL: True
        VL->>CB: listenword_audio_callback(hotword_audio_bytes)
    end
    end

    VL->>CB: wake_callback(...)
    VL->>VL: state transition
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Files to pay extra attention to:
    • ovos_dinkum_listener/voice_loop/hotwords.py — API signature change and verify logic
    • ovos_dinkum_listener/service.py — plugin discovery, instantiation, and error handling
    • ovos_dinkum_listener/voice_loop/voice_loop.py — audio aggregation and verification placement
    • Requirements bumps — ensure compatibility with plugin-manager and plugin versions

Poem

🐰🎶
I hop on bytes and listen clear,
Plugins whisper, then I hear,
Verifiers blink, false wakes depart,
Softly keeps the morning start.

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Hotword verifier' directly and clearly summarizes the main change: adding wake-word verifier plugin support throughout the codebase.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hotword_veriifier

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71d0814 and dc56a4c.

📒 Files selected for processing (1)
  • requirements/requirements.txt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • requirements/requirements.txt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@JarbasAl JarbasAl marked this pull request as ready for review November 4, 2025 03:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3afe709 and 57742e9.

📒 Files selected for processing (7)
  • ovos_dinkum_listener/service.py (3 hunks)
  • ovos_dinkum_listener/voice_loop/hotwords.py (3 hunks)
  • ovos_dinkum_listener/voice_loop/voice_loop.py (2 hunks)
  • requirements/extras.txt (1 hunks)
  • requirements/onnx.txt (0 hunks)
  • requirements/requirements.txt (1 hunks)
  • setup.py (0 hunks)
💤 Files with no reviewable changes (2)
  • requirements/onnx.txt
  • setup.py
🧰 Additional context used
🧬 Code graph analysis (2)
ovos_dinkum_listener/service.py (1)
ovos_dinkum_listener/voice_loop/hotwords.py (1)
  • HotwordContainer (98-357)
ovos_dinkum_listener/voice_loop/voice_loop.py (1)
ovos_dinkum_listener/voice_loop/hotwords.py (2)
  • clear (33-37)
  • verify (304-309)
🪛 Ruff (0.14.3)
ovos_dinkum_listener/service.py

200-200: Do not catch blind exception: Exception

(BLE001)


200-200: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

ovos_dinkum_listener/voice_loop/hotwords.py

102-102: Do not perform function call FakeBus in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

@JarbasAl JarbasAl marked this pull request as draft November 4, 2025 15:01
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

49-49: Fix JSON syntax error.

The opening quote is missing for the "VAD" key, making this an invalid JSON example.

Apply this diff:

-    VAD": {
+    "VAD": {
♻️ Duplicate comments (2)
ovos_dinkum_listener/service.py (2)

204-207: Respect the same enable flag when reporting missing verifiers.

The loading logic at line 195 checks cfg.get("enabled", True), but the missing-plugin warning here checks v.get("active", True). This inconsistency causes false warnings when users set "enabled": false to deliberately disable a verifier. Please use the same enable flag in both locations.

Based on past review comments.


191-209: Reload verifiers when configuration changes.

Wake-word verifier plugins are instantiated only once during service initialization. The reload_configuration method (lines 1071-1171) reloads hotwords, STT, and other components when config changes, but never refreshes verifiers. This means changes to listener.ww_verifiers config (enable/disable, threshold adjustments) have no effect until the entire service is restarted. Please extract verifier loading into a helper method and call it both here and within reload_configuration after the new config is read, assigning the fresh verifier list to self.hotwords.verifiers.

Based on past review comments.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57742e9 and be0f092.

📒 Files selected for processing (6)
  • README.md (1 hunks)
  • ovos_dinkum_listener/service.py (3 hunks)
  • ovos_dinkum_listener/voice_loop/hotwords.py (3 hunks)
  • ovos_dinkum_listener/voice_loop/voice_loop.py (2 hunks)
  • requirements/extras.txt (1 hunks)
  • requirements/requirements.txt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • requirements/extras.txt
🧰 Additional context used
🧬 Code graph analysis (2)
ovos_dinkum_listener/service.py (1)
ovos_dinkum_listener/voice_loop/hotwords.py (2)
  • get (71-75)
  • HotwordContainer (98-357)
ovos_dinkum_listener/voice_loop/voice_loop.py (1)
ovos_dinkum_listener/voice_loop/hotwords.py (2)
  • plugins (222-223)
  • verify (304-309)
🪛 Ruff (0.14.3)
ovos_dinkum_listener/service.py

200-200: Do not catch blind exception: Exception

(BLE001)


200-200: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

ovos_dinkum_listener/voice_loop/hotwords.py

102-102: Do not perform function call FakeBus in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)

🔇 Additional comments (3)
ovos_dinkum_listener/voice_loop/voice_loop.py (1)

558-566: LGTM!

The verification gate is cleanly implemented. Audio is assembled from chunks once, verified through the plugin chain, and detection is discarded early if any verifier fails. This prevents false wake-word callbacks while maintaining efficient processing.

ovos_dinkum_listener/voice_loop/hotwords.py (1)

102-110: LGTM!

The verifier integration is well-implemented. The verifiers parameter follows best practices with a None default, and the verify method provides clear fail-fast semantics—returning False on the first verification failure and True only if all verifiers pass.

Also applies to: 304-309

requirements/requirements.txt (1)

1-1: The alpha version requirement is justified by the new wake word verifier feature.

The version bump to >=2.1.0a1 is directly tied to the "ww verifier" feature introduced in this commit (be0f092), which requires new find_wake_word_verifier_plugins() APIs that don't exist in the stable 1.0.3 release. The feature is now actively used in service.py and voice_loop.py, and is documented in the README. This is intentional, coordinated development with upstream ovos-plugin-manager (PR #341).

However, since you're depending on an alpha version, monitor upstream releases for a stable 2.1.0 final version to transition away from the prerelease.

@JarbasAl JarbasAl changed the title Hotword veriifier feat: Hotword verifier Nov 4, 2025
@JarbasAl JarbasAl marked this pull request as ready for review November 4, 2025 19:11
@github-actions github-actions bot added feature and removed feature labels Nov 4, 2025
@github-actions github-actions bot added feature and removed feature labels Nov 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants