[打断低延迟修复]:完成真实播报打断门控修正,包含短保护窗口、用户音色优先和诊断输出

This commit is contained in:
mkbk
2026-06-19 11:27:34 +08:00
parent f1f4885cc5
commit 7c6797aeb0
8 changed files with 222 additions and 32 deletions
+33 -7
View File
@@ -204,7 +204,12 @@ def make_runtime(
reporter = RecordingReporter()
event_bus = PipelineEventBus()
runtime = VoiceAssistantPipeline(
config=AppConfig(llm_api_key="secret", speech_provider="cloud", wake_ack_text=wake_ack_text),
config=AppConfig(
llm_api_key="secret",
speech_provider="cloud",
wake_ack_text=wake_ack_text,
barge_in_enabled=False,
),
transport=transport,
wakeword=KeywordWakeWordProvider(),
vad_recorder=VadRecorder(EnergyVadProvider(), min_duration_ms=40, end_silence_ms=40),
@@ -345,7 +350,12 @@ class LiveRuntimeTests(unittest.TestCase):
transport = MemoryAudioTransport(frames, flush_clears_input=False)
ack_tts = CountingTtsProvider()
runtime = VoiceAssistantPipeline(
config=AppConfig(llm_api_key="secret", speech_provider="cloud", wake_ack_text="我在"),
config=AppConfig(
llm_api_key="secret",
speech_provider="cloud",
wake_ack_text="我在",
barge_in_enabled=False,
),
transport=transport,
wakeword=KeywordWakeWordProvider(),
vad_recorder=VadRecorder(EnergyVadProvider(), min_duration_ms=40, end_silence_ms=40),
@@ -363,8 +373,8 @@ class LiveRuntimeTests(unittest.TestCase):
self.assertEqual(summary.completed_turns, 2)
self.assertEqual(ack_tts.synthesized_texts, ["我在"])
self.assertEqual(transport.played_segments[0].metadata["text"], "我在")
self.assertEqual(transport.played_segments[3].metadata["text"], "我在")
ack_segments = [segment for segment in transport.played_segments if segment.metadata.get("text") == "我在"]
self.assertEqual(len(ack_segments), 2)
def test_zero_post_playback_drain_flushes_without_dropping_prefilled_question(self) -> None:
runtime, stt, _, transport, reporter = make_runtime(["第一问"])
@@ -387,7 +397,7 @@ class LiveRuntimeTests(unittest.TestCase):
self.assertEqual(summary.completed_turns, 1)
self.assertEqual(reporter.transcripts, ["第一问"])
self.assertEqual(len(stt.calls), 1)
self.assertEqual(len(transport.played_segments), 2)
self.assertGreaterEqual(len(transport.played_segments), 2)
self.assertEqual(transport.flush_count, 2)
self.assertEqual(transport.played_segments[-1].metadata["chime"], "end")
self.assertEqual(transport.played_segments[-1].metadata["source"], "file")
@@ -400,8 +410,8 @@ class LiveRuntimeTests(unittest.TestCase):
summary = runtime.run(max_turns=1)
self.assertEqual(summary.completed_turns, 1)
self.assertEqual(len(transport.played_segments), 1)
self.assertNotIn("chime", transport.played_segments[-1].metadata)
self.assertGreaterEqual(len(transport.played_segments), 1)
self.assertFalse(any("chime" in segment.metadata for segment in transport.played_segments))
def test_temporary_context_is_sent_to_second_llm_call(self) -> None:
runtime, _, llm, _, _ = make_runtime(["第一问", "第二问"])
@@ -587,6 +597,7 @@ class LiveRuntimeTests(unittest.TestCase):
speech_provider="cloud",
wake_ack_text="",
followup_listen_timeout_ms=3000,
barge_in_enabled=False,
),
transport=transport,
wakeword=KeywordWakeWordProvider(),
@@ -627,6 +638,7 @@ class LiveRuntimeTests(unittest.TestCase):
speech_provider="cloud",
wake_ack_text="",
followup_listen_timeout_ms=3000,
barge_in_enabled=False,
),
transport=transport,
wakeword=KeywordWakeWordProvider(),
@@ -662,6 +674,7 @@ class LiveRuntimeTests(unittest.TestCase):
speech_provider="cloud",
wake_ack_text="",
followup_listen_timeout_ms=3000,
barge_in_enabled=False,
),
transport=transport,
wakeword=KeywordWakeWordProvider(),
@@ -771,6 +784,19 @@ class LiveRuntimeTests(unittest.TestCase):
self.assertEqual(reporter.transcripts[-1], "打断问题")
self.assertEqual(len(llm.calls), 2)
def test_barge_in_echo_guard_is_capped_and_only_used_once_per_reply(self) -> None:
runtime, _, _, _, _ = make_runtime(["第一问"])
runtime.controller._barge_in_reply_guard_used = False
segment = AudioSegment(b"\x01\x00" * 16000, 16000, 1, 0, 1000)
first_guard = runtime.controller._effective_barge_in_echo_guard_ms(segment)
second_guard = runtime.controller._effective_barge_in_echo_guard_ms(segment)
min_speech = runtime.controller._effective_barge_in_min_speech_ms()
self.assertEqual(first_guard, 120)
self.assertEqual(second_guard, 0)
self.assertLessEqual(min_speech, runtime.config.interrupt_target_latency_ms)
if __name__ == "__main__":
unittest.main()