Speaker Identity Source Map
이 문서는 화자 분리/인식 PoC의 실제 소스와 Cloud A2A 연결 지점을 파일 단위로 정리한다. 목적은 “아이디어 설명”이 아니라, 어느 파일이 어떤 계약을 만들고 어떤 서비스 계층으로 확장될 수 있는지 추적하는 것이다.
1. 온디바이스 소스 경계
| 파일 | 책임 | 현재 산출물 | 확장 포인트 |
|---|---|---|---|
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. 온디바이스 처리 흐름
처리 흐름:
- 사용자가 현재 PoC 화자 등록 UI에서 nickname으로 녹음한다.
- 등록 WAV가
registerSpeakerFromWavPaths()로 들어간다. computeEmbeddingFromWav()가 WAV를 16kHz PCM으로 파싱한다.SpeakerEmbeddingExtractor가 임베딩을 만든다.SpeakerEmbeddingManager와registeredEmbeddings가 화자별 임베딩을 보관한다.- 런타임 발화는
DiarizationEngine으로 화자 구간을 분리한다. - 각 구간 또는 전체 발화에서 임베딩을 추출해 등록 화자와 비교한다.
SpeakerStabilityFeature가 직전/최근 화자 보정을 적용한다.- 임계값과 다화자 정책을 통과하면 로컬 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 소스 경계
| 파일 | 책임 | 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. 소스 기반 계약 후보
온디바이스에서 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로 보내지 말아야 할 항목:
- WAV/PCM 파일
- 원본 음성 파일 경로
- 학습용 음성 샘플
- 민감한 개인 프로필 원문
등록 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 조회 |