# 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 ─┘ ```