STT 오디오 처리/세션 (Go) — VAD·필터·turn history 코드레벨 동작 흐름 P2코드레벨

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

작성일: 2026-06-14 대상: 개발자 — STT 서버 내부 오디오/세션 모듈 파악 핵심 파일: apps/stt/internal/{audio,session}/

개요 · 범위

STT 배치 서버(#4)의 하위 모듈 — 오디오 처리(filter/limiter/VAD/PCM)세션 상태(turn 버퍼·history·debounce). #4가 "흐름"이라면 본 문서는 그 흐름이 쓰는 "부품".

오디오 처리 internal/audio/

모듈역할
pcm.goPCM int16 ↔ float64 변환, WAV 인코딩/디코딩, AudioDuration(bytes, sr)
filter.goBiquad(2nd) + 6th-order HPF / 4th-order LPF Butterworth
limiter.go다이내믹 레인지 제한(ceiling), ProcessWithGain
processor.go파이프라인: HPF 195Hz(6th) → LPF 13kHz(4th) → Limiter 89%
vad.goRMS 기반 무음 trim·VAD
DefaultProcessorConfig: 16kHz, HPF 195Hz, LPF 13kHz, ceiling 0.89(89%). "Python 서버와 동일" 주석 — 기존 파이프라인 포팅. (클라이언트 STT 전용 HPF 100Hz/Limiter -3dBFS와는 별개 — #9)

무음 trim vad.go: TrimLeading/TrailingSilencePCM L42/119

TrimLeadingSilencePCM(pcm, threshold, keepMS, sampleRate)
TrimTrailingSilencePCM(...)        // RMS < threshold(int16, 예 200) = 무음
CalculateRMS(pcm)                  // 무음 판정 기준

#4의 handleBatchFinalize가 user leading/trailing·AI 무음을 이 함수들로 잘라낸다(keepMS만큼 보존).

세션 상태 internal/session/session.go, history.go

구조/함수역할
Session.CurrentTurn현재 턴 {AIAudio, UserAudio} bytes.Buffer (mutex 보호)
WriteAudioChunk(speaker, data)바이너리 수신분을 current turn 버퍼에 append
SnapshotAndResetCurrentTurnAPI 호출 전 원자 스냅샷+리셋(#4 핵심)
AddTurnToHistory턴을 history에 추가, MaxBatchTurns 초과분 앞에서 제거(슬라이딩)
BuildCombinedAudioWithCurrenthistory(AI+User 순) + 현재 턴 결합, MaxBatchBytes 초과 시 뒤쪽만 보존
ConversationHistory화자별 텍스트 히스토리(HistorySizePerSpeaker, 화자분리 컨텍스트)
BatchDebounceStatefinalize requestID 발급·최신성(IsLatest)
combined audio 순서 = AI 먼저: BuildCombinedAudioWithCurrent가 각 턴을 AIAudio → UserAudio 순으로 쓴다. 이 순서가 화자분리 First-Speaker Rule(첫 화자=AI, #4)의 전제.

함정 · 주의

  • AI 먼저 순서 고정: combined 빌드가 AI→User 순. 바꾸면 First-Speaker Rule 화자 라벨 반전(#4).
  • MaxBatchBytes는 뒤쪽 보존: 초과 시 data[len-max:]로 최신만 남김(앞쪽 오래된 컨텍스트 절삭).
  • trim threshold는 int16 범위: RMS threshold(예 200)는 int16 진폭 기준. dBFS와 혼동 금지.
  • 서버/클라이언트 DSP 별개: 서버 Processor(HPF 195/LPF 13k/89%)와 클라 STT DSP(#9, HPF 100/Limiter -3dB)는 서로 다른 단계.
  • mutex 보호: CurrentTurn/TurnHistory는 동시 접근(바이너리 수신 vs finalize goroutine)되므로 Lock 필수.

파일 · 라인 레퍼런스

파일/심볼역할
internal/audio/processor.go (DefaultProcessorConfig)HPF/LPF/Limiter 파이프라인
internal/audio/vad.go (TrimLeading/Trailing L42/119)무음 trim·RMS
internal/audio/pcm.goPCM/WAV 변환·duration
internal/session/session.go (Snapshot/AddTurn/BuildCombined)턴 버퍼·history·debounce
internal/session/history.go화자별 텍스트 히스토리