[实时字幕端点]:完成无新文字快速结束录音,包含1.5秒停滞配置、Capture端点和回归测试
This commit is contained in:
@@ -163,6 +163,7 @@ class TurnController:
|
||||
self.vad_recorder.provider.reset()
|
||||
self.audio_preprocessor.reset()
|
||||
realtime_session = self._start_realtime_transcript()
|
||||
last_partial_ms: int | None = None
|
||||
self._event(CAPTURE_STARTED, PipelineState.RECORDING, state_message, turn_id=turn_id)
|
||||
while True:
|
||||
frames = self.transport.read_frames(timeout_ms=100)
|
||||
@@ -180,7 +181,8 @@ class TurnController:
|
||||
if isinstance(result, ProviderError):
|
||||
return result
|
||||
if self.vad_recorder.started and realtime_session is not None:
|
||||
self._emit_realtime_transcript(realtime_session, frame, turn_id)
|
||||
if self._emit_realtime_transcript(realtime_session, frame, turn_id):
|
||||
last_partial_ms = frame.timestamp_ms
|
||||
if isinstance(result, AudioSegment):
|
||||
if realtime_session is not None:
|
||||
self._finish_realtime_transcript(realtime_session, turn_id)
|
||||
@@ -192,6 +194,18 @@ class TurnController:
|
||||
payload={"end_reason": result.metadata.get("end_reason", "")},
|
||||
)
|
||||
return result
|
||||
if self._should_end_after_realtime_idle(last_partial_ms, frame.timestamp_ms):
|
||||
if realtime_session is not None:
|
||||
self._finish_realtime_transcript(realtime_session, turn_id)
|
||||
result = self.vad_recorder.finish("partial_transcript_idle")
|
||||
self._event(
|
||||
SPEECH_ENDED,
|
||||
PipelineState.RECORDING,
|
||||
"用户语音结束",
|
||||
turn_id=turn_id,
|
||||
payload={"end_reason": result.metadata.get("end_reason", "")},
|
||||
)
|
||||
return result
|
||||
|
||||
def _start_realtime_transcript(self) -> RealtimeTranscriptSession | None:
|
||||
if not self.config.realtime_transcript_enabled or self.realtime_stt is None:
|
||||
@@ -203,14 +217,19 @@ class TurnController:
|
||||
realtime_session: RealtimeTranscriptSession,
|
||||
frame: AudioFrame,
|
||||
turn_id: int,
|
||||
) -> None:
|
||||
) -> bool:
|
||||
transcript = realtime_session.accept_frame(frame)
|
||||
if transcript is None:
|
||||
return
|
||||
return False
|
||||
text = transcript.normalized_text
|
||||
if not is_valid_transcript_text(text):
|
||||
return
|
||||
return False
|
||||
self._event(TRANSCRIPT_PARTIAL, PipelineState.RECORDING, "", turn_id=turn_id, payload={"text": text})
|
||||
return True
|
||||
|
||||
def _should_end_after_realtime_idle(self, last_partial_ms: int | None, current_ms: int) -> bool:
|
||||
timeout_ms = self.config.realtime_transcript_idle_timeout_ms
|
||||
return timeout_ms > 0 and last_partial_ms is not None and current_ms - last_partial_ms >= timeout_ms
|
||||
|
||||
def _finish_realtime_transcript(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user