Speaker Identity Source Map
이 문서는 화자 분리/인식 PoC의 실제 소스와 Cloud A2A 연결 지점을 파일 단위로 정리한다. 목적은 “아이디어 설명”이 아니라, 어느 파일이 어떤 계약을 만들고 어떤 서비스 계층으로 확장될 수 있는지 추적하는 것이다.
1. 온디바이스 소스 경계
| 파일 | 책임 | 현재 산출물 | 확장 포인트 |
|---|---|---|---|
SpeakerIdentificationEngine.kt |
화자 임베딩 추출/등록/검색 | SearchResult(name, score) |
speaker confidence, accepted/unknown, profile scope |
DiarizationEngine.kt |
화자 구간 분리 | 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 성격이 강하다. 특히 임베딩 저장은 registeredEmbeddings in-memory 구조이고, UI는 filesDir/speaker_id/{speakerName} 기반의 기록 조회를 갖는다. 제품화하려면 embedding/profile/history의 저장소와 삭제 정책을 분리해야 한다.
2. 온디바이스 처리 흐름
처리 흐름:
- 사용자가 화자 등록 UI에서 같은 이름으로 여러 번 녹음한다.
- 등록 WAV가
registerSpeakerFromWavPaths()로 들어간다. computeEmbeddingFromWav()가 WAV를 16kHz PCM으로 파싱한다.SpeakerEmbeddingExtractor가 임베딩을 만든다.SpeakerEmbeddingManager와registeredEmbeddings가 화자별 임베딩을 보관한다.- 런타임 발화는
DiarizationEngine으로 화자 구간을 분리한다. - 각 구간 또는 전체 발화에서 임베딩을 추출해 등록 화자와 비교한다.
SpeakerStabilityFeature가 직전/최근 화자 보정을 적용한다.- 임계값과 다화자 정책을 통과하면
speaker_context후보가 된다.
3. Cloud A2A 소스 경계
| 파일 | 책임 | speaker context 연결 방식 |
|---|---|---|
gemini/a2a/runtime/session_state.py |
voice_context 기본화, owner selection, active agent/skill, slot state |
speaker_context 기본값/owner speaker propagation 후보 |
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는 음성 자체를 분석하지 않는다. Cloud의 책임은 온디바이스가 계산한 speaker evidence를 정책적으로 소비하는 것이다.
4. 소스 기반 계약 후보
온디바이스에서 Cloud로 넘길 최소 필드:
{
"speaker_context": {
"contract_version": "speaker-context-v1",
"speaker_id": "user_001",
"display_name": "아빠",
"speaker_confidence": 0.72,
"speaker_state": "identified",
"speaker_count": 1,
"overlap_ratio": 0.0,
"unknown_ratio": 0.0,
"max_score": 0.72,
"safety_gate": "pass",
"personalization_allowed": true,
"authority_level": "normal"
}
}
온디바이스 내부 raw data 중 Cloud로 보내지 말아야 할 항목:
- raw embedding vector
- WAV/PCM 파일
- 원본 음성 파일 경로
- 학습용 음성 샘플
- 민감한 개인 프로필 원문
Cloud로 보내도 되는 항목은 “판단 결과와 score” 중심이어야 한다.
5. 현재 구현과 제품화 간극
| 항목 | 현재 | 제품화 필요 조건 |
|---|---|---|
| 화자 등록 | WAV path 기반 등록 함수 | UI 녹음 저장/검증/재등록/삭제 UX |
| 임베딩 저장 | in-memory | 암호화 저장, 로드, 삭제, 백업 제외 |
| 화자 기록 | history.txt UI 조회 |
DB schema, speaker_id 외래키, retention 정책 |
| 다화자 차단 | 문서화된 임계값 | runtime 적용 위치와 테스트 |
| Cloud 전달 | 아직 표준 계약 없음 | speaker_context 필드 확정 |
| A2A 소비 | voice_context 확장 가능 | planner/memory/task manager 정책 반영 |