Files

9.0 KiB
Raw Permalink Blame History

Piano Highlight Generator - GUI 修正功能设计

背景

现有 GUI 仅有"选文件+开始处理"的功能,跑完后用户无法对结果进行修正。本设计在跑完之后提供知识点编辑和字幕编辑能力,支持增删改,并自动判断如何应用修改。

配置体系重构

原则

  • 项目配置跟项目走,保存到项目文件中
  • 全局配置API密钥等)不跟项目,放在独立文件

两类配置文件

项目文件 (generated_config.yaml)

video_src: "D:/...mp4"           # 项目元信息
ppt_path: "D:/...pptx"           # 项目元信息
output_dir: "D:/...output"       # 项目元信息
max_total_duration: 600
clips: [...]
video_params: {...}
term_corrections: {...}
# api_key/api_host 不在这里

全局配置 (config.ini)

[api]
api_key = "..."
api_host = "..."
whisper_model = "large"

迁移计划

  • config.py 拆分:项目路径 → 传给 cli.py 时作为临时参数,不持久化;API 配置 → 留在 config.ini
  • generated_config.yaml 增加 video_srcppt_pathmax_total_duration 字段(现有流程跑完后补充写入)
  • CLI 新建项目时,generated_config.yaml 直接作为项目文件输出
  • GUI 打开已有项目时,从 generated_config.yaml 读取所有项目信息,API 配置从 config.ini 单独读取

CLI/GUI 项目文件体系

generated_config.yaml 即为项目文件。CLI 和 GUI 共用同一套项目文件:

