04db423416
- 70 skills with code and documentation - Add .gitignore (ignore __pycache__, output/, temp/, venv/) - Clean up test intermediates and caches
227 lines
10 KiB
Markdown
227 lines
10 KiB
Markdown
# 📋 钢琴课精华视频生成技能 - 会话状态与交接文档
|
||
|
||
> **生成时间**: 2026-04-02
|
||
> **最后更新**: 2026-04-03
|
||
> **当前状态**: ✅ 全流程验证通过,环境配置已固化
|
||
|
||
---
|
||
|
||
## 🎯 核心目标
|
||
利用 `piano-lesson-highlight-generator` 技能,根据 PPT 和视频自动生成精华视频(<15分钟),包含标题卡、字幕、转场。
|
||
|
||
---
|
||
|
||
## 🔧 环境配置
|
||
|
||
**详见 `ENVIRONMENT.md`**
|
||
|
||
关键信息:
|
||
- **Python 环境**: `D:/ProgramData/anaconda3/envs/py312_cuda/python.exe`(Python 3.12.13)
|
||
- **PyTorch**: 2.5.1+cu121(**必须 GPU**,CPU 会超时)
|
||
- **Whisper 模型**: `D:/AI/LM-Models/faster-whisper/large-v3/`
|
||
- **运行命令**: 直接使用完整路径调用 Python,不要用 `conda activate`
|
||
|
||
### 环境验证
|
||
|
||
```bash
|
||
"D:/ProgramData/anaconda3/envs/py312_cuda/python.exe" -c "import torch; print(torch.cuda.is_available())"
|
||
# 必须输出 True
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 已解决的结构性问题
|
||
|
||
### 1. 知识点匹配错误(核心修复)
|
||
|
||
| 问题 | 根因 | 修复方案 | 状态 |
|
||
|------|------|----------|------|
|
||
| 匹配到导读区而非教学区 | 搜索词按顺序匹配,找到第一个就 break;评分只看密度 | 完整关键词+核心子词+相关词映射+数字归一化收集所有 segment;评分综合考量出现次数、文本量、讲解密度、孤立程度 | ✅ |
|
||
| 匹配到回顾区而非教学区 | 回顾区有更多相关 segment | 靠近作业时间惩罚 + 回顾性语言检测("刚才"、"刚刚"等) | ✅ |
|
||
| 匹配到"等下再说"而非实际教学 | 预告和实际教学无法区分 | 预告/讲解特征词检测;推迟语言检测;导读过滤(无讲解 + segment ≤ 2 → 跳过) | ✅ |
|
||
| 通用词误匹配(如"记号"匹配到无关内容) | 搜索词包含 2 字通用词 | 通用后缀过滤(记号、符号、音符等不单独匹配);相关词映射 | ✅ |
|
||
| 数字不匹配("十六分音符"≠"16分音符") | Whisper 将中文数字识别为阿拉伯数字 | 数字归一化匹配(中文数字↔阿拉伯数字互转) | ✅ |
|
||
| "掀起你的盖头来"只在导读出现 | 转录中未出现该歌曲名 | 导读过滤:无讲解特征 + segment ≤ 2 → 跳过 | ✅ |
|
||
|
||
### 2. 字幕同步问题
|
||
|
||
| 问题 | 根因 | 修复方案 | 状态 |
|
||
|------|------|----------|------|
|
||
| 字幕 1分18秒开始乱套 | clip3/clip4 重叠导致 JSON 内容重复,偏移计算用 config duration 而非实际 segments end | 偏移改用 JSON segments 实际最大 end 时间 | ✅ |
|
||
| 字幕滞后 2-3 秒 | 转录过滤包含跨边界片段,调整后的时间戳超出 clip 实际时长 | 限制时间戳在 clip 实际时长范围内 | ✅ |
|
||
| clip2(延音线)被跳过 | Whisper 把"延音"识别为"言音",内容验证失败 | 内容验证时先应用术语纠正(言音→延音、演音→延音等) | ✅ |
|
||
|
||
### 3. 作业片段匹配
|
||
|
||
| 问题 | 根因 | 修复方案 | 状态 |
|
||
|------|------|----------|------|
|
||
| 作业片段匹配不到 | 引导语列表不全 | 用"作业"词密度替代引导语匹配 | ✅ |
|
||
| 作业片段截断太早 | detect_gap_cutoff 对作业场景太敏感 | 间隔阈值从 15s 放宽到 30s;视频末尾前 2 分钟兜底 | ✅ |
|
||
| 作业结束不准确 | 无法识别口语化结束表达 | 模糊匹配 30+ 种口语表达("作业.*就这样"、"作业.*就这些"、"下课"等) | ✅ |
|
||
|
||
### 4. 去重逻辑优化
|
||
|
||
| 问题 | 根因 | 修复方案 | 状态 |
|
||
|------|------|----------|------|
|
||
| 多个知识点在同一区域被丢弃 | 去重逻辑只保留密度最高的,丢弃其他 | 调整边界让相邻知识点共存,而非丢弃 | ✅ |
|
||
|
||
### 5. GPU 资源管理
|
||
|
||
| 问题 | 根因 | 修复方案 | 状态 |
|
||
|------|------|----------|------|
|
||
| 僵尸进程占用 GPU 显存 | 多次启动转录进程,旧进程未释放 | 转录后 `del model` + `gc.collect()` + `torch.cuda.empty_cache()` | ✅ |
|
||
| `taskkill` 自杀命令 | 清理命令杀掉了当前进程 | 移除转录前的 taskkill,改为转录后显式释放模型 | ✅ |
|
||
|
||
---
|
||
|
||
## 🏗️ 知识点匹配架构
|
||
|
||
### 评分公式
|
||
|
||
```
|
||
score = (base_score + full_bonus) × text_bonus × isolation_penalty × teaching_bonus × review_penalty × defer_penalty × preview_penalty
|
||
```
|
||
|
||
| 因子 | 计算方式 | 作用 |
|
||
|------|---------|------|
|
||
| base_score | total_count × avg_rel | 相关 segment 数量 × 平均相关度 |
|
||
| full_bonus | full_count × 2.0 | 完整关键词出现次数奖励 |
|
||
| text_bonus | min(total_text_len / 30, 5.0) | 上下文文本量加成 |
|
||
| isolation_penalty | 1.0 / (1.0 + other_kw_count × 0.5) | 和其他知识点一起出现惩罚 |
|
||
| teaching_bonus | 1.0 + teaching_density × 2.0 | 讲解词占比加成 |
|
||
| review_penalty | max(0.1, time_to_homework / 300) | 靠近作业时间惩罚 |
|
||
| defer_penalty | max(0.1, 1.0 - defer_ratio × 2.0) | 推迟语言惩罚 |
|
||
| preview_penalty | max(0.1, 1.0 - preview_ratio × 2.0) | 预告语言惩罚 |
|
||
|
||
### 相关度评分
|
||
|
||
| 匹配类型 | 分数 | 示例 |
|
||
|---------|------|------|
|
||
| 完整关键词 | 3.0 | "附点音符" 匹配 "附点音符" |
|
||
| 数字归一化 | 2.5 | "十六分音符" 匹配 "16分音符" |
|
||
| 核心子词 | 2.0 | "双音的支撑" 匹配 "双音支撑" |
|
||
| 相关词映射 | 1.5 | "升降记号" 匹配 "升号"/"降号" |
|
||
| 前缀匹配 | 1.5 | "附点音符" 匹配 "附点" |
|
||
| 核心词 | 1.0 | 3-4 字核心词匹配 |
|
||
|
||
### 相关词映射
|
||
|
||
```python
|
||
related_terms = {
|
||
"升降记号": ["升号", "降号", "升记", "降记", "升降", "升半", "降半"],
|
||
"还原记号": ["还原"],
|
||
"附点音符": ["附点"],
|
||
"延音线": ["延音", "同音连线"],
|
||
"双音的支撑": ["双音", "支撑"],
|
||
"婚礼进行曲": ["婚礼"],
|
||
"掀起你的盖头来": ["盖头来", "盖头", "掀起"],
|
||
"十六分音符": ["16分", "十六分"],
|
||
"八分音符": ["8分", "八分"],
|
||
}
|
||
```
|
||
|
||
### 特征词检测
|
||
|
||
| 类型 | 关键词 |
|
||
|------|--------|
|
||
| 推迟语言 | "等下再说"、"等下讲"、"后面再说"、"稍后再说"、"先不说" |
|
||
| 预告语言 | "先说一下"、"先讲一下"、"首先说"、"我先说"、"提一下" |
|
||
| 讲解语言 | "因为"、"所以"、"就是"、"什么意思"、"为什么"、"怎么"、"比如说"、"大家看"、"弹"、"按"、"练" |
|
||
| 回顾语言 | "刚才"、"刚刚"、"今天学"、"今天讲"、"回顾"、"练习一下"、"复习" |
|
||
|
||
### 作业结束检测(模糊匹配 30+ 种表达)
|
||
|
||
| 类型 | 匹配模式 | 示例 |
|
||
|------|---------|------|
|
||
| 明确下课 | `下课`、`拜拜`、`再见` | "下课" |
|
||
| 作业完成 | `作业.*就这样`、`作业.*就这些`、`作业.*讲到这里` | "今天的作业就这样"、"关于作业就讲到这里" |
|
||
| 通用结束 | `就到这里`、`就这样了`、`说完了`、`没什么.*说的` | "就这些了"、"没什么要说的了" |
|
||
| 群发通知 | `发群`、`到时候.*发` | "到时候我发群里" |
|
||
|
||
---
|
||
|
||
## 📂 项目目录结构
|
||
|
||
```
|
||
projects/piano-lesson-highlights/
|
||
├── data/ # 原始输入数据
|
||
│ ├── lesson2/
|
||
│ │ ├── video.mp4
|
||
│ │ └── course.pptx
|
||
│ └── lesson3/
|
||
│ ├── video.mp4
|
||
│ └── course.pptx
|
||
└── cases/ # 每个案例的工作区
|
||
├── lesson2/
|
||
│ ├── config.yaml
|
||
│ ├── intermediates/
|
||
│ │ └── full_transcript.json
|
||
│ └── output/
|
||
│ ├── v1_final.mp4
|
||
│ └── subs/
|
||
└── lesson3/
|
||
├── config.yaml
|
||
├── intermediates/
|
||
│ └── full_transcript.json
|
||
└── output/
|
||
├── v1_final.mp4
|
||
└── subs/
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ lesson2 验证结果
|
||
|
||
| # | 知识点 | 匹配位置 | 实际内容 | 状态 |
|
||
|---|--------|---------|---------|------|
|
||
| 1 | 附点音符 | 3126s (52min) | 实际教学区 | ✅ |
|
||
| 2 | 延音线 | 4040s (67min) | 实际教学区 | ✅ |
|
||
| 3 | 升降记号 | 4237s (70min) | 实际教学区 | ✅ |
|
||
| 4 | 还原记号 | 4682s (78min) | 实际教学区 | ✅ |
|
||
| 5 | 双音的支撑 | 5051s (84min) | 实际教学区 | ✅ |
|
||
| 6 | 婚礼进行曲 | 5345s (89min) | 实际教学区 | ✅ |
|
||
| 7 | 作业 | 6515s-6998s (482s) | 作业区 | ✅ |
|
||
|
||
**产出**:
|
||
- v1_final.mp4: 679秒(11.3分钟),133.3 MB
|
||
- 380 条字幕(original/terms/ai 三个版本)
|
||
|
||
---
|
||
|
||
## ✅ lesson3 验证结果
|
||
|
||
| # | 知识点 | 匹配位置 | 实际内容 | 状态 |
|
||
|---|--------|---------|---------|------|
|
||
| 1 | 八分音符 | 2332s (38min) | 实际教学区 | ✅ |
|
||
| 2 | 十六分音符 | 2456s (40min) | 实际教学区(数字归一化匹配) | ✅ |
|
||
| 3 | 反复记号 | 3296s (54min) | 实际教学区 | ✅ |
|
||
| 4 | 高八度 | 3315s (55min) | 实际教学区 | ✅ |
|
||
| 5 | 低八度记号 | 3369s (56min) | 实际教学区 | ✅ |
|
||
| 6 | 作业 | 5272s-5981s (709s) | 作业区(下课 5951s + 30s) | ✅ |
|
||
| ❌ | 掀起你的盖头来 | 已跳过 | 只在导读出现,无实际教学 | ✅ 正确跳过 |
|
||
|
||
**产出**:
|
||
- v1_final.mp4: 867秒(14.5分钟),69.8 MB
|
||
- 417 条字幕(original/terms/ai 三个版本)
|
||
|
||
---
|
||
|
||
## ⏳ 待处理
|
||
|
||
| 项目 | 状态 | 说明 |
|
||
|------|------|------|
|
||
| 字幕 AI 纠错验证 | 待人工 | 老莫需要看 v1_ai.srt 的纠错效果 |
|
||
| 视频质量审核 | 待人工 | 老莫需要看 v1_final.mp4 确认标题卡、转场、字幕同步 |
|
||
|
||
---
|
||
|
||
## 💡 关键经验
|
||
|
||
1. **转录数据可复用**:同一节课的 `full_transcript.json` 可以直接复制使用,不需要重新转录
|
||
2. **GPU 是必须的**:CPU 转录 100 分钟视频会超时(100+ 分钟),GPU 约 20-30 分钟
|
||
3. **术语纠正很重要**:Whisper 会把"附点"识别为"副点"、"延音"识别为"言音"等
|
||
4. **教学 vs 导读 vs 回顾**:需要综合多种特征才能准确区分,单一指标不可靠
|
||
5. **数字归一化**:Whisper 可能将中文数字识别为阿拉伯数字("十六"→"16"),需要双向匹配
|
||
6. **作业结束检测**:老师口语表达多样,必须用模糊匹配覆盖 30+ 种表达
|
||
7. **GPU 资源管理**:转录完成后必须显式释放模型,否则显存泄漏
|