mirror of
https://github.com/home-assistant/core.git
synced 2026-11-02 03:31:34 -04:00
Use different VAD thresholds for before and during voice command (#129848)
* Use two VAD thresholds * Fix VoiceActivityTimeout class * Update homeassistant/components/assist_pipeline/audio_enhancer.py --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
co-authored by
Joost Lekkerkerker
parent
6caa4baa00
commit
69e3348cd7
@@ -16,7 +16,7 @@ def test_silence() -> None:
|
||||
segmenter = VoiceCommandSegmenter()
|
||||
|
||||
# True return value indicates voice command has not finished
|
||||
assert segmenter.process(_ONE_SECOND * 3, False)
|
||||
assert segmenter.process(_ONE_SECOND * 3, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
|
||||
@@ -26,15 +26,15 @@ def test_speech() -> None:
|
||||
segmenter = VoiceCommandSegmenter()
|
||||
|
||||
# silence
|
||||
assert segmenter.process(_ONE_SECOND, False)
|
||||
assert segmenter.process(_ONE_SECOND, 0.0)
|
||||
|
||||
# "speech"
|
||||
assert segmenter.process(_ONE_SECOND, True)
|
||||
assert segmenter.process(_ONE_SECOND, 1.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
# silence
|
||||
# False return value indicates voice command is finished
|
||||
assert not segmenter.process(_ONE_SECOND, False)
|
||||
assert not segmenter.process(_ONE_SECOND, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
|
||||
@@ -112,19 +112,19 @@ def test_silence_seconds() -> None:
|
||||
segmenter = VoiceCommandSegmenter(silence_seconds=1.0)
|
||||
|
||||
# silence
|
||||
assert segmenter.process(_ONE_SECOND, False)
|
||||
assert segmenter.process(_ONE_SECOND, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
# "speech"
|
||||
assert segmenter.process(_ONE_SECOND, True)
|
||||
assert segmenter.process(_ONE_SECOND, 1.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
# not enough silence to end
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
# exactly enough silence now
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
|
||||
@@ -134,27 +134,27 @@ def test_silence_reset() -> None:
|
||||
segmenter = VoiceCommandSegmenter(silence_seconds=1.0, reset_seconds=0.5)
|
||||
|
||||
# silence
|
||||
assert segmenter.process(_ONE_SECOND, False)
|
||||
assert segmenter.process(_ONE_SECOND, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
# "speech"
|
||||
assert segmenter.process(_ONE_SECOND, True)
|
||||
assert segmenter.process(_ONE_SECOND, 1.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
# not enough silence to end
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
# speech should reset silence detection
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, True)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 1.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
# not enough silence to end
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
# exactly enough silence now
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
|
||||
@@ -166,23 +166,23 @@ def test_speech_reset() -> None:
|
||||
)
|
||||
|
||||
# silence
|
||||
assert segmenter.process(_ONE_SECOND, False)
|
||||
assert segmenter.process(_ONE_SECOND, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
# not enough speech to start voice command
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, True)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 1.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
# silence should reset speech detection
|
||||
assert segmenter.process(_ONE_SECOND, False)
|
||||
assert segmenter.process(_ONE_SECOND, 0.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
# not enough speech to start voice command
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, True)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 1.0)
|
||||
assert not segmenter.in_command
|
||||
|
||||
# exactly enough speech now
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, True)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 1.0)
|
||||
assert segmenter.in_command
|
||||
|
||||
|
||||
@@ -193,18 +193,18 @@ def test_timeout() -> None:
|
||||
|
||||
# not enough to time out
|
||||
assert not segmenter.timed_out
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
assert not segmenter.timed_out
|
||||
|
||||
# enough to time out
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, True)
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, 1.0)
|
||||
assert segmenter.timed_out
|
||||
|
||||
# flag resets with more audio
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, True)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 1.0)
|
||||
assert not segmenter.timed_out
|
||||
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
assert segmenter.timed_out
|
||||
|
||||
|
||||
@@ -215,14 +215,38 @@ def test_command_seconds() -> None:
|
||||
command_seconds=3, speech_seconds=1, silence_seconds=1, reset_seconds=1
|
||||
)
|
||||
|
||||
assert segmenter.process(_ONE_SECOND, True)
|
||||
assert segmenter.process(_ONE_SECOND, 1.0)
|
||||
|
||||
# Silence counts towards total command length
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
|
||||
# Enough to finish command now
|
||||
assert segmenter.process(_ONE_SECOND, True)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert segmenter.process(_ONE_SECOND, 1.0)
|
||||
assert segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
|
||||
# Silence to finish
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, False)
|
||||
assert not segmenter.process(_ONE_SECOND * 0.5, 0.0)
|
||||
|
||||
|
||||
def test_speech_thresholds() -> None:
|
||||
"""Test before/in command speech thresholds."""
|
||||
|
||||
segmenter = VoiceCommandSegmenter(
|
||||
before_command_speech_threshold=0.2,
|
||||
in_command_speech_threshold=0.5,
|
||||
command_seconds=2,
|
||||
speech_seconds=1,
|
||||
silence_seconds=1,
|
||||
)
|
||||
|
||||
# Not high enough probability to trigger command
|
||||
assert segmenter.process(_ONE_SECOND, 0.1)
|
||||
assert not segmenter.in_command
|
||||
|
||||
# Triggers command
|
||||
assert segmenter.process(_ONE_SECOND, 0.3)
|
||||
assert segmenter.in_command
|
||||
|
||||
# Now that same probability is considered silence.
|
||||
# Finishes command.
|
||||
assert not segmenter.process(_ONE_SECOND, 0.3)
|
||||
|
||||
Reference in New Issue
Block a user