← Docs hub

Speaker Identity Source Map

이 문서는 화자 분리/인식 PoC의 실제 소스와 Cloud A2A 연결 지점을 파일 단위로 정리한다. 목적은 “아이디어 설명”이 아니라, 어느 파일이 어떤 계약을 만들고 어떤 서비스 계층으로 확장될 수 있는지 추적하는 것이다.

Source Map Overview

1. 온디바이스 소스 경계

On-device Source Boundary

파일 책임 현재 산출물 확장 포인트
service/module/SpeakerIdentificationEngine.kt CPU 화자 임베딩 추출/등록/검색 SearchResult(name, score) Voice ID index, profile version
service/module/DiarizationEngine.kt CPU 화자 구간 분리 DiarizationSegment(startSec, endSec, speakerId) speaker count, overlap, dominant speaker
SpeakerStabilityFeature.kt 세션 기반 score 보정 boosted score multi-turn speaker continuity
SpeakerListActivity.kt 등록 화자 목록/기록 진입 speaker list 사용자별 설정/삭제 UI
SpeakerHistoryActivity.kt 화자별 대화 기록 조회 history.txt 표시 short-term memory viewer
docs/SPEAKER_THRESHOLDS.md 차단/재시도 조건 임계값 정책 runtime policy table
strings.xml 화자 관련 안내 문구 retry/overlap/too many TTS 다국어 사용자 안내

현재 구현은 PoC 성격이 강하다. SpeakerVoiceProfile.kt는 nickname을 정제해 voiceId로 사용하고, SpeakerTurnAnalyzer는 로컬 WAV가 있어야 CPU 엔진을 초기화한다. 임베딩 검색은 메모리 기반이며 UI는 filesDir/speaker_id/{voiceId}를 직접 본다. 제품화하려면 nickname과 독립적인 OnDevice Voice ID, 암호화 template repository, metadata Outbox를 분리해야 한다.

2. 온디바이스 처리 흐름

On-device Runtime Source Flow

처리 흐름:

  1. 사용자가 현재 PoC 화자 등록 UI에서 nickname으로 녹음한다.
  2. 등록 WAV가 registerSpeakerFromWavPaths()로 들어간다.
  3. computeEmbeddingFromWav()가 WAV를 16kHz PCM으로 파싱한다.
  4. SpeakerEmbeddingExtractor가 임베딩을 만든다.
  5. SpeakerEmbeddingManager와 registeredEmbeddings가 화자별 임베딩을 보관한다.
  6. 런타임 발화는 DiarizationEngine으로 화자 구간을 분리한다.
  7. 각 구간 또는 전체 발화에서 임베딩을 추출해 등록 화자와 비교한다.
  8. SpeakerStabilityFeature가 직전/최근 화자 보정을 적용한다.
  9. 임계값과 다화자 정책을 통과하면 로컬 Voice ID 기반 speaker_context 후보가 된다.

이 흐름은 현재 1회 녹음 PoC다. Figma 제품 사양의 3문장 x 5세트, 품질 gate, OnDevice Voice ID 발급, Cloud Voice ID/Reference Embedding sync는 아직 구현되지 않았다.

목표 데이터 경계의 직접 근거는 C:\securedir\화자인식\VoiceProfile_Architecture_EmailSafe.pptx 3페이지다. 이 그림은 등록 시 Voice ID + Reference Embedding을 Cloud Registry에 동기화하고, 런타임 매칭과 신뢰도 정책은 On-device에서 수행하도록 정의한다.

3. Cloud A2A 소스 경계

Cloud A2A Source Boundary

파일 책임 speaker context 연결 방식
gemini/a2a/runtime/session_state.py voice_context 기본화, owner selection, active agent/skill, slot state speaker_context 기본값 후보
gemini/a2a/runtime/memory_context.py memory snapshot 정규화, memory update 후보 생성 speaker별 short-term pair/profile candidate 분리 후보
gemini/a2a/runtime/orchestrator.py router 호출, route 실행, orchestration 응답 생성 speaker gate 결과를 agent activity/session_state에 포함 후보
gemini/a2a/runtime/task_manager.py multi-step plan 실행, device_task_requests 생성 side-effect task의 speaker confidence/authority gate 후보
gemini/a2a/planner/main_router_api.py route/skill/step planning speaker context를 prompt evidence로 반영 후보
gemini/a2a/planner/preclassifier.py lightweight route hint speaker state 기반 STT_NULL/clarify 보조 후보

현재 Cloud 코드에는 Voice Sync Registry, Voice ID resolve와 speaker_context 제품 계약이 구현되어 있지 않다. 목표 책임은 OnDevice evidence를 받고 Voice ID로 사용자 정보를 조회하는 것이다.

4. 소스 기반 계약 후보

Contract Candidate From Sources

온디바이스에서 Cloud로 넘길 최소 필드:

{
  "speaker_context": {
    "contract_version": "speaker-context-v2",
    "voice_id": "vp_opaque_uuid",
    "speaker_confidence": 0.72,
    "speaker_state": "identified",
    "speaker_count": 1,
    "overlap_ratio": 0.0,
    "unknown_ratio": 0.0,
    "max_score": 0.72,
    "model_version": "speaker-model-version",
    "profile_version": 1
  }
}

온디바이스 내부 데이터 중 Cloud로 보내지 말아야 할 항목:

등록 Reference Embedding은 Voice Sync Registry에 동기화하는 예외다. 런타임 Query Embedding은 PPT 호환 입력에 포함될 수 있으나 Cloud 조회·매칭·저장에는 사용하지 않는다. person_id, 표시명, 개인화 동의, 권한은 Cloud lookup 결과로만 만든다.

5. 현재 구현과 제품화 간극

항목 현재 제품화 필요 조건
화자 등록 수동 1회 WAV 등록 5세트/품질/취소/복구 상태 머신
임베딩 저장 in-memory 암호화 저장, 로드, 삭제, 백업 제외
화자 기록 history.txt UI 조회 DB schema, speaker_id 외래키, retention 정책
다화자 차단 문서화된 임계값 runtime 적용 위치와 테스트
Voice ID nickname 정제 문자열 OnDevice opaque ID generator
Cloud 연결 구현 없음 Voice ID/Reference Embedding sync/delete/resolve API
A2A 소비 구현 없음 speaker_context-v2 → person_context 조회

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date