output_dir/
├── generated_config.yaml   ← 项目文件(元信息 + clips 配置,唯一真源)
├── intermediates/          ← 中间缓存(视频片段 + Whisper JSON
│   ├── clip1.json
│   ├── clip1.mp4
│   └── ...
├── subs/                  ← 字幕文件
│   ├── v1_title.srt
│   └── v1_content.srt
├── concat_merged.mp4      ← 中间合并视频
└── final.mp4              ← 最终输出

CLI 批量处理 → 每个视频输出独立 output_dir/(项目文件) GUI 审核修改 → 打开任意 output_dir/,加载已有的 generated_config.yaml

GUI 打开项目时自动检测:

  • generated_config.yaml 存在 → 可编辑
  • intermediates/clip*.json 存在 → 对应 clip 可重生成
  • subs/v1_title.srt 存在 → 可编辑标题
  • subs/v1_content.srt 存在 → 可编辑字幕

名词定义

  • clip:底层实现细节,表示一个视频片段(start/end/title_segments
  • 知识点:用户感知的单位,即 clip 的 title
  • 标题v1_title.srt,知识点名称的大字叠加层
  • 字幕v1_content.srt,实际转录文本的小字叠加层
  • 项目文件generated_config.yaml,项目元信息 + clips 配置的唯一真源
  • 全局配置config.iniAPI 密钥等应用级配置

用户流程

GUI 两种模式

模式一:新建项目

选择视频 + PPT → 完整流程(PPT解析→转录→字幕→烧录)→ 显示结果

模式二:打开已有项目

选择 output_dir/ → 加载 generated_config.yaml → 显示 clip 列表和字幕
→ 用户编辑 → 系统按需重生成 → 重烧

完整编辑流程

打开项目 → 显示 clip 列表(知识点标题)+ 字幕预览
                        ↓
              ┌─────────┴─────────┐
         编辑知识点             编辑字幕
         (改/删/增标题)         (改/删文本)
              ↓                      ↓
    系统自动判断如何重生成      直接应用用户修改
    (删json/重新匹配/处理重叠)  (跳过LLM校正)
              ↓                      ↓
              └──────┬─────────────┘
                     ↓
                  自动重烧
                     ↓
            用户用播放器查看(预览后续再说)

知识点编辑

用户操作

  • 改标题:直接编辑文字
  • 删 clip:删除该 clip
  • 新增知识点:输入新标题(PPT 里没有的也行)

系统行为

操作 底层动作
改 clip N 标题 clipN.json → 用新标题在 transcript 里重新匹配 start/end → 处理重叠 → 重烧
删 clip N 从 generated_config.yaml 删掉该 clip → 删 clipN.json + clipN.mp4 → 重烧
新增知识点 用新标题在 transcript 里匹配 start/end → 判断是否合并到相邻 clip(重叠处理)→ 重烧

未匹配处理

匹配不到(老师没讲完 PPT)的 clip:

  • GUI 显示"未匹配"标签
  • 不参与烧录(不生成默认短时长占位)
  • 用户可改标题重试,或直接删掉

重叠处理

新增/修改后如果与现有 clip 重叠,系统自动:

  1. 合并重叠片段
  2. 生成 title_segments(按 transcript 关键词首次出现时间切分)
  3. 每个标题最多显示 title_duration 秒

字幕编辑

用户操作

直接编辑字幕文件中的文本(v1_content.srt)。

系统行为

  • 改字幕文本:以用户修改为准,跳过 LLM 校正,直接重烧
  • 删字幕条目:用户删除某条,系统保留,其他正常重烧
  • 改时间轴:不支持(时间轴由底层逻辑决定)

底层原子化支撑

底层需要提供以下能力,供 GUI 调用:

# 新增:单标题重新匹配
reextract_clip(config, clip_index, new_title, video_src, output_dir)
  → 删 clipN.json → 在 corrected_transcript.json 里用新标题匹配 → 更新 generated_config.yaml → 重烧

# 新增:删除 clip
delete_clip(config, clip_index, output_dir)
  → 从 config 删 clip → 删 intermediates/clipN.json + clipN.mp4 → 重烧

# 新增:新增知识点(用新标题在 transcript 里匹配)
add_clip_by_title(config, new_title, video_src, output_dir)
  → 在 corrected_transcript.json 里匹配 → 判断合并/新增 clip → 更新 config → 重烧

# 已有(需检查):重烧标题轨
reburn_titles(config, output_dir)

# 已有(需检查):重烧字幕轨(跳过 LLM 校正)
reburn_subtitles(config, output_dir, user_texts=None)

数据流

generated_config.yaml  ← 项目文件,元信息+clips配置唯一真源(编辑后同步更新)
intermediates/           ← 中间缓存
  clip*.json           ← Whisper 转录(按需删除重生成)
  clip*.mp4            ← 视频片段(删 clip 时删除)
  corrected_transcript.json ← LLM校正后的全量转录(新增/重匹配clip时用,不重生成)
subs/
  v1_title.srt        ← 标题轨(改标题后重烧)
  v1_content.srt       ← 字幕轨(用户直接改文本,跳过 LLM 校正)
config.ini             ← 全局配置(API密钥等应用级配置,不跟项目)

架构原则

  1. 项目文件 = 项目元信息 + clips 配置generated_config.yaml 是唯一真源,CLI 和 GUI 共用
  2. 全局配置分离API 密钥等放在 config.ini,不写入项目文件
  3. 按需重生成:只删除/重生成受影响的 clip,不动其他
  4. 字幕以用户为准:字幕文本修改跳过 LLM 校正
  5. CLI/GUI 底层复用:所有原子操作在 core/ 里

实施步骤

Phase 0: 配置体系重构

  1. generated_config.yaml 增加 video_srcppt_pathmax_total_duration 字段,跑完流程后写入
  2. config.py 移除项目路径参数,改为运行时传参;API 配置留在 config.ini
  3. CLI 新建项目时直接输出含完整元信息的 generated_config.yaml

Phase 1: 底层原子化

  1. core/ppt_parser.py 提取 _find_title_in_transcript(title, transcript) — 给定标题在 corrected_transcript.json 里找匹配时间段,匹配不到返回 None
  2. core/pipeline.py 增加 reextract_clip(clip_index, new_title) — 删对应 json → 调用匹配 → 更新 config
  3. core/pipeline.py 增加 delete_clip(clip_index) — 从 config 删 → 删 json/mp4
  4. core/pipeline.py 增加 add_clip_by_title(new_title) — 匹配 → 判断合并/新增 → 更新 config
  5. core/pipeline.py 增加 reburn_titles() / reburn_subtitles(user_texts=None) — 支持只烧标题或只烧字幕,跳过 LLM 校正
  6. burn_only.py 适配新接口(已有大部分逻辑,可能需要调整参数)

Phase 2: GUI 重构

  1. GUI 支持两种启动模式:
    • "新建项目" — 选择视频+PPT,运行完整流程
    • "打开项目" — 选择已有 output_dir/,从 generated_config.yaml 加载元信息
  2. GUI 编辑界面:
    • 左侧:clip 列表(知识点标题),可改/删/增
    • 右侧:字幕预览(显示 v1_content.srt 内容),可编辑文本
    • 未匹配 clip 标记显示("未匹配"标签),不参与烧录
  3. 点"应用" → 调用底层原子函数 → 按需重生成 → 重烧
  4. CLI 完整性测试:CLI 跑完 → GUI 打开同一项目 → 改标题 → 重烧 → 验证结果

Phase 3: 收尾

  1. 删除死代码(原有 gui.py 里被替换掉的部分)
  2. 更新文档:USAGE.md 增加 GUI 编辑说明
  3. commit