478 lines
16 KiB
Markdown
478 lines
16 KiB
Markdown
# Piano Highlight Generator App - 任务拆解
|
||
|
||
> 创建日期:2026-05-02
|
||
> 基于:design.md
|
||
|
||
---
|
||
|
||
## 任务总览
|
||
|
||
| # | 任务 | 依赖 | 优先级 | 工期 |
|
||
|---|------|------|--------|------|
|
||
| 1 | 项目骨架搭建 | - | P0 | 1h |
|
||
| 2 | ConfigPanel 配置面板 | 1 | P0 | 1h |
|
||
| 3 | StateManager 状态管理 | 1 | P0 | 0.5h |
|
||
| 4 | ProgressView 进度视图 | 1 | P0 | 1h |
|
||
| 5 | Worker 后台线程 | 1 | P0 | 1h |
|
||
| 6 | PipelineController 流水线控制 | 3, 5 | P0 | 1.5h |
|
||
| 7 | TitleEditor 标题编辑器 | 6 | P1 | 1.5h |
|
||
| 8 | 主窗口集成 | 2, 4, 7 | P0 | 1h |
|
||
| 9 | 核心模块适配 | 1 | P0 | 0.5h |
|
||
| 10 | 错误处理完善 | 8 | P2 | 1h |
|
||
| 11 | 打包配置 + 测试 | 10 | P2 | 1.5h |
|
||
| 12 | 文档和 README | 11 | P3 | 0.5h |
|
||
|
||
---
|
||
|
||
## 任务 1: 项目骨架搭建
|
||
|
||
**文件**:
|
||
- `src/__init__.py`
|
||
- `src/main.py` - 应用入口
|
||
- `src/app.py` - QMainWindow 主窗口
|
||
- `src/gui/__init__.py`
|
||
- `src/logic/__init__.py`
|
||
- `src/core/__init__.py`
|
||
- `requirements.txt`
|
||
- `pyproject.toml`
|
||
|
||
**内容**:
|
||
- 创建目录结构
|
||
- 创建空的 `__init__.py`
|
||
- `main.py` 使用 QApplication 启动
|
||
- `app.py` 创建空的主窗口框架
|
||
- `requirements.txt` 包含所有依赖
|
||
- 配置 pyproject.toml
|
||
|
||
**验收标准**:
|
||
- 运行 `python src/main.py` 能启动空窗口
|
||
- 窗口标题为 "Piano Highlight Generator"
|
||
|
||
---
|
||
|
||
## 任务 2: ConfigPanel 配置面板
|
||
|
||
**文件**:`src/gui/config_panel.py`
|
||
|
||
**UI 组件**:
|
||
```
|
||
┌─────────────────────────────────────────────┐
|
||
│ API 配置 │
|
||
│ API Host: [________________________] │
|
||
│ API Key: [________________________] │
|
||
│ 模型: [火山方舟 Ark v] │
|
||
├─────────────────────────────────────────────┤
|
||
│ 视频配置 │
|
||
│ 视频文件: [________________] [浏览...] │
|
||
│ 输出目录: [________________] [浏览...] │
|
||
├─────────────────────────────────────────────┤
|
||
│ Whisper 配置 │
|
||
│ 模型: [large v] │
|
||
│ 模型路径: [________________] [浏览...] │
|
||
├─────────────────────────────────────────────┤
|
||
│ [开始处理] [保存配置] │
|
||
└─────────────────────────────────────────────┘
|
||
```
|
||
|
||
**信号**:
|
||
- `config_changed_signal(dict)` - 配置变更时发出
|
||
|
||
**方法**:
|
||
- `load_config(config: dict)` - 加载配置到 UI
|
||
- `get_config() -> dict` - 从 UI 获取配置
|
||
- `validate() -> (bool, str)` - 验证配置有效性
|
||
|
||
**验收标准**:
|
||
- 所有输入框能正常输入
|
||
- 文件选择对话框能选择文件和目录
|
||
- 配置变更时发出信号
|
||
|
||
---
|
||
|
||
## 任务 3: StateManager 状态管理
|
||
|
||
**文件**:`src/logic/state_manager.py`
|
||
|
||
**类**:`StateManager`
|
||
|
||
**方法**:
|
||
```python
|
||
def __init__(self, state_file: str):
|
||
"""初始化,加载或创建状态文件"""
|
||
|
||
def save(self):
|
||
"""保存状态到 JSON 文件"""
|
||
|
||
def get_current_step(self) -> int:
|
||
"""获取当前步骤索引 (0-6)"""
|
||
|
||
def get_step_name(self) -> str:
|
||
"""获取当前步骤名称"""
|
||
|
||
def set_step_status(self, step_name: str, status: str):
|
||
"""设置步骤状态 (pending/in_progress/completed/failed)"""
|
||
|
||
def update_clip(self, clip_index: int, **kwargs):
|
||
"""更新 clip 信息"""
|
||
|
||
def get_clips(self) -> list:
|
||
"""获取所有 clips"""
|
||
|
||
def get_user_modified_titles(self) -> dict:
|
||
"""获取用户修改过的标题 {clip_index: title}"""
|
||
|
||
def reset(self):
|
||
"""重置状态,开始新项目"""
|
||
```
|
||
|
||
**状态文件**:`{output_dir}/state.json`
|
||
|
||
**验收标准**:
|
||
- 创建新状态时生成默认结构
|
||
- 加载已有状态时恢复完整信息
|
||
- 保存后 JSON 文件格式正确
|
||
|
||
---
|
||
|
||
## 任务 4: ProgressView 进度视图
|
||
|
||
**文件**:`src/gui/progress_view.py`
|
||
|
||
**UI 组件**:
|
||
```
|
||
┌─────────────────────────────────────────────┐
|
||
│ 当前步骤: 提取视频片段 [Clip 3/14] │
|
||
│ ████████████░░░░░░░░░░░░ 50% │
|
||
├─────────────────────────────────────────────┤
|
||
│ [准备] → [提取] → [转录] → [纠正] → [字幕] │
|
||
│ → [合并] → [烧录] │
|
||
├─────────────────────────────────────────────┤
|
||
│ 日志: │
|
||
│ ┌───────────────────────────────────────┐ │
|
||
│ │ 10:30:01 开始提取片段 3/14 │ │
|
||
│ │ 10:30:02 片段 3 提取完成 │ │
|
||
│ │ 10:30:03 开始提取片段 4/14 │ │
|
||
│ └───────────────────────────────────────┘ │
|
||
├─────────────────────────────────────────────┤
|
||
│ [暂停] [停止] [继续] │
|
||
└─────────────────────────────────────────────┘
|
||
```
|
||
|
||
**信号**:
|
||
- `start_signal` - 开始处理
|
||
- `pause_signal` - 暂停
|
||
- `resume_signal` - 继续
|
||
- `stop_signal` - 停止
|
||
|
||
**方法**:
|
||
- `update_step(step_name: str, percent: int)` - 更新步骤进度
|
||
- `update_clip_progress(current: int, total: int)` - 更新 Clip 进度
|
||
- `append_log(message: str)` - 追加日志
|
||
- `show_titles_for_review(titles: list)` - 显示标题待审核(触发 TitleEditor)
|
||
|
||
**验收标准**:
|
||
- 进度条能实时更新
|
||
- 日志能自动滚动到最新
|
||
- 按钮状态能根据流水线状态变化
|
||
|
||
---
|
||
|
||
## 任务 5: Worker 后台线程
|
||
|
||
**文件**:`src/logic/worker.py`
|
||
|
||
**类**:`Worker(QThread)`
|
||
|
||
**信号**:
|
||
```python
|
||
progress_signal = pyqtSignal(str, int, str) # step_name, percent, message
|
||
clip_completed_signal = pyqtSignal(int) # clip_index
|
||
step_started_signal = pyqtSignal(str) # step_name
|
||
step_completed_signal = pyqtSignal(str) # step_name
|
||
titles_ready_signal = pyqtSignal(list) # [{clip_index, original, llm_suggested}]
|
||
error_signal = pyqtSignal(str) # error_message
|
||
finished_signal = pyqtSignal(bool, str) # success, message
|
||
log_signal = pyqtSignal(str) # log message
|
||
```
|
||
|
||
**方法**:
|
||
- `__init__(config, state_manager, controller)`
|
||
- `run()` - 执行流水线
|
||
- `request_pause()` - 请求暂停
|
||
- `request_stop()` - 请求停止
|
||
|
||
**暂停实现**:
|
||
```python
|
||
def run(self):
|
||
for step in self.steps:
|
||
if self.is_stopped:
|
||
break
|
||
if self.is_paused:
|
||
self.wait_for_resume() # 等待用户resume信号
|
||
# 执行步骤...
|
||
```
|
||
|
||
**验收标准**:
|
||
- UI 在处理过程中不卡顿
|
||
- 暂停信号能在 1 秒内响应
|
||
- 所有信号能正确传递到 UI
|
||
|
||
---
|
||
|
||
## 任务 6: PipelineController 流水线控制
|
||
|
||
**文件**:`src/logic/pipeline_controller.py`
|
||
|
||
**类**:`PipelineController`
|
||
|
||
**步骤定义**:
|
||
```python
|
||
STEPS = [
|
||
'ready',
|
||
'extracting', # 提取片段
|
||
'transcribing', # 转录
|
||
'title_correcting', # 标题纠正(人工介入点)
|
||
'generating_subtitles', # 生成字幕
|
||
'merging', # 合并
|
||
'burning', # 烧录
|
||
'completed'
|
||
]
|
||
```
|
||
|
||
**方法**:
|
||
```python
|
||
def __init__(self, config: dict, state: StateManager):
|
||
self.config = config
|
||
self.state = state
|
||
self.is_paused = False
|
||
self.is_stopped = False
|
||
|
||
def run(self, worker: Worker):
|
||
"""运行流水线"""
|
||
|
||
def pause(self):
|
||
"""暂停"""
|
||
|
||
def resume(self):
|
||
"""恢复"""
|
||
|
||
def stop(self):
|
||
"""停止"""
|
||
|
||
def step_extracting(self, worker: Worker):
|
||
"""提取片段"""
|
||
|
||
def step_transcribing(self, worker: Worker):
|
||
"""转录(调用 Whisper)"""
|
||
|
||
def step_title_correcting(self, worker: Worker) -> list:
|
||
"""标题纠正 - 调用 LLM,返回需要用户确认的标题"""
|
||
|
||
def step_generating_subtitles(self, worker: Worker):
|
||
"""生成字幕"""
|
||
|
||
def step_merging(self, worker: Worker):
|
||
"""合并视频"""
|
||
|
||
def step_burning(self, worker: Worker):
|
||
"""烧录字幕"""
|
||
```
|
||
|
||
**验收标准**:
|
||
- 每个步骤能正确执行
|
||
- 暂停/恢复能正确工作
|
||
- 状态能正确保存
|
||
|
||
---
|
||
|
||
## 任务 7: TitleEditor 标题编辑器
|
||
|
||
**文件**:`src/gui/title_editor.py`
|
||
|
||
**UI 组件**:
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 标题审核 - 请确认以下标题是否正确 │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ # │ 原始标题 │ LLM建议 │ 修改后 │ 操作 │
|
||
├───┼──────────────┼─────────────┼───────────────┼──────────┤
|
||
│ 1 │ 弹奏 │ 弹奏 │ [弹奏 ] │ [编辑] │
|
||
│ 2 │ 非连奏弹奏法 │ 非连奏弹奏法 │ [非连奏弹奏法] │ [编辑] │
|
||
│ 3 │ 时值 │ 休止符 ✗ │ [休止符 ] │ [编辑] │
|
||
│ 4 │ 休止符 │ 休止符 │ [休止符 ] │ [编辑] │
|
||
│ 5 │ 节奏 │ 节奏 │ [节奏 ] │ [编辑] │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ [全部确认] [取消] │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**编辑弹窗**:
|
||
```
|
||
┌─────────────────────────────────┐
|
||
│ 编辑标题 - Clip #3 │
|
||
│ │
|
||
│ 原始标题: 时值 │
|
||
│ LLM建议: 休止符 │
|
||
│ │
|
||
│ 修改后: [_______________] │
|
||
│ │
|
||
│ [确定] [取消] │
|
||
└─────────────────────────────────┘
|
||
```
|
||
|
||
**信号**:
|
||
- `titles_confirmed_signal(list)` - 用户确认的标题
|
||
|
||
**验收标准**:
|
||
- 能显示所有标题
|
||
- 能编辑单个标题
|
||
- 能批量确认
|
||
- 确认后返回列表
|
||
|
||
---
|
||
|
||
## 任务 8: 主窗口集成
|
||
|
||
**文件**:`src/app.py`
|
||
|
||
**布局**:
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Piano Highlight Generator [_][□][X] │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ ┌─────────────────┐ ┌─────────────────────────────────┐ │
|
||
│ │ │ │ │ │
|
||
│ │ 配置面板 │ │ 进度视图 │ │
|
||
│ │ ConfigPanel │ │ ProgressView │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ ├─────────────────────────────────┤ │
|
||
│ │ │ │ 标题编辑器 (折叠) │ │
|
||
│ │ │ │ TitleEditor │ │
|
||
│ └─────────────────┘ └─────────────────────────────────┘ │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ 状态: 就绪 v1.0 │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**集成逻辑**:
|
||
1. ConfigPanel 发出 `config_changed_signal` → Controller 接收
|
||
2. 用户点击"开始" → Controller 启动 Worker
|
||
3. Worker 发出 `titles_ready_signal` → TitleEditor 显示
|
||
4. 用户确认标题 → TitleEditor 发出 `titles_confirmed_signal` → Worker 继续
|
||
5. Worker 发出 `progress_signal` → ProgressView 更新
|
||
|
||
**验收标准**:
|
||
- 能启动处理
|
||
- 各组件能正确通信
|
||
- 标题编辑器在正确时机显示
|
||
|
||
---
|
||
|
||
## 任务 9: 核心模块适配
|
||
|
||
**文件**:`src/core/` (复用现有模块)
|
||
|
||
**适配工作**:
|
||
1. 复制 `scripts/` 下的核心模块到 `src/core/`
|
||
2. 修改 import 路径
|
||
3. 确保 `constants.py` 中的路径配置可从外部传入
|
||
4. 适配视频处理函数返回成功/失败状态
|
||
|
||
**验收标准**:
|
||
- 核心模块能在 GUI 中正常调用
|
||
- 错误能被捕获并传递到 UI
|
||
|
||
---
|
||
|
||
## 任务 10: 错误处理完善
|
||
|
||
**处理场景**:
|
||
|
||
| 场景 | 处理方式 |
|
||
|------|----------|
|
||
| API Key 无效 | 401 错误,提示用户检查配置 |
|
||
| 视频文件不存在 | 暂停,弹窗提示 |
|
||
| 磁盘空间不足 | 暂停,弹窗提示 |
|
||
| Whisper 模型未找到 | 提示下载或选择其他模型 |
|
||
| 处理异常 | 保存状态,显示错误日志 |
|
||
|
||
**验收标准**:
|
||
- 错误不导致程序崩溃
|
||
- 错误信息清晰用户友好
|
||
- 状态正确保存
|
||
|
||
---
|
||
|
||
## 任务 11: 打包配置 + 测试
|
||
|
||
**文件**:
|
||
- `nuitka_options.py`
|
||
- `build.bat` (Windows 打包脚本)
|
||
- `build.sh` (Linux/Mac 打包脚本)
|
||
|
||
**打包步骤**:
|
||
1. 安装依赖:`pip install -r requirements.txt`
|
||
2. 开发测试:`python src/main.py`
|
||
3. 打包:`python -m nuitka nuitka_options.py`
|
||
4. 测试 exe:`dist/PianoHighlightGenerator.exe`
|
||
|
||
**验收标准**:
|
||
- 打包后体积 < 50MB
|
||
- 双击能正常运行
|
||
- 所有功能在打包后正常工作
|
||
|
||
---
|
||
|
||
## 任务 12: 文档和 README
|
||
|
||
**文件**:`README.md`
|
||
|
||
**内容**:
|
||
- 应用介绍和截图
|
||
- 系统要求
|
||
- 安装指南(开发安装、打包安装)
|
||
- 使用说明
|
||
- 常见问题
|
||
- 许可证
|
||
|
||
**验收标准**:
|
||
- 用户能根据 README 运行应用
|
||
- 常见问题有解决方案
|
||
|
||
---
|
||
|
||
## 并行化分析
|
||
|
||
**可并行任务**:
|
||
|
||
| 任务组 | 可并行任务 | 原因 |
|
||
|--------|-----------|------|
|
||
| UI 组件组 | 2, 4, 7 | 独立开发,独立 UI 组件 |
|
||
| 核心逻辑组 | 3, 5, 6 | 有依赖关系,需顺序开发 |
|
||
| 集成测试组 | 8, 10 | 依赖前面所有任务 |
|
||
|
||
**推荐开发顺序**:
|
||
1. **第一波(可并行)**:1, 2, 4, 7, 9
|
||
2. **第二波(依赖第一波)**:3, 5, 6
|
||
3. **第三波(集成)**:8, 10
|
||
4. **最后**:11, 12
|
||
|
||
---
|
||
|
||
## Git 分支规划
|
||
|
||
**建议分支**:
|
||
- `main` - 主分支,稳定代码
|
||
- `feat/ui` - UI 组件开发 (任务 2, 4, 7)
|
||
- `feat/core` - 核心逻辑开发 (任务 3, 5, 6)
|
||
- `feat/integration` - 集成和打包 (任务 8, 10, 11, 12)
|
||
|
||
**合并顺序**:
|
||
```
|
||
feat/ui ─────────┐
|
||
feat/core ────────┼──► main
|
||
feat/integration ─┘
|
||
```
|