마지막 업데이트 2026-07-22
아동 마이크를 16kHz Int16 PCM으로 가공해 Go STT 서버(wss://.../ws/stt)로 스트리밍하고, 배치 전사 결과를 콜백으로 돌려받는 브라우저측 WebSocket 클라이언트. 서버측(배치/화자분리/dedup)은 #4 STT 배치 서버.
batch_result)는 use-ai-session이 받아 세션 로그 저장 + (waitForSttResponse 모드면) 수동 response.create 트리거에 쓴다. 모드 전환·소비는 stt-expert 영역.
| 레이어 | 역할 | 파일 |
|---|---|---|
ExternalSTTObserver | WS 연결·오디오 그래프·prebuffer·송수신(클래스, 551L) | entities/guest-session/lib/external-stt-observer.ts |
useExternalStt | React 래퍼: start/stop/requestFinalize/requestReset + 콜백 배선(244L) | hooks/use-external-stt.ts |
VAD가 "아동 발화 시작"을 인지하는 시점은 실제 발화보다 약간 늦다. 그 사이 음성을 버리면 첫 음절이 잘린다. 그래서 발화 전 오디오를 prebuffer(~600ms)에 모아두다가, userTalking이 켜지는 순간 shouldFlushPrebuffer로 한 번에 flush한 뒤 이어서 실시간 전송한다.
setUserTalking(true) → flush 예약. !userTalking 동안은 addToPrebuffer로만 축적(한도 prebufferSamplesLimit).hasAiSpokenOnce 게이트: AI가 한 번도 말하기 전(세션 초반)에는 전송하지 않음.// 바이너리: [speaker byte] + Int16 PCM header = [0] (user) | [1] (ai) → ws.send(header + int16)
| 메서드 | 전송 |
|---|---|
sendAudio(data, "user") | 아동 마이크 PCM (0x00) |
sendAIAudio(data) | AI 음성 PCM (0x01) |
requestFinalize() | {type:"finalize"} → 배치 STT 트리거 |
requestAIAudioSTT() | {type:"process_ai_audio"} |
requestReset() | {type:"reset"} (활동 전환) |
| type | 콜백 | 페이로드 |
|---|---|---|
monitor | transcriptCallback(isFinal:false) | 중간 결과 |
finalized | transcript + finalizedCallback | 최종(스트리밍 모드) |
batch_result | finalizedCallback | transcript, originalText, wasDeduped, diarization, sttSessionId/requestId, latencyMs |
ai_stt | aiSttCallback | transcript, confidence, history_count |
latency는 finalizeRequestedAt/aiSttRequestedAt과의 차로 계산. wasDeduped+originalText는 세션 로그의 stt_dedup 타입 저장에 쓰인다(#4).
gen !== current면 stale 이벤트로 무시 → StrictMode 이중 실행·재연결 레이스에서 옛 소켓 콜백이 새 연결을 망치는 것 방지.maxReconnectAttempts회, 지수 백오프(1000 * attemptms).| 파일/심볼 | 역할 |
|---|---|
| external-stt-observer.ts | WS 클라이언트 본체 |
| startAudioStreaming (L290) | 오디오 그래프·다운샘플·prebuffer 전송 |
| connectWebSocket (L147) | 연결·gen 가드·재연결 |
| onmessage (L168) | monitor/finalized/batch_result/ai_stt 분기 |
| hooks/use-external-stt.ts | React 래퍼·콜백 배선 |