13 KiB
13 KiB
Phase 10: 킬러 피처 — Speakly를 넘어서
Speakly가 제공하지 않는 D3RO-VOICE 고유 기능. 완전 로컬이라는 강점을 극대화하여 차별화된 사용자 경험을 제공한다.
10.1 실시간 자막 모드 (Live Caption)
목표
핫키 없이 마이크를 계속 듣고, 화면 하단에 실시간 자막을 오버레이로 표시한다. 회의/강의/영상 시청 시 자동 자막 + 회의록 자동 생성.
구현 방안
- Streaming Transcription: Whisper의 VAD(Voice Activity Detection) 기반 세그먼트 분할
- 오디오를 5~10초 청크로 분할, 이전 컨텍스트를 initialPrompt로 전달
- 침묵 감지(500ms 이상) 시 세그먼트 확정 → 다음 세그먼트 시작
- 오버레이 윈도우: 항상 최상위(alwaysOnTop), 반투명 배경, 화면 하단 고정
- Vanilla JS 팝업 (React 번들 불필요, 빠른 렌더링)
- 최근 3줄 표시, 오래된 줄은 페이드아웃
- 위치/크기 드래그로 조정 가능
- 회의록 저장: 모든 세그먼트를 타임스탬프와 함께 히스토리에 자동 저장
- 세션 종료 시 전체 텍스트를 마크다운으로 내보내기 가능
- 화자 분리(speaker diarization)는 Phase 10+ (Whisper 자체 미지원, 추후 pyannote 등 연동)
필요 서비스
LiveCaptionService(신규): 스트리밍 전사 오케스트레이션AudioCaptureService: 지속 캡처 모드 추가 (기존 세션 모드와 별도)LocalSTTService: 스트리밍 전사 API 추가 (청크 단위 transcribe)WindowManager: LiveCaptionWindow 프리로딩 + 관리
IPC 채널
| 채널 | 방향 | 설명 |
|---|---|---|
caption:start |
handle | 실시간 자막 시작 |
caption:stop |
handle | 실시간 자막 종료 |
caption:getState |
handle | 자막 상태 조회 (active/inactive) |
caption:setPosition |
handle | 오버레이 위치 설정 |
caption:segment |
send | 확정된 자막 세그먼트 (main→renderer) |
caption:delta |
send | 중간 전사 결과 (main→renderer) |
caption:sessionSaved |
send | 회의록 저장 완료 |
UI 컴포넌트
- LiveCaptionWindow (Vanilla JS 팝업): 오버레이 자막 표시
- CaptionControlBar: 트레이 메뉴 또는 Dashboard에 시작/정지 토글
- CaptionHistoryView: 저장된 회의록 열람 (HistoryPage 확장)
우선순위: 1순위 (가장 차별화되는 기능)
10.2 스크린 컨텍스트 (Screen Context)
목표
활성 앱 이름 + 선택된 텍스트를 LLM 프롬프트에 함께 전달하여 컨텍스트 인식 처리. 예: VS Code에서 코드 선택 후 "이거 설명해줘" → 코드+음성 합쳐서 LLM 처리.
구현 방안
-
활성 윈도우 감지: Windows UI Automation API 또는
@electron/windows-utils- 활성 앱 프로세스명, 윈도우 타이틀 가져오기
GetForegroundWindow()+GetWindowText()+GetModuleFileName()
-
선택 텍스트 가져오기: 두 가지 전략
- 클립보드 방식 (안전): Ctrl+C 시뮬레이션 → 클립보드에서 읽기 → 원본 복원
- UI Automation (고급): IUIAutomation의 TextPattern으로 직접 읽기
- 초기에는 클립보드 방식, 추후 UI Automation으로 고도화
-
LLM 프롬프트 주입: VoiceModeService에서 컨텍스트를 시스템 프롬프트에 삽입
[컨텍스트] 활성 앱: Visual Studio Code 활성 파일: src/main/services/VoiceModeService.ts 선택된 텍스트: ```typescript private tryFlushAll(): void { ... }[사용자 음성] 이 함수가 뭐하는 건지 설명해줘
-
앱별 프롬프트 커스텀: 앱 이름에 따라 다른 시스템 프롬프트 적용
- VS Code → "코드 관련 질문입니다"
- Chrome → "웹 페이지 내용 관련 질문입니다"
- 일반 → "텍스트 관련 질문입니다"
필요 서비스
ContextService(신규): 활성 윈도우 + 선택 텍스트 캡처LocalLLMService: 컨텍스트 주입 시스템 프롬프트 확장VoiceModeService: 녹음 시작 시 자동 컨텍스트 캡처ConfigService: 앱별 컨텍스트 설정 저장
IPC 채널
| 채널 | 방향 | 설명 |
|---|---|---|
context:getActiveApp |
handle | 활성 앱 정보 조회 |
context:getSelectedText |
handle | 선택된 텍스트 가져오기 |
context:setAppConfig |
handle | 앱별 컨텍스트 설정 |
context:getAppConfigs |
handle | 앱별 설정 목록 |
UI 컴포넌트
- ContextIndicator: StatusBar에 현재 활성 앱 + 컨텍스트 상태 표시
- ContextSettingsTab: Settings에 앱별 프롬프트 커스텀 UI
- RecordingTip 확장: 컨텍스트 캡처 상태 아이콘 표시
우선순위: 2순위 (실용성 높음, 코드 작업 시 매우 유용)
10.3 음성 메모장 (Voice Memo)
목표
전사 결과를 카테고리별로 자동 정리하는 전용 메모 시스템. 태그, 마크다운 내보내기, 검색, 필터 지원.
구현 방안
- 태그 시스템:
#회의,#아이디어,#할일,#메모등 해시태그 자동 감지- 전사 텍스트에서
#단어패턴 추출 - LLM 자동 태그 제안 (선택적): 텍스트 내용 분석 → 태그 추천
- 수동 태그 추가/편집
- 전사 텍스트에서
- 카테고리 자동 분류: LLM 기반 또는 키워드 기반
- "할 일", "해야 할 것" →
#할일자동 태그 - "아이디어", "생각" →
#아이디어자동 태그
- "할 일", "해야 할 것" →
- 마크다운 내보내기: 태그별/날짜별 그룹핑된 마크다운 파일 생성
# 음성 메모 — 2026-04-05 ## #회의 - 10:30 AM: 프로젝트 킥오프 미팅에서 논의한 내용... - 02:15 PM: 디자인 리뷰 피드백... ## #할일 - 11:00 AM: Phase 10 설계서 작성할 것 - DB 확장: memo 테이블 또는 history 테이블에 태그 컬럼 추가
CREATE TABLE memo_tags ( id TEXT PRIMARY KEY, history_id TEXT NOT NULL REFERENCES history(id), tag TEXT NOT NULL, created_at INTEGER NOT NULL ); CREATE INDEX idx_memo_tags_tag ON memo_tags(tag);
필요 서비스
MemoService(신규): 메모 CRUD + 태그 관리 + 내보내기HistoryService: 태그 연동 확장LocalLLMService: 자동 태그 제안 (선택적)
IPC 채널
| 채널 | 방향 | 설명 |
|---|---|---|
memo:getTags |
handle | 전체 태그 목록 |
memo:setTags |
handle | 히스토리 항목에 태그 설정 |
memo:getByTag |
handle | 태그별 메모 조회 |
memo:export |
handle | 마크다운 내보내기 |
memo:suggestTags |
handle | LLM 기반 태그 자동 제안 |
UI 컴포넌트
- MemoPage: 사이드바에 MEMO 탭 추가, 태그 클라우드 + 메모 목록
- TagEditor: 태그 추가/삭제 인라인 편집 (Chip 기반)
- MemoExportDialog: 내보내기 범위/포맷 선택
우선순위: 3순위 (히스토리 확장, 비교적 단순)
10.4 멀티 LLM 체인 (Multi-LLM Chain)
목표
여러 LLM 명령어를 순차 실행하는 파이프라인 기능. 예: 전사 → 번역 → 요약을 한번의 핫키로 실행.
구현 방안
- 파이프라인 정의: CustomInstruction에 chain 기능 추가
interface InstructionChain { id: string; name: string; steps: ChainStep[]; hotkey?: HotkeyBinding; } interface ChainStep { instructionId: string; // 기존 CustomInstruction ID 참조 inputSource: 'previous' | 'original'; // 이전 단계 결과 or 원본 options?: { targetLanguage?: string; temperature?: number; }; } - 실행 엔진: VoiceModeService에서 체인 실행
- 전사 완료 → 첫 번째 명령어 실행
- 결과 → 두 번째 명령어의 입력으로 전달
- ... → 최종 결과를 텍스트 삽입
- 각 단계 진행 상황을 RecordingTip에 표시
- 중간 취소 가능 (현재 단계 완료 후 중단)
- 파이프라인 에디터: 드래그 앤 드롭으로 단계 구성
- 기존 명령어 목록에서 드래그하여 체인에 추가
- 화살표로 단계 간 연결 시각화
- 테스트 실행: 샘플 텍스트로 체인 전체 실행 결과 미리보기
필요 서비스
ChainExecutionService(신규): 체인 실행 엔진CustomInstructionService: chain 저장/관리 확장LocalLLMService: 순차 호출 + 이전 결과 컨텍스트 전달VoiceModeService: 체인 모드 추가
IPC 채널
| 채널 | 방향 | 설명 |
|---|---|---|
chain:getAll |
handle | 체인 목록 조회 |
chain:create |
handle | 체인 생성 |
chain:update |
handle | 체인 수정 |
chain:delete |
handle | 체인 삭제 |
chain:execute |
handle | 체인 수동 실행 (텍스트 입력) |
chain:progress |
send | 체인 실행 진행 상황 (현재 단계/총 단계) |
UI 컴포넌트
- ChainEditorPage: 파이프라인 에디터 (CommandsPage 확장 또는 별도 탭)
- ChainStepCard: 각 단계 카드 (명령어 이름 + 설정)
- ChainPreview: 체인 실행 결과 미리보기
우선순위: 4순위 (고급 기능, 파워 유저 대상)
10.5 음성 단축키 (Voice Command)
목표
녹음 시작 후 "번역해줘", "요약해줘" 같은 음성 키워드로 명령어를 자동 선택. 핫키 없이 음성만으로 명령어 전환 가능.
구현 방안
- 키워드 매칭: Whisper 전사 결과에서 첫 N초(3초) 또는 첫 문장에서 키워드 탐색
interface VoiceCommand { id: string; keywords: string[]; // ["번역해줘", "번역", "translate"] instructionId: string; // 연결된 CustomInstruction triggerPosition: 'start' | 'end' | 'any'; // 키워드 위치 } // 매칭 로직 function matchVoiceCommand(text: string, commands: VoiceCommand[]): VoiceCommand | null { for (const cmd of commands) { for (const keyword of cmd.keywords) { if (text.startsWith(keyword) || text.includes(keyword)) { return cmd; } } } return null; } - 키워드 제거: 매칭된 키워드를 전사 텍스트에서 제거 후 LLM에 전달
- "이 코드 설명해줘" → 키워드 "설명해줘" 제거 → "이 코드"를 LLM에 전달
- 키워드가 문장 시작/끝에 있을 때만 제거 (중간은 유지)
- 프리셋 키워드: 기본 명령어에 기본 키워드 매핑
- 번역: "번역해줘", "번역", "translate", "영어로"
- 요약: "요약해줘", "요약", "summarize"
- 다듬기: "다듬어줘", "다듬기", "polish"
- 설명: "설명해줘", "explain"
- 커스텀 키워드 등록: Settings에서 명령어별 키워드 편집
필요 서비스
VoiceCommandService(신규): 키워드 매칭 + 명령어 라우팅VoiceModeService: 전사 완료 후 키워드 매칭 → 명령어 자동 선택CustomInstructionService: 명령어별 키워드 저장ConfigService: 음성 단축키 on/off 설정
IPC 채널
| 채널 | 방향 | 설명 |
|---|---|---|
voiceCommand:getAll |
handle | 음성 명령어 목록 |
voiceCommand:setKeywords |
handle | 명령어별 키워드 설정 |
voiceCommand:setEnabled |
handle | 음성 단축키 활성화/비활성화 |
voiceCommand:matched |
send | 키워드 매칭 알림 (어떤 명령어가 선택됐는지) |
UI 컴포넌트
- VoiceCommandSettings: Settings에 음성 단축키 탭 또는 섹션
- KeywordEditor: 명령어별 키워드 목록 편집 (Chip 입력)
- RecordingTip 확장: 키워드 감지 시 선택된 명령어 아이콘 표시
우선순위: 5순위 (UX 개선, 키워드 정확도 검증 필요)
구현 우선순위 요약
| 순위 | 피처 | 난이도 | 임팩트 | 의존성 |
|---|---|---|---|---|
| 1 | 실시간 자막 | 높음 | 매우 높음 | STT 스트리밍 |
| 2 | 스크린 컨텍스트 | 중간 | 높음 | Windows API |
| 3 | 음성 메모장 | 낮음 | 중간 | DB 확장 |
| 4 | 멀티 LLM 체인 | 중간 | 중간 | CustomInstruction 확장 |
| 5 | 음성 단축키 | 낮음 | 중간 | STT 결과 후처리 |
권장 구현 순서
- 10.3 음성 메모장 — 가장 단순, 기존 인프라 활용도 높음
- 10.5 음성 단축키 — 키워드 매칭만 추가, VoiceModeService 확장
- 10.2 스크린 컨텍스트 — Windows API 연동 필요하지만 기존 패턴 재사용
- 10.4 멀티 LLM 체인 — 파이프라인 에디터 UI가 복잡
- 10.1 실시간 자막 — 스트리밍 전사 + 오버레이 윈도우 = 가장 큰 작업량
Speakly 대비 차별점
| 기능 | Speakly | D3RO-VOICE |
|---|---|---|
| 실시간 자막 | X | Phase 10.1 |
| 스크린 컨텍스트 | 부분 (활성 앱명만) | Phase 10.2 (선택 텍스트 포함) |
| 음성 메모장 | X | Phase 10.3 |
| 멀티 LLM 체인 | X | Phase 10.4 |
| 음성 단축키 | X | Phase 10.5 |
| 완전 로컬 | X (클라우드 의존) | O (Ollama + Whisper) |
| 커서 히스토리 팝업 | X | Phase 3.5 (이미 완료) |
| Ctrl+Shift+C 커맨드 팝업 | X | Phase 9 (이미 완료) |