STT 폴백 (Web Speech API) — 코드레벨 동작 흐름 P2코드레벨

마지막 업데이트 2026-07-22

작성일: 2026-06-14 대상: 개발자 — 브라우저 네이티브 폴백 전사 파악 핵심 파일: hooks/use-stt-fallback.ts

개요 · 범위

3계층 STT 중 최후 폴백. OpenAI Realtime 내장 전사·External STT(#4/#9)가 결과를 못 줄 때 브라우저 네이티브 Web Speech API(SpeechRecognition, ko-KR)로 아동 발화를 텍스트화해 핑퐁이에 입력한다.

세션 매니저(#1)가 구동: fallbackTranscriptionEnabled일 때 활성. 전사 결과는 onTranscriptionsendMessage(transcript)로 텍스트 입력 전송. 데이터채널 이벤트(speech_started/output_audio_buffer)에 맞춰 start/stop이 토글된다.

SpeechRecognition 설정 initializeSpeechRecognition L36

recognition.continuous = true;
recognition.interimResults = true;   // 중간 결과로 빠른 처리
recognition.lang = "ko-KR";
recognition.maxAlternatives = 3;       // 다중 후보 중 최고 confidence 선택
// 가능 시 Google Speech API serviceURI 선호

미지원 브라우저(webkitSpeechRecognition/SpeechRecognition 둘 다 없음)면 null 반환 → 폴백 비활성.

결과 처리 setupSpeechRecognition onresult L95

  • final 결과: 최대 3개 alternative 중 최고 confidence 선택 → handleFallbackTranscription.
  • interim 결과: 최신 interim을 보관하고 1500ms 타임아웃 설정 → 그 안에 final이 안 오면 best interim을 결과로 사용(빠른 응답성 ↔ 정확성 타협).
  • final 도착 시 pending interim 타임아웃 취소.

전사 게이트 (에코 방지) handleFallbackTranscription L65

아래 조건을 모두 통과해야만 전사를 내보낸다:

audioInputEnabled && sessionActive && enabled
  && !isUserTalking && !isPeerTalking
  && recognitionId === currentRecognitionId
  • !isPeerTalking: 핑퐁이 발화 중에는 막아 AI 음성이 마이크로 들어가 전사되는 에코를 차단. 세션 매니저가 output_audio_buffer 이벤트에 맞춰 start/stop도 한다(#1).
  • recognitionId 매칭: start마다 id 증가. stop 시 0으로 무효화 → 옛 인식 인스턴스의 stale 타임아웃/결과가 새 세션에 끼어드는 것 방지.

생명주기 · 에러 start/stop/onend/onerror

  • start: enabled+audioInputEnabled일 때만. 새 recognitionId 발급 → 인스턴스 생성·setup·start.
  • onend 자동 재시작: continuous가 끊기면(브라우저가 주기적으로 종료) session/enabled/audioInput 활성 시 100ms 후 재시작.
  • stop: recognition.stop + id=0 무효화 + interim 타임아웃 정리.
  • onerror: no-speech/audio-capture/network는 일시 오류(무시), not-allowed/service-not-allowed는 권한 거부 로깅, aborted는 의도적 정지(재시작 안 함), 그 외 unknown은 안전상 폴백 비활성.

함정 · 주의

  • 폴백은 보조: 정확도·언어 지원이 External STT/OpenAI보다 낮다. 주 경로가 동작하면 쓰지 않는다.
  • recognitionId 무효화 필수: stop 시 id=0으로 안 바꾸면 옛 interim 타임아웃 결과가 새 발화에 섞임.
  • isPeerTalking 게이트: 빠지면 AI 음성이 폴백으로 다시 전사되는 에코 루프. 세션 매니저의 start/stop 토글과 이중 방어.
  • 브라우저 의존: Web Speech API 미지원(일부 인앱 브라우저)이면 폴백 자체가 없음 → 주 경로 장애 시 무전사.
  • onend 재시작 루프: 조건(session/enabled/audioInput)이 잘못 유지되면 stop 후에도 재시작될 수 있음 → updateEnabled(false)가 stop을 호출하는 구조에 의존.

파일 · 라인 레퍼런스

파일/심볼역할
use-stt-fallback.tsWeb Speech API 래퍼
initializeSpeechRecognition (L36)설정·미지원 가드
setupSpeechRecognition (L91) / handleFallbackTranscription (L65)결과 처리·게이트
use-session-manager.ts (sttFallback)구동·start/stop 토글