doco P3-C2: 讯飞ASR适配层接入 + 修复 doco/programs 忽略规则
- C2: asr_adapter 并入讯飞上传/轮询/解析,复用 extract_audio 分离音频, 新增 doco asr 命令读 C1 热词;真转写 ep001 出 310 句带时间戳 - 补提交 C1 代码(llm.py / term_extract.py)与累积词典 - .gitignore: 挡 doco/programs 下 png/wav/mp4 及中间帧目录、本地 settings Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# Doco 子项目续接快照 · 交接给下一轮 Opus 顾问
|
||||
|
||||
> 起草:Opus 4.7 顾问(算力即将耗尽)
|
||||
> 日期:2026-06-12
|
||||
> 给:接手本对话的下一个 Opus 实例
|
||||
> 用户:制片人刘通(《军事科技》栏目 TPS 中台主理人)
|
||||
|
||||
---
|
||||
|
||||
## 一、先看哪些文件(读完这几份再接话)
|
||||
|
||||
主 project 知识库里这几份**必读**:
|
||||
|
||||
1. `Claude协作原则.md` — 跟制片人说话的规矩(简体中文、说人话、不堆叠技术语言、Cline 指令要代码块、宪法第 3 条不架空 Cline 的 Plan 模式)
|
||||
2. `Doco子项目_Brief.md` — Doco 子项目宪法,红线全在这
|
||||
3. `doco_project_design.md` — Doco 算法层设计(P3 阶段才用,但先了解全貌)
|
||||
4. `主project对Doco_PRDv2的回复.md` — 主项目顾问对 5 个问题的批复
|
||||
5. `跨子项目协作规则.md` — PRD 版本管理
|
||||
|
||||
---
|
||||
|
||||
## 二、当前进度坐标
|
||||
|
||||
- **阶段**:Doco P1(视频双路拆分预处理)
|
||||
- **节点**:dry-run 调试,**核心 bug 未解决,不能进入 OCR 阶段**
|
||||
- **git 状态**:多个 commit 已推 origin/main,按宪法直接推 main 不开分支
|
||||
|
||||
P1 任务回顾:
|
||||
- 输入:一期节目视频(黑底白字字幕,干净人声)+ A 稿
|
||||
- 输出:B 稿 txt + audio_16k.wav + keyframes.json
|
||||
- 流程:ffmpeg 抽帧(1fps,crop 到下方 20%全宽)→ 空白帧过滤 → dHash+IoU 去重 → 关键帧 → (OCR)→ B 稿
|
||||
|
||||
---
|
||||
|
||||
## 三、当前 bug 状态(最重要)
|
||||
|
||||
### 已确认未修复的核心 bug
|
||||
|
||||
**`is_blank_frame()` 读取的图像 ≠ `frames/` 目录里最终保存的图像**
|
||||
|
||||
证据链:
|
||||
1. 制片人上传 `frame_0008.png`(从 frames/ 直接复制)
|
||||
2. Opus 用 Python 实测:整张图 414720 像素**全部为 0**(`arr.max() == 0`)
|
||||
3. CSV 报告 frame_8:`max_brightness=255, white_pixel_ratio=0.0124`
|
||||
4. **两者无法同时为真** → 检测时读的不是这张图
|
||||
|
||||
最新 dry-run 自检也证实了这点:
|
||||
```
|
||||
[WARNING] 自检失败: frame_0938.png 像素数据与 CSV 不一致!
|
||||
CSV: max_brightness=255, white_ratio=0.007603
|
||||
实际重读: max_brightness=255, white_ratio=0.022852
|
||||
[error] 已中止
|
||||
```
|
||||
|
||||
### Cline 已经修了但没修对的事
|
||||
|
||||
Cline 把这个 bug 解释成"CSV 列写入顺序错位",但**那只是表层**——
|
||||
列对齐改完后,frame_8 的 CSV 数据 `max_brightness=255、white_ratio=0.0124` 仍然跟"全 0 像素"对不上。
|
||||
|
||||
Cline 已修复(列错位)是真问题,但**根本原因没找到**。
|
||||
|
||||
### 推测根因(交接给你)
|
||||
|
||||
很可能 video_split.py 的抽帧流程是分两步,而不是 ffmpeg 一步搞定:
|
||||
- ffmpeg 把帧抽到某临时目录(可能是全尺寸 1920×1080,**没**裁切)
|
||||
- Python 用 PIL 后裁切到 1920×216 再存到 frames/
|
||||
- `is_blank_frame()` 读的是裁切前的临时全画面(里面有节目画面有亮像素 → max=255)
|
||||
- `frames/` 里是裁切后的小图(字幕区域纯黑 → 像素全 0)
|
||||
|
||||
但这只是**推测**,你应该让 Cline 自查代码确认。
|
||||
|
||||
---
|
||||
|
||||
## 四、下一步建议指令(给你参考,可调整)
|
||||
|
||||
发给 Cline 的 ACT 模式指令,大致这样:
|
||||
|
||||
```
|
||||
[ACT 模式]
|
||||
|
||||
P1 dry-run 自检揪出严重 bug:is_blank_frame() 读的图 ≠ frames/ 里保存的图。
|
||||
|
||||
证据:
|
||||
1. 制片人确认 frame_0008.png 是全 0 纯黑(Python 实测 arr.max()=0)
|
||||
2. CSV 仍报告 max_brightness=255, white_ratio=0.0124
|
||||
3. dry-run 自检也确认 frame_0938.png 数据不一致
|
||||
|
||||
上次"列错位"修复是真 bug 但不是这次的根因,这是另一个独立的 bug。
|
||||
|
||||
请逐行排查 video_split.py 的抽帧流程,回答以下问题(在汇报里贴具体代码):
|
||||
|
||||
1. ffmpeg 命令是什么?是否真的有 vf "fps=1,crop=iw:ih*0.2:0:ih*0.8" 过滤器?
|
||||
2. ffmpeg 输出到哪个目录?
|
||||
3. is_blank_frame() 接收的 image_path 是哪个目录?
|
||||
4. compute_hash() / compute_binary_matrix() 接收的 image_path 是哪个目录?
|
||||
5. 最终保存到 frames/ 的图,是从哪里来的?
|
||||
|
||||
如果发现某个判断函数读了"非 frames/ 里的图",修复方法:
|
||||
- 选项 A:让 ffmpeg 用 vf crop 直接输出裁切后的小图到 frames/,
|
||||
所有判断函数都从 frames/ 读(单一数据源)
|
||||
- 选项 B:保持当前流程,但把所有判断函数的 image_path 改为 frames/ 里的路径
|
||||
|
||||
修复后重新跑 dry-run,自检通过 + 制片人验证 frames/ 里没纯黑帧才算成功。
|
||||
|
||||
不要再加新功能,这次只修这一个 bug。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、协作风格备忘
|
||||
|
||||
- **制片人不懂代码**,你要"说人话",不堆叠 Python 术语
|
||||
- **简明扼要**,他明确要求不要解释中间过程
|
||||
- **给 Cline 的指令一律用 ``` 代码块封装**,方便他复制粘贴
|
||||
- **明确标 ACT 或 Plan 模式**——前几轮制片人提醒过这点
|
||||
- 不要架空 Cline 的 Plan 模式(宪法第 3 条),但小 bug 修复可以直接 ACT
|
||||
- 制片人现在的疲劳度比较高(连续 dry-run 多轮),回复要紧凑,不要长篇大论
|
||||
- 制片人的 git 工作流:直接推 main 不开分支(宪法规定)
|
||||
|
||||
---
|
||||
|
||||
## 六、关键决策(已锁,不能动)
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 字幕裁切区域 | `crop=iw:ih*0.2:0:ih*0.8`(全宽 × 下方 20%),写死,栏目全年 52 期一致 |
|
||||
| 抽帧密度 | 1fps |
|
||||
| 哈希算法 | dHash 默认,阈值 5 |
|
||||
| IoU 保底阈值 | 0.95 |
|
||||
| 空白帧双条件 | `max_brightness >= 240` AND `white_pixel_ratio >= 0.005` |
|
||||
| 凭证管理 | doco 自管 `doco/.env`,主仓库根 `docs/api_credentials_inventory.md` 只记元信息 |
|
||||
| OCR 提供方 | DeepSeek Vision API(P1 dry-run 阶段还没正式调用) |
|
||||
| ASR 提供方 | 讯飞录音文件转写标准版(P2 才用) |
|
||||
| AI 融合层 | Claude Sonnet 4.6(P3 才用) |
|
||||
| 不引入 ffmpeg-python wrapper | subprocess 调系统 ffmpeg |
|
||||
| Git workflow | 按宪法直接推 main |
|
||||
|
||||
---
|
||||
|
||||
## 七、环境信息
|
||||
|
||||
- Windows + Python 3.12.10 + `.venv`(主项目共享虚拟环境)
|
||||
- VS Code + Cline 插件
|
||||
- 仓库根目录:`E:\tps-dashboard\`
|
||||
- 主仓库:`simonkoson/tps-dashboard`(自部署 git,localhost:3000)
|
||||
- ffmpeg:已通过 winget 安装,系统 PATH
|
||||
- demo 视频:`programs/ep001_20260612_fangkong_fandao/source/video.mp4`(《现代防空反导大对决》26 分钟)
|
||||
|
||||
doco 子模块目录结构(已建好):
|
||||
```
|
||||
doco/
|
||||
├── src/
|
||||
│ └── doco/ ← src layout 的包目录
|
||||
│ ├── __init__.py
|
||||
│ ├── cli.py
|
||||
│ ├── video_split.py ← 当前 bug 在这
|
||||
│ ├── asr_adapter.py ← P2 用
|
||||
│ └── ocr_adapter.py ← P2 用
|
||||
├── tests/
|
||||
│ ├── test_video_split.py
|
||||
│ └── fixtures/
|
||||
│ └── mini_test.mp4
|
||||
├── .env.example
|
||||
├── .env(本地,不进 git)
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、踩过的坑(不要重蹈)
|
||||
|
||||
1. **Python 包配置 src layout**:Cline 第一次配置时忘了在 src/ 下建 doco/ 子目录,导致 `doco --help` 报 `ModuleNotFoundError`。后来 git mv 文件到 src/doco/ 下才好。
|
||||
2. **系统 Python vs .venv**:制片人第一次 `pip install -e doco/` 装到了系统 Python 3.12,而不是 .venv 里。VS Code 重启后 .venv 自动激活,需要在 .venv 里重装。
|
||||
3. **VS Code 工作目录**:必须打开 `E:\tps-dashboard\`(仓库根目录),不能打开 `docs\` 子目录,否则 Cline 看不到 .clinerules 和其他子模块。
|
||||
4. **ffmpeg PATH 不生效**:winget 装完 ffmpeg 后,旧的 VS Code 终端 PATH 还是旧的,要完全关闭 VS Code 重开。
|
||||
5. **Cline 的命令示例有错**:Cline 多次给的命令示例是错的(用 `python -m doco.src.doco.cli` + `split-video` 子命令),正确命令是 `doco split --episode-id XXX --input-video XXX --output-dir XXX [--dry-run]`。
|
||||
6. **frames/ 目录的语义**:Cline 第一次实现把 1620 张原始抽帧全部保留在 frames/,让制片人误以为"筛选没生效"。后来改为只保留最终关键帧。
|
||||
7. **pHash 阈值**:dHash 阈值 5,pHash 阈值 2,IoU 阈值 0.95——这些是实测调好的,不要再动。
|
||||
8. **CSV 列对齐**:Cline 加列时只改 header 没改写入顺序导致全部错位。这次修复了,但**不是核心 bug**。
|
||||
|
||||
---
|
||||
|
||||
## 九、最新一次 dry-run 的统计(自检失败那次)
|
||||
|
||||
```
|
||||
[stats] 原始抽帧: 1620 张
|
||||
[stats] 空白帧过滤后: 1393 张 (筛掉 227 张纯黑)
|
||||
[stats] pHash/dHash 去重后(IoU保底): 308 张 (筛掉 0 张IoU相同 + 0 张哈希相同) ← 统计 bug 还在
|
||||
[stats] 最终关键帧: 308 张
|
||||
[debug] frames/ 目录实际文件数: 308 (预期: 308)
|
||||
[WARNING] 自检失败: frame_0938.png 像素数据与 CSV 不一致!
|
||||
[error] 已中止
|
||||
```
|
||||
|
||||
注意:
|
||||
- "筛掉 0 张IoU相同 + 0 张哈希相同" 这个统计还是 0,说明**之前那个 stats 计数 bug 也没真正修好**——或者是这次新加的双条件改变了流程,导致 IoU/hash 没被触发(走了空白帧分支?)。需要复查。
|
||||
|
||||
最近的 commit(按时间倒序):
|
||||
1. Cline 双条件 + 自检 + 测试 + CSV 列对齐
|
||||
2. Cline numpy 加速 + CLI 参数
|
||||
3. Cline IoU 保底 + dHash + 诊断 CSV
|
||||
4. Cline 第一次修空白帧检测(用 brightness=200,后来发现不够,改 240)
|
||||
5. Cline 加 crop 写死 + dry-run flag
|
||||
6. Cline 初始化 doco 子项目 P1
|
||||
|
||||
---
|
||||
|
||||
## 十、给下一个 Opus 的最后嘱托
|
||||
|
||||
- 这个 bug 排查过两轮了(Cline 都没真正定位到),所以这次**让 Cline 自查代码并贴出关键函数的实际代码**,不要轻信他的口头解释
|
||||
- 制片人有耐心,但已经累了,你接手后**第一句话就给方案,不要重复诊断**
|
||||
- 修完这个 bug 后,P1 dry-run 应该能通过自检,接下来就是填 DeepSeek API key 跑正式 OCR(去掉 --dry-run)
|
||||
- 如果 dry-run 通过,P1 就算完工,可以进入 P2(讯飞 ASR 集成)
|
||||
|
||||
祝接力顺利。
|
||||
Reference in New Issue
Block a user