# 人物身份整合功能使用指南

## 概述

该功能通过整合人脸识别（Face Recognition）和声纹识别（ASRX Speaker Diarization），在视频块（Chunk）中自动标注人物身份。

## 快速开始

### 1. 处理视频

首先需要处理视频以提取人脸和声纹信息：

```bash
# 处理视频，提取所有特征
cargo run -- process /path/to/video.mp4 --modules face,asrx

# 或者使用 playground 进行测试
cargo run --bin momentry_playground -- process /path/to/video.mp4 --modules face,asrx
```

这将生成：
- `face.json` - 人脸检测结果
- `asrx.json` - 说话人分离结果

### 2. 自动识别人物身份

使用 API 自动匹配人脸和声纹：

```bash
curl -X POST http://localhost:3002/api/v1/person/identify \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_api_key" \
  -d '{
    "file_uuid": "your_file_uuid",
    "auto_match": true,
    "match_threshold": 0.5
  }'
```

响应示例：

```json
{
  "success": true,
  "message": "Identified 3 persons",
  "persons": [
    {
      "person_id": "person_abc123",
      "speaker_id": "SPEAKER_00",
      "confidence": 0.85,
      "appearance_count": 15,
      "total_appearance_duration": 120.5
    }
  ]
}
```

### 3. 查询人物时间轴

查询某个人物在视频中的出场时间：

```bash
curl -X GET "http://localhost:3002/api/v1/person/person_abc123/timeline?file_uuid=your_file_uuid" \
  -H "X-API-Key: your_api_key"
```

响应示例：

```json
{
  "person_id": "person_abc123",
  "name": "张三",
  "timeline": [
    {
      "start_time": 10.5,
      "end_time": 25.3,
      "duration": 14.8,
      "confidence": 0.92
    }
  ],
  "statistics": {
    "total_appearances": 15,
    "total_duration": 120.5,
    "first_appearance": 10.5,
    "last_appearance": 350.2,
    "average_confidence": 0.88
  }
}
```

### 4. 手动标注人物姓名

为识别的人物添加姓名：

```bash
curl -X PATCH http://localhost:3002/api/v1/person/person_abc123 \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_api_key" \
  -d '{
    "name": "张三",
    "metadata": {
      "role": "主持人",
      "department": "新闻部"
    },
    "is_confirmed": true
  }'
```

### 5. 查询 Chunk 中的人物

查看某个视频块中出现的人物：

```bash
curl -X GET http://localhost:3002/api/v1/chunks/sentence_0012/persons \
  -H "X-API-Key: your_api_key"
```

响应示例：

```json
{
  "success": true,
  "chunk_id": "sentence_0012",
  "persons": [
    {
      "person_id": "person_abc123",
      "name": "张三",
      "confidence": 0.85,
      "overlap_duration": 3.5
    }
  ]
}
```

## API 端点总结

| 端点 | 方法 | 描述 |
|------|------|------|
| `/api/v1/person/identify` | POST | 自动识别人物身份 |
| `/api/v1/person/:person_id` | GET | 获取人物详情 |
| `/api/v1/person/:person_id` | PATCH | 更新人物信息 |
| `/api/v1/person/:person_id/timeline` | GET | 查询人物时间轴 |
| `/api/v1/person/:person_id/appearances` | GET | 查询人物出场记录 |
| `/api/v1/chunks/:chunk_id/persons` | GET | 查询 Chunk 中的人物 |

## 数据库表结构

### person_identities（人物身份表）

| 字段 | 类型 | 描述 |
|------|------|------|
| person_id | VARCHAR(255) | 人物唯一标识 |
| face_identity_id | INTEGER | 关联的人脸身份 ID |
| speaker_id | VARCHAR(64) | 说话人 ID（SPEAKER_00, SPEAKER_01...） |
| file_uuid | VARCHAR(255) | 来源视频 UUID |
| name | VARCHAR(255) | 人物姓名（手动标注） |
| confidence | DOUBLE PRECISION | 关联置信度 |
| appearance_count | INTEGER | 出场次数 |
| total_appearance_duration | DOUBLE PRECISION | 总出场时长（秒） |
| is_confirmed | BOOLEAN | 是否已确认 |

### person_appearances（人物出场记录表）

| 字段 | 类型 | 描述 |
|------|------|------|
| person_id | VARCHAR(255) | 关联的人物身份 ID |
| file_uuid | VARCHAR(255) | 视频 UUID |
| start_time | DOUBLE PRECISION | 开始时间（秒） |
| end_time | DOUBLE PRECISION | 结束时间（秒） |
| duration | DOUBLE PRECISION | 持续时间（秒） |
| face_detection_id | INTEGER | 关联的人脸检测 ID |
| confidence | DOUBLE PRECISION | 置信度 |

## 工作流程

### 完整处理流程

```
1. 视频上传
   ↓
2. 并行处理
   ├─ Face Detection → face_detections
   ├─ ASRX Processing → speaker_id
   └─ Chunk Generation → chunks
   ↓
3. 自动匹配
   ├─ 时间重叠分析
   ├─ Face ID + Speaker ID → Person Identity
   └─ 创建 person_identities 和 person_appearances
   ↓
4. 更新 Chunks
   └─ 在 metadata 中添加人物信息
   ↓
5. 查询和使用
   ├─ 时间轴查询
   ├─ 人物搜索
   └─ Chunk 标注
```

