Phase 14 구현: 회의 모드 (Meeting Mode)

실시간 녹음 + 타임스탬프 메모 + STT 전사 + LLM 구조화 회의록 + PDF/MD 내보내기.
CaptionService 연동, 동시 사용 충돌 방지, 긴 회의 2-pass 요약 지원.
DB 2테이블, IPC 15채널, UI 3뷰(목록/녹음/상세), 12개 locale i18n.
This commit is contained in:
Yun Chan 2026-04-08 01:16:52 +09:00
parent dd68fc9ccd
commit d0c4f9ee53
38 changed files with 2550 additions and 769 deletions

View file

@ -12,36 +12,37 @@ tools:
# UI Specialist
Speakly 렌더러 분석(781KB 번들)에서 추출한 UI 패턴을 적용.
D3RO-VOICE의 "정밀 기기(Meteorological Instrument)" 디자인 정체성을 구현.
## 컴포넌트 구조 (Speakly 패턴)
```
App (root)
├── ThemeProvider (MUI, light/dark/auto)
├── Drawer (240px 사이드바)
│ ├── NavItems
│ └── BottomBar
└── Content Area
├── Dashboard (통계, 최근 세션)
├── History (검색, 재시도)
├── Dictionary (사전 관리)
└── Settings (Modal)
```
## 디자인 토큰 체계 (SSOT)
- **d3roPalette**: 색상 토큰 (theme.ts에서 export)
- **d3roTypo**: 13단계 타이포 (hero 42px ~ nano 7px)
- **d3roShadow**: 10종 그림자 (chassis/card/inset/button 등)
- **d3roRadius**: 7종 반경 (outer 24px ~ pill 999px)
- hex 리터럴 직접 사용 금지 (theme.ts 제외)
## MUI 테마 (Speakly 참조)
- primary: rgb(31, 93, 242)
- borderRadius: 12
- fontFamily: -apple-system, BlinkMacSystemFont, "Segoe UI"
- textTransform: 'none'
- WebkitAppRegion: 'drag' (타이틀바)
## DS 컴포넌트 (src/renderer/components/ds/)
- CrtDisplay: WebGL CRT 셰이더 (파형+스캔라인+비네팅+글리치)
- InstrumentPanel: 메탈 섀시 컨테이너
- Led: LED 인디케이터 (amber/green/red, pulse)
- PhysicalButton: 물리 버튼 (돌출 그림자, 눌림)
- MetalCard: 메탈 카드 컨테이너
- PhosphorText: 인광 텍스트 (13종 변형)
- MetalDial: 메탈 다이얼 (드래그 회전)
- ScreenPanel: 글래스 스크린 패널
- ButtonGroup: 인셋 버튼 클러스터
## 녹음 UI 상태 머신
opening → recording → thinking → result/error/cancelled
- 9개 wave-bar, cos(n*PI/2) 분포 가중치
- 100ms 간격 setInterval, smoothing: v += (S-v)*0.5
- 100ms 간격, smoothing: v += (S-v)*0.5
- thinking: `min(95, (1 - 1/(1+1.5*t)) * 100)%` 점근 수렴
## 팝업 윈도우 (Vanilla JS)
- 별도 HTML 엔트리포인트, React 미사용
- 별도 HTML, React 미사용
- 2-phase 리사이즈: prepare → measured → show
- CSS transition + transitionend + 200ms setTimeout 폴백
- 앰버 악센트(#f25b29)
## i18n
- React: t() 함수 사용, 하드코딩 한국어/영어 금지
- 리소스: src/renderer/locales/{ko,en}.json

View file

@ -28,16 +28,17 @@ AudioState: IDLE → INITIALIZING → STREAMING → STOPPED (별도 추적)
- 이중 조건 플러시: 모델 로딩 + 오디오 캡처 병렬
- `_tryFlushAll()`: 양쪽 조건 모두 true 시 flush
- 순서 보장: 설정 메시지 → 오디오 데이터
- "오디오 손실 방지 > 컨텍스트 품질" 원칙
## 오디오 설정
- sampleRate: 24000Hz → 16000Hz (Whisper 기본)
- channels: 1 (mono)
- noiseSuppression: false (초기 프레임 손실 방지)
- echoCancellation: false (일방향 입력)
- autoGainControl: false
- sampleRate: 16000Hz (Whisper 기본)
- channels: 1 (mono), bitDepth: 16 (PCM16)
- noiseSuppression: false, echoCancellation: false, autoGainControl: false
## 로컬 STT 연동
- Whisper에 PCM 16-bit 16kHz mono 직접 전달
- Opus 인코딩 불필요 (로컬이므로)
- faster-whisper Python sidecar 또는 whisper.cpp addon
- PCM 16-bit 16kHz mono → faster-whisper Python sidecar (FastAPI HTTP)
- Opus 인코딩 불필요 (로컬)
## 타이밍 상수
- 더블프레스: 300ms, 최소 오디오: 700ms
- 녹음 후 대기: 4초 (버퍼 있으면 6초)
- 완료 아이들 타임아웃: 30초, 절대 최대: 120초