Add minimum command seconds to VAD (#124447)

This commit is contained in:
Michael Hansen 2024-08-24 15:21:03 -05:00 committed by GitHub
parent c506188c13
commit 156e39ebb2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 1 deletions

View File

@ -78,6 +78,9 @@ class VoiceCommandSegmenter:
speech_seconds: float = 0.3
"""Seconds of speech before voice command has started."""
command_seconds: float = 1.0
"""Minimum number of seconds for a voice command."""
silence_seconds: float = 0.7
"""Seconds of silence after voice command has ended."""
@ -96,6 +99,9 @@ class VoiceCommandSegmenter:
_speech_seconds_left: float = 0.0
"""Seconds left before considering voice command as started."""
_command_seconds_left: float = 0.0
"""Seconds left before voice command could stop."""
_silence_seconds_left: float = 0.0
"""Seconds left before considering voice command as stopped."""
@ -112,6 +118,7 @@ class VoiceCommandSegmenter:
def reset(self) -> None:
"""Reset all counters and state."""
self._speech_seconds_left = self.speech_seconds
self._command_seconds_left = self.command_seconds - self.speech_seconds
self._silence_seconds_left = self.silence_seconds
self._timeout_seconds_left = self.timeout_seconds
self._reset_seconds_left = self.reset_seconds
@ -142,6 +149,9 @@ class VoiceCommandSegmenter:
if self._speech_seconds_left <= 0:
# Inside voice command
self.in_command = True
self._command_seconds_left = (
self.command_seconds - self.speech_seconds
)
self._silence_seconds_left = self.silence_seconds
_LOGGER.debug("Voice command started")
else:
@ -154,7 +164,8 @@ class VoiceCommandSegmenter:
# Silence in command
self._reset_seconds_left = self.reset_seconds
self._silence_seconds_left -= chunk_seconds
if self._silence_seconds_left <= 0:
self._command_seconds_left -= chunk_seconds
if (self._silence_seconds_left <= 0) and (self._command_seconds_left <= 0):
# Command finished successfully
self.reset()
_LOGGER.debug("Voice command finished")
@ -163,6 +174,7 @@ class VoiceCommandSegmenter:
# Speech in command.
# Reset silence counter if enough speech.
self._reset_seconds_left -= chunk_seconds
self._command_seconds_left -= chunk_seconds
if self._reset_seconds_left <= 0:
self._silence_seconds_left = self.silence_seconds
self._reset_seconds_left = self.reset_seconds

View File

@ -206,3 +206,23 @@ def test_timeout() -> None:
assert not segmenter.process(_ONE_SECOND * 0.5, False)
assert segmenter.timed_out
def test_command_seconds() -> None:
"""Test minimum number of seconds for voice command."""
segmenter = VoiceCommandSegmenter(
command_seconds=3, speech_seconds=1, silence_seconds=1, reset_seconds=1
)
assert segmenter.process(_ONE_SECOND, True)
# Silence counts towards total command length
assert segmenter.process(_ONE_SECOND * 0.5, False)
# Enough to finish command now
assert segmenter.process(_ONE_SECOND, True)
assert segmenter.process(_ONE_SECOND * 0.5, False)
# Silence to finish
assert not segmenter.process(_ONE_SECOND * 0.5, False)