### 匹配算法

核心匹配算法基于**时间重叠**：

1. 对于每个人脸检测，找到时间重叠的 ASRX 片段
2. 计算重叠比例 = overlap_duration / segment_duration
3. 如果 overlap_ratio >= threshold，则创建匹配
4. 按匹配数量和置信度聚类，形成人物身份

## 配置参数

### 匹配阈值

```rust
// 默认匹配阈值
const DEFAULT_MATCH_THRESHOLD: f64 = 0.5;

// 最小置信度
const MIN_CONFIDENCE: f64 = 0.6;
```

### 数据库索引

系统自动创建以下索引以优化查询性能：

```sql
-- 时间范围查询
CREATE INDEX idx_person_appearances_time 
ON person_appearances(file_uuid, start_time, end_time);

-- 人物查询
CREATE INDEX idx_person_identities_file_uuid 
ON person_identities(file_uuid);

-- 说话人查询
CREATE INDEX idx_person_identities_speaker 
ON person_identities(speaker_id);
```

## 最佳实践

### 1. 视频处理顺序

```bash
# 推荐：先处理基础特征，再识别人物
cargo run -- process video.mp4 --modules asr,asrx,face
```

### 2. 批量处理

```bash
# 批量处理多个视频
for video in /path/to/videos/*.mp4; do
  cargo run -- process "$video" --modules asr,asrx,face
  
  # 获取 UUID
  uuid=$(basename "$video" .mp4)
  
  # 自动识别人物
  curl -X POST http://localhost:3002/api/v1/person/identify \
    -H "Content-Type: application/json" \
    -H "X-API-Key: your_api_key" \
    -d "{\"file_uuid\": \"$uuid\", \"auto_match\": true}"
done
```

### 3. 人物标注工作流

```bash
# 1. 列出未确认的人物
curl -X GET "http://localhost:3002/api/v1/person/list?is_confirmed=false"

# 2. 查看人物出场片段
curl -X GET "http://localhost:3002/api/v1/person/person_xxx/timeline"

# 3. 确认并标注姓名
curl -X PATCH http://localhost:3002/api/v1/person/person_xxx \
  -H "Content-Type: application/json" \
  -d '{"name": "张三", "is_confirmed": true}'
```

## 故障排查

### 问题 1：匹配数量过低

**原因**：匹配阈值过高

**解决**：降低阈值到 0.3-0.5

```bash
curl -X POST http://localhost:3002/api/v1/person/identify \
  -H "Content-Type: application/json" \
  -d '{"file_uuid": "xxx", "match_threshold": 0.3}'
```

### 问题 2：人物身份重复

**原因**：同一人物被识别为多个身份

**解决**：使用 merge API 合并

```sql
-- 直接在数据库中合并
SELECT merge_person_identities(
  'person_target',
  ARRAY['person_source1', 'person_source2']
);
```

### 问题 3：时间轴查询慢

**原因**：缺少索引或数据量大

**解决**：
1. 确认索引已创建：`\d person_appearances`
2. 使用 EXPLAIN 分析查询
3. 考虑分区表（按 file_uuid）

## 性能优化

### 1. 批量插入

```rust
// 使用事务批量插入出场记录
pub async fn batch_insert_appearances(
    db: &PostgresDb,
    appearances: &[PersonAppearance],
) -> Result<()> {
    let mut tx = db.pool().begin().await?;
    
    for appearance in appearances {
        sqlx::query("INSERT INTO ...")
            .bind(...)
            .execute(&mut *tx)
            .await?;
    }
    
    tx.commit().await?;
    Ok(())
}
```

### 2. 缓存策略

```rust
// 使用 Redis 缓存时间轴查询
let cache_key = format!("person_timeline:{}:{}", file_uuid, person_id);

if let Some(cached) = redis.get(&cache_key).await? {
    return Ok(serde_json::from_str(&cached)?);
}

// 查询数据库并缓存
let timeline = query_from_db().await?;
redis.set_ex(&cache_key, &serde_json::to_string(&timeline)?, 300).await?;
```

## 监控指标

```rust
// Prometheus 指标
lazy_static! {
    static ref PERSON_IDENTITIES_CREATED: Counter = 
        register_counter!("person_identities_created_total").unwrap();
    
    static ref PERSON_MATCH_CONFIDENCE: Histogram = 
        register_histogram!("person_match_confidence").unwrap();
}
```

## 未来扩展

### 1. 多模态融合

- 结合 OCR（字幕、名牌）
- 结合场景分类
- 结合姿态识别

### 2. 跨视频追踪

- 全局人物身份库
- 人脸嵌入相似度匹配
- 服装特征识别

### 3. 实时处理

- 流式视频处理
- 实时人物识别
- WebSocket 推送更新

## 参考资料

- [InsightFace Documentation](https://github.com/deepinsight/insightface)
- [WhisperX Speaker Diarization](https://github.com/m-bain/whisperX)
- [PostgreSQL pgvector](https://github.com/pgvector/pgvector)
- [完整架构设计文档](./PERSON_IDENTITY_INTEGRATION.md)
