Files
lesson-highlights/docs/IMPLEMENTATION_PLAN.md
T

8.6 KiB
Raw Blame History

Piano Highlight Generator - GUI 编辑功能实现计划

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 实现 GUI 编辑功能,支持增删改知识点和字幕,CLI/GUI 共用项目文件体系,底层原子化复用。

Architecture:

  • generated_config.yaml = 项目文件(元信息 + clips 配置)
  • config.ini = 全局配置(API 密钥等),不跟项目
  • 底层原子操作在 core/,CLI 和 GUI 共用
  • 按需重生成(只重烧受影响的 clip

Tech Stack: PySide6 GUI, YAML, faster-whisper, FFmpeg


Phase 0: 配置体系重构

Task 1: 项目文件增加元信息字段

Files:

  • Modify: src/core/pipeline.py — Pipeline.run() 结束时写 video_srcppt_pathmax_total_duration 到 generated_config.yaml
  • Modify: src/core/ppt_parser.py_create_config() 写入 video_srcppt_path

Steps:

  • Pipeline.run()step_generate_subtitles 结束后,读取 config 中的 video_src/ppt_path,写入 generated_config.yaml
  • 确保 _create_config() 包含 max_total_duration 字段
  • 验证:跑完 run.bat 后,generated_config.yaml 包含 video_src 和 ppt_path

Task 2: config.py 重构(项目路径 vs 全局配置分离)

Files:

  • Modify: config.py — 移除 VIDEO/PPT/OUTPUTAPI 配置留在 config.ini
  • Modify: run.py — 从 config.py 只读 API 相关字段,项目路径由 CLI 参数指定
  • Modify: src/cli.py — 确认 --video/--ppt/--output 参数能正确传入 pipeline

Steps:

  • 修改 config.py:只保留 API_KEY/API_HOST/PYTHON/CLI_DIR,移除 VIDEO/PPT/OUTPUT/MAX_TOTAL_DURATION
  • 修改 run.py:从 config.py 读 API 配置,VIDEO/PPT/OUTPUT 通过 cli.py 参数传入(cli.py 已有 --video/--ppt/--output
  • 验证:run.bat 能正常跑完整流程

Phase 1: 底层原子化

Task 3: 提取标题匹配函数

Files:

  • Modify: src/core/ppt_parser.py — 提取 _find_title_in_transcript(title, transcript_segments) 函数
  • Create: src/core/subtitle_matcher.py (可选,如果逻辑复杂则独立)

Steps:

  • ppt_parser.py 中提取 _find_title_in_transcript(title, corrected_segments):
    • 输入:标题文字 + corrected_transcript.json 的 segments 列表
    • 处理:在每个 segment 的 text 中搜索标题关键词(子串匹配)
    • 返回:(start, end)None(匹配不到)
  • 写单元测试验证:mock segments 数据,测试匹配返回正确时间戳,匹配不到返回 None
  • 验证:corrected_transcript.json 存在情况下,给定一个已知标题能找到对应时间段

Task 4: reextract_clip — 单标题重新匹配

Files:

  • Modify: src/core/pipeline.py — 增加 reextract_clip(clip_index, new_title) 方法

Steps:

  • 在 Pipeline 类中增加 reextract_clip(self, clip_index, new_title):
    def reextract_clip(self, clip_index, new_title):
        clip = self.clips[clip_index]
        # 加载 corrected_transcript.json
        # 调用 _find_title_in_transcript(new_title, segments)
        # 匹配到 → 更新 clip['start']/clip['end']
        # 匹配不到 → clip['matched'] = False(或标记)
        # 调用 _merge_overlapping_clips 如有必要
        # 保存 updated config to generated_config.yaml
        # 删除 clip_index 对应的 json(触发重生成)
    
  • 写测试:用 lesson1 的 output,跑完后 reextract 某个 clip 改标题,验证 config 更新

Task 5: delete_clip — 删除 clip

Files:

  • Modify: src/core/pipeline.py — 增加 delete_clip(clip_index) 方法

Steps:

  • 在 Pipeline 类中增加 delete_clip(self, clip_index):
    def delete_clip(self, clip_index):
        # 从 self.clips 删除该 clip
        # 删除 intermediates/clipN.json 和 clipN.mp4
        # 保存 updated config to generated_config.yaml
    
  • 写测试:跑完后删一个 clip,验证 json/mp4 删除、config 更新

Task 6: add_clip_by_title — 新增知识点

Files:

  • Modify: src/core/pipeline.py — 增加 add_clip_by_title(new_title) 方法

Steps:

  • 在 Pipeline 类中增加 add_clip_by_title(self, new_title):
    def add_clip_by_title(self, new_title):
        # 调用 _find_title_in_transcript 匹配时间段
        # 匹配到 → 判断是否与现有 clip 重叠 → 合并处理
        # 匹配不到 → 标记 matched=False,不加入 self.clips(或加到待确认列表)
        # 保存 updated config
    
  • 写测试:加一个新标题,验证 config 更新、json 不生成(待确认状态)

Task 7: reburn_titles / reburn_subtitles — 部分重烧

Files:

  • Modify: src/core/pipeline.py — 增加 reburn_titles()reburn_subtitles(user_texts=None) 方法
  • Modify: src/core/subtitle.py — 检查 generate_from_clips 能否跳过 LLM 校正直接用用户文本

Steps:

  • reburn_titles(self):
    def reburn_titles(self):
        # 用已有的 clip configs(不重生成 json
        # 调用 subtitle_pipeline.generate_from_clips
        # 烧录标题轨到 subs/v1_title.srt
    
  • reburn_subtitles(self, user_texts=None):
    def reburn_subtitles(self, user_texts=None):
        # user_texts: 可选,直接用用户文本烧字幕,跳过 LLM 校正
        # 读取 v1_content.srt 或直接用传入的文本
        # 烧录字幕轨到 subs/v1_content.srt
    
  • 修改 burn_only.py 适配新的 Pipeline 方法

Phase 2: GUI 重构

Task 8: GUI 两种启动模式

Files:

  • Modify: src/gui.py — 重构为分步界面(启动页 → 处理/编辑页)

Steps:

  • 重构 GUI 启动页:两个选项按钮
    • "新建项目" → 跳转文件选择(视频+PPT+输出目录)
    • "打开已有项目" → 打开目录选择框 → 加载 generated_config.yaml
  • 实现"打开已有项目"
    def load_project(self, output_dir):
        config = load_yaml(os.path.join(output_dir, 'generated_config.yaml'))
        # 设置 video_src, ppt_path, output_dir
        # 初始化 Pipeline(config)
        # 加载 clips 列表显示
        # 加载字幕预览
    
  • 验证:打开 lesson1 output 目录,能正确显示 clip 列表

Task 9: GUI 编辑界面

Files:

  • Modify: src/gui.py — 增加编辑界面组件

Steps:

  • 左侧 clip 列表:
    • QListWidget 显示 clip 标题列表
    • 双击编辑标题
    • 右键菜单:删除、新增
    • 未匹配 clip 显示红色/警告图标
  • 右侧字幕预览:
    • QTextEdit 显示 v1_content.srt 内容
    • 用户可直接编辑
  • 底部"应用"按钮:
    • 收集所有修改
    • 调用底层原子操作
    • 进度显示
    • 重烧后刷新预览

Task 10: 应用按钮 — 原子操作集成

Files:

  • Modify: src/gui.py — 应用按钮连接到 Pipeline 原子方法

Steps:

  • 应用按钮逻辑:
    def on_apply(self):
        # 检测变化:
        # - clip 标题改了 → reextract_clip(i, new_title)
        # - clip 删了 → delete_clip(i)
        # - 新增知识点 → add_clip_by_title(title)
        # - 字幕改了 → reburn_subtitles(user_texts)
        # - 任一 clip 变了 → reburn_titles()
        # 最后调用 Pipeline.step_burn() 或 reburn 最终视频
    
  • 未匹配 clip 不参与重烧,显示提示
  • 验证:改标题 → 点应用 → final.mp4 更新

Task 11: CLI/GUI 互操作测试

Steps:

  • CLI run.bat 跑 lesson1 → 生成完整 output
  • GUI 打开同一 output 目录
  • 改 clip3 标题为"新标题" → 点应用 → 验证 config 更新、final.mp4 更新
  • GUI 删 clip5 → 点应用 → 验证 config 更新、final.mp4 更新
  • GUI 改字幕文本 → 点应用 → 验证 final.mp4 更新

Phase 3: 收尾

Task 12: 删除死代码

Files:

  • Identify: 检查 gui.py 中被替换掉的旧代码
  • Remove: 删除不再使用的 UI 组件和逻辑

Task 13: 更新文档

Files:

  • Modify: docs/USAGE.md — 增加 GUI 编辑说明

Task 14: commit

Steps:

  • git add -A
  • commit: "feat: GUI edit mode with clip/subtitle editing, config separation"
  • push

自检清单

  • 所有修改文件有备份/可回滚
  • 每个 task 后验证功能正常
  • CLI 完整流程测试通过
  • GUI 新建项目测试通过
  • GUI 打开已有项目测试通过
  • 改/删/增 clip 后 final.mp4 正确更新
  • 字幕编辑后 final.mp4 正确更新
  • 无新增警告或 lint 错误