"제일 위험한 두 순간은 첫 밀리초와 마지막 밀리초야. 나머지는 다 기록 관리야."
누르고, 말하고, 놓고
받아쓰기 하나는 단축키에서 깔끔히 쪼개져. 키-누름에 두 개를 동시에 잡아: 타깃 스냅샷(지금 누가 포커스인가)과 오디오 스트림(마이크가 이미 데워진 채로). 키-놓음에 전사를 확정하고, 정리하고, 스냅샷한 타깃에 삽입해. 컨트롤러는 일부러 작아:
DictationController.start(mode):
snapshot = TargetCapture.snapshot() # 최전면 앱, 포커스된 요소, 선택
Audio.start() # 짧은 프리롤과 함께 캡처 시작
DictationController.stop():
audio = Audio.finish() # 마지막 음절 살리게 짧은 꼬리 추가
text = STT.finalize(audio)
clean = Cleanup.run(text, snapshot)
Insertion.insert(clean, into: snapshot)
첫 밀리초: 프리롤
사람은 손가락이 다 누르기 전에 말하기 시작해. 캡처가 키-누름 정확히 그 순간에 시작하면 첫 음절이 이미 사라졌어 — "보내" 가 "내" 가 돼. 해법은 프리롤: 짧은 롤링 버퍼를 유지해서 확정하는 오디오가 키가 등록되기 전 ~반 초를 포함하게. 근데 프리롤은 프라이버시랑 싸워 — 진짜 롤링 버퍼는 받아쓰기 사이에 마이크가 늘 살아있다는 뜻이야. Firekeeper 의 솔직한 트레이드오프는 늘-켜진 버퍼 대신 실행 시 마이크 권한을 요청하고 엔진을 빨리 시작하는 거야, 왜냐면 보이는-녹음-만 규칙이 숨은-늘-듣기 보다 나으니까.
마지막 밀리초: 꼬리
거울 문제가 끝에 있어. 사람은 마지막 단어를 끝내는 순간 키를 놓아 — 때론 살짝 일찍. 오디오를 키-놓음 정확히 그 순간에 자르면 마지막 음절이 잘려. 그래서 캡처는 확정 전에 키-놓음 후 짧은 꼬리(Firekeeper 는 대략 4분의 1초) 동안 계속 돌아. 앞뒤 두 개의 아주 작은 시간-이동이 '전사가 고장 났어' 와 '전사가 완벽해' 의 차이야.
녹음의 가운데만 말고 가장자리를 지켜. 발화 가운데의 STT 품질은 모델 일이야. 첫 음절과 마지막 음절은 앱 일이야 — 프리롤이 시작을 지키고, 놓음 꼬리가 끝을 지켜. 가장자리를 틀리면 유저는 네가 만든 버그를 모델 탓해.
침묵 감지기가 첫 단어를 먹게 절대 두지 마. 음성 활동 감지(VAD)는 죽은 공기를 다듬고 끝점 찾는 데 좋아 — 근데 프리롤 전에 돌면, 조용한 도입부를 '아무것도 아님' 으로 판단해 네가 필요했던 바로 그 음절을 버릴 수 있어. 순서가 중요해: 프리롤 유지 후 침묵 다듬기, 절대 반대로 하지 마.