Files
TrueGrowth/docs/features/sora-character-feature.md

385 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sora-2 角色创建功能开发计划
## 功能概述
为 Sora-2 视频模型添加角色创建和复用功能,用户可以从已完成的视频任务中提取角色,并在后续视频生成中通过 `@username` 方式引用该角色。
## API 接口说明
### 1. 创建角色接口
- **URL**: `POST https://api.tu-zi.com/v1/videos`
- **Content-Type**: `multipart/form-data`
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `character_from_task` | string | 是 | 源视频任务ID格式: `sora-2:task_xxx` |
| `model` | string | 是 | 固定值: `sora-2-character` |
| `character_timestamps` | string | 否 | 时间范围,格式: `start,end`差值需在1-3秒内 |
**响应示例**:
```json
{
"id": "sora-2-character:ch_6944ed3a51888191bd1ac40c763620fb"
}
```
### 2. 查询角色接口
- **URL**: `GET https://api.tu-zi.com/v1/videos/{id}`
- **认证**: Bearer Token
**响应示例**:
```json
{
"id": "sora-2-character:ch_6944ed3a51888191bd1ac40c763620fb",
"username": "xscjkajd.lunaradian",
"permalink": "https://sora.chatgpt.com/profile/xscjkajd.lunaradian",
"profile_picture_url": "https://filesystem.site/cdn/xxx.jpg"
}
```
## 开发任务清单
### 阶段一:基础架构(预计 2-3 天)
#### Task 1: 创建角色类型定义
- **文件**: `packages/drawnix/src/types/character.types.ts`
- **内容**:
- `SoraCharacter` 接口(角色完整信息)
- `CharacterStatus` 枚举pending/processing/completed/failed
- `CreateCharacterParams` 接口(创建参数)
- `CharacterQueryResponse` 接口(查询响应)
#### Task 2: 实现角色 API 服务
- **文件**: `packages/drawnix/src/services/character-api-service.ts`
- **功能**:
- `createCharacter()` - 提交角色创建请求
- `queryCharacter()` - 查询角色状态
- `createCharacterWithPolling()` - 创建并轮询直到完成
- **依赖**: Task 1
#### Task 3: 实现角色存储服务
- **文件**: `packages/drawnix/src/services/character-storage-service.ts`
- **功能**:
- IndexedDB 存储(使用 localforage
- `saveCharacter()` - 保存角色
- `getCharacters()` - 获取所有角色
- `getCharacterById()` - 按ID获取
- `deleteCharacter()` - 删除角色
- `updateCharacter()` - 更新角色状态
- **存储键**: `sora-characters`
- **依赖**: Task 1
#### Task 4: 创建角色状态管理 Hook
- **文件**: `packages/drawnix/src/hooks/useCharacters.ts`
- **功能**:
- 角色列表状态管理RxJS BehaviorSubject
- `characters` - 角色列表
- `pendingCharacters` - 处理中的角色
- `createCharacter()` - 创建角色(带状态更新)
- `deleteCharacter()` - 删除角色
- `refreshCharacters()` - 刷新列表
- **依赖**: Task 2, Task 3
### 阶段二UI 组件(预计 2-3 天)
#### Task 5: 实现角色创建对话框
- **文件**: `packages/drawnix/src/components/character/CharacterCreateDialog.tsx`
- **功能**:
- 显示源视频信息
- 时间范围选择器(滑块或输入框)
- 时间约束验证1-3秒
- 提交/取消按钮
- 创建中状态显示
- **UI**: 使用 TDesign Dialog + Slider/InputNumber
- **依赖**: Task 4
#### Task 6: 在 TaskItem 中添加「提取角色」按钮
- **文件**: `packages/drawnix/src/components/task-queue/TaskItem.tsx`
- **修改**:
- 添加「提取角色」按钮(仅对 sora-2 已完成任务显示)
- 添加 `onExtractCharacter` 回调
- 按钮条件判断逻辑
- **依赖**: Task 5
#### Task 7: 实现角色卡片组件
- **文件**: `packages/drawnix/src/components/character/CharacterCard.tsx`
- **功能**:
- 显示头像profile_picture_url
- 显示 @username
- 复制按钮(复制 @username
- 删除按钮
- 处理中状态loading
- **样式**: `character.scss`
- **依赖**: Task 1
#### Task 8: 实现角色列表/选择器组件
- **文件**: `packages/drawnix/src/components/character/CharacterList.tsx`
- **功能**:
- 显示所有已创建的角色
- 支持选择角色(用于插入提示词)
- 空状态提示
- 可选:搜索过滤
- **依赖**: Task 4, Task 7
### 阶段三:提示词集成(预计 1-2 天)
#### Task 9: 在 PromptInput 中集成 @ 提及功能
- **文件**: `packages/drawnix/src/components/ttd-dialog/shared/PromptInput.tsx`
- **修改**:
- 监听 `@` 输入
- 弹出角色选择器Popup/Dropdown
- 选择后插入 `@username`
- 支持键盘导航(上下选择,回车确认)
- **新文件**: `CharacterMentionPopup.tsx`
- **依赖**: Task 4, Task 8
### 阶段四:状态同步与优化(预计 1 天)
#### Task 10: 页面刷新恢复
- 从 IndexedDB 恢复角色列表
- 恢复处理中的角色创建任务
- 继续轮询未完成的角色
#### Task 11: 错误处理与用户反馈
- API 错误提示(网络错误、超时、服务器错误)
- 角色创建失败处理
- 重试机制
## 文件结构
```
packages/drawnix/src/
├── types/
│ └── character.types.ts # 角色类型定义
├── services/
│ ├── character-api-service.ts # 角色 API 服务
│ └── character-storage-service.ts # 角色存储服务
├── hooks/
│ └── useCharacters.ts # 角色状态管理 Hook
├── components/
│ ├── character/
│ │ ├── index.ts
│ │ ├── CharacterCreateDialog.tsx
│ │ ├── CharacterCard.tsx
│ │ ├── CharacterList.tsx
│ │ ├── CharacterMentionPopup.tsx
│ │ └── character.scss
│ └── task-queue/
│ └── TaskItem.tsx # 修改:添加提取角色按钮
└── components/ttd-dialog/shared/
└── PromptInput.tsx # 修改:添加 @ 提及功能
```
## 数据流
```
┌─────────────────────────────────────────────────────────────────┐
│ 用户交互流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 用户点击「提取角色」 │
│ │ │
│ ▼ │
│ 2. CharacterCreateDialog 弹出 │
│ │ │
│ ▼ │
│ 3. 用户选择时间范围 → 点击创建 │
│ │ │
│ ▼ │
│ 4. useCharacters.createCharacter() │
│ │ │
│ ├──► characterApiService.createCharacter() │
│ │ │ │
│ │ ▼ │
│ │ POST /v1/videos (character_from_task, model) │
│ │ │ │
│ │ ▼ │
│ │ 返回 character_id │
│ │ │
│ ├──► characterStorageService.saveCharacter(pending) │
│ │ │
│ └──► 开始轮询 queryCharacter() │
│ │ │
│ ▼ │
│ GET /v1/videos/{id} │
│ │ │
│ ▼ │
│ 返回 username, profile_picture_url │
│ │ │
│ ▼ │
│ 5. characterStorageService.updateCharacter(completed) │
│ │ │
│ ▼ │
│ 6. UI 更新显示角色卡片 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
## UI 设计参考
### 1. 提取角色按钮位置
```
┌─────────────────────────────────────────────────────────────────┐
│ TaskItem (sora-2 已完成任务) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 🎬 [prompt text...] │
│ │
│ sora-2 | 10秒 | 1920x1080 | ✅ 已完成 │
│ │
│ [预览图] │
│ │
│ [删除] [下载] [插入] [缓存] [编辑] [👤 提取角色] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 2. 角色创建对话框
```
┌─────────────────────────────────────────────────────────────────┐
│ 提取角色 [X] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 从视频中提取角色,创建后可在后续视频中通过 @username 引用 │
│ │
│ 源视频: 一只白色的猫在花园里玩耍... │
│ 任务ID: sora-2:task_01kbh21pg... │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ 时间范围 (角色在视频中出现的位置) │
│ │
│ 开始时间: [0 ] 秒 结束时间: [3 ] 秒 │
│ │
│ ⓘ 时间范围需在 1-3 秒之间 │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ [取消] [创建角色] │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 3. 角色卡片
```
┌──────────────────────────────────┐
│ ┌────────┐ │
│ │ 头像 │ @xscjkajd.lunar... │
│ │ 64x64 │ │
│ └────────┘ [📋 复制] [🗑 删除] │
│ │
│ 来源: 白猫视频任务 │
│ 创建于: 2024-01-15 14:30 │
└──────────────────────────────────┘
```
### 4. @ 提及弹窗
```
提示词输入框:
┌─────────────────────────────────────────────────────────────────┐
│ 一只猫在追逐 @| │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────┐
│ 📷 @xscjkajd.lunaradian │ ← 选中
│ 📷 @abc123.character │
│ ─────────────────────────────── │
│ + 从视频提取新角色... │
└─────────────────────────────────┘
```
## 技术要点
### 1. 模型判断逻辑
```typescript
// 判断是否可以提取角色
const canExtractCharacter = (task: Task): boolean => {
return (
task.status === TaskStatus.COMPLETED &&
task.type === TaskType.VIDEO &&
task.remoteId?.startsWith('sora-2:') &&
['sora-2', 'sora-2-pro'].includes(task.params.model || '')
);
};
```
### 2. 时间范围验证
```typescript
const validateTimestamps = (start: number, end: number, videoDuration: number): boolean => {
const duration = end - start;
return (
start >= 0 &&
end <= videoDuration &&
duration >= 1 &&
duration <= 3
);
};
```
### 3. IndexedDB 存储结构
```typescript
// 存储键: 'sora-characters'
// 数据结构: SoraCharacter[]
{
id: 'sora-2-character:ch_xxx',
username: 'xscjkajd.lunaradian',
profilePictureUrl: 'https://...',
permalink: 'https://...',
sourceTaskId: 'local-task-uuid',
sourceVideoId: 'sora-2:task_xxx',
characterTimestamps: '0,3',
status: 'completed',
createdAt: 1705312200000,
completedAt: 1705312260000,
}
```
## 测试要点
1. **API 集成测试**
- 角色创建请求格式正确
- 轮询查询正常工作
- 错误响应处理
2. **UI 交互测试**
- 提取角色按钮仅对符合条件的任务显示
- 时间范围选择器约束正确
- 角色创建状态实时更新
- @ 提及弹窗正确显示和选择
3. **数据持久化测试**
- 刷新页面后角色列表恢复
- 角色删除后正确移除
- 处理中任务恢复轮询
## 开发顺序建议
```
Week 1:
├── Day 1-2: Task 1-3 (类型定义 + API服务 + 存储服务)
├── Day 3: Task 4 (状态管理 Hook)
└── Day 4-5: Task 5-6 (创建对话框 + TaskItem按钮)
Week 2:
├── Day 1-2: Task 7-8 (角色卡片 + 列表组件)
├── Day 3-4: Task 9 (@ 提及功能)
└── Day 5: Task 10-11 (状态同步 + 错误处理)
```
## 后续扩展
1. **角色库面板** - 独立的角色管理界面
2. **角色分组/标签** - 组织和筛选角色
3. **角色使用统计** - 追踪角色使用频率
4. **批量导出** - 导出角色数据备份
5. **角色分享** - 跨设备同步角色(需后端支持)