Files

235 lines
9.0 KiB
Markdown
Raw Permalink 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.
# Piano Highlight Generator - GUI 修正功能设计
## 背景
现有 GUI 仅有"选文件+开始处理"的功能,跑完后用户无法对结果进行修正。本设计在跑完之后提供知识点编辑和字幕编辑能力,支持增删改,并自动判断如何应用修改。
## 配置体系重构
### 原则
- **项目配置**跟项目走,保存到项目文件中
- **全局配置**(API密钥等)不跟项目,放在独立文件
### 两类配置文件
**项目文件** (`generated_config.yaml`)
```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`)
```ini
[api]
api_key = "..."
api_host = "..."
whisper_model = "large"
```
### 迁移计划
- `config.py` 拆分:项目路径 → 传给 cli.py 时作为临时参数,不持久化;API 配置 → 留在 config.ini
- `generated_config.yaml` 增加 `video_src``ppt_path``max_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.ini`API 密钥等应用级配置
## 用户流程
### 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: 配置体系重构
0. `generated_config.yaml` 增加 `video_src``ppt_path``max_total_duration` 字段,跑完流程后写入
0. `config.py` 移除项目路径参数,改为运行时传参;API 配置留在 `config.ini`
0. 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 重构
7. GUI 支持两种启动模式:
- "新建项目" — 选择视频+PPT,运行完整流程
- "打开项目" — 选择已有 output_dir/,从 generated_config.yaml 加载元信息
8. GUI 编辑界面:
- 左侧:clip 列表(知识点标题),可改/删/增
- 右侧:字幕预览(显示 v1_content.srt 内容),可编辑文本
- 未匹配 clip 标记显示("未匹配"标签),不参与烧录
9. 点"应用" → 调用底层原子函数 → 按需重生成 → 重烧
10. CLI 完整性测试:CLI 跑完 → GUI 打开同一项目 → 改标题 → 重烧 → 验证结果
### Phase 3: 收尾
11. 删除死代码(原有 gui.py 里被替换掉的部分)
12. 更新文档:USAGE.md 增加 GUI 编辑说明
13. commit