from agr_assistent.audio.recorder import UtteranceDetector, UtteranceStatus # Частота 100 отсчётов в секунду, окно — 10 отсчётов (0.1 с): так проще считать _WINDOW = 10 def _detector(**overrides: float) -> UtteranceDetector: settings = dict(threshold=0.5, start_timeout_seconds=1, silence_seconds=0.3, max_seconds=5) settings.update(overrides) return UtteranceDetector(sample_rate=100, **settings) def _feed(detector: UtteranceDetector, probabilities: list[float]) -> list[UtteranceStatus]: return [detector.update(p, _WINDOW) for p in probabilities] def test_phrase_completes_after_silence() -> None: statuses = _feed(_detector(), [0.1, 0.9, 0.8, 0.2, 0.1, 0.1]) assert statuses[:-1] == [UtteranceStatus.CONTINUE] * 5 assert statuses[-1] is UtteranceStatus.COMPLETE def test_short_pause_does_not_end_phrase() -> None: statuses = _feed(_detector(), [0.9, 0.1, 0.1, 0.9, 0.1, 0.1]) assert UtteranceStatus.COMPLETE not in statuses def test_no_speech_before_timeout() -> None: statuses = _feed(_detector(), [0.1] * 10) assert statuses[-1] is UtteranceStatus.NO_SPEECH assert statuses[:-1] == [UtteranceStatus.CONTINUE] * 9 def test_max_duration_completes_ongoing_speech() -> None: detector = _detector(max_seconds=0.5) statuses = _feed(detector, [0.9] * 5) assert statuses[-1] is UtteranceStatus.COMPLETE assert detector.speech_detected