1372600d71
- 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>
7.1 KiB
7.1 KiB
Doco 子项目 · P1 完工快照 · 交接给 P2(OCR 阶段)
起草:Opus 顾问(本对话) 日期:2026-06-15 用户:制片人刘通(《军事科技》栏目 TPS 中台主理人) 上一份:
doco_handoff_to_next_chat.md(P1 调试中,bug 未解) 状态:P1 dry-run 已通过自检与人工验收,P1 完工
一、一句话总结
P1(视频双路拆分预处理)的抽帧→空白过滤→去重→关键帧流水线已跑通并通过全部验收,可进入 OCR 阶段。OCR 选型方向已更正为本地部署 DeepSeek-OCR(经 Ollama)。
二、P1 做了什么
- 输入:一期节目视频(黑底白字字幕 + 干净人声)+ A 稿
- 本阶段产物:
frames/(308 张字幕关键帧)+ keyframes 数据;音轨/B 稿是后续阶段 - 流程:ffmpeg 抽帧(1fps,crop 到下方 20% 全宽)→ 空白帧过滤 → dHash + IoU 去重 → 关键帧
- demo 视频:《现代防空反导大对决》(26 分钟)
三、本轮修复的 3 个 bug(都已修好、已验收)
交接前的核心卡点是「is_blank_frame() 读的图 ≠ frames/ 里的图」,自检反复中止。逐层挖下去,实际是三个独立 bug:
bug 1 · off-by-one 索引错位(核心)
- 根因:
extract_frames()用enumerate()从 0 开始编号(frame_index 0-based),但下游清理逻辑和自检逻辑都从文件名提取 1-based 编号(frame_0008.png→ 8),两套编号差 1。 - 后果:空白帧因编号错位被错误保留;自检重读图片取到正确像素,却去查 CSV 错误的行 → 报告不一致、中止。
- 不是"读了不同目录的图"——所有判断函数始终从同一个 frames/ 读图,是编号体系不一致。
- 修复:改为直接从文件名提取 1-based 编号。commit
bc5a30e
bug 2 · 去重计数器恒为 0
- 根因:
decision_stats[...] = decision_stats.get(..., 0)缺了+ 1,每次迭代没递增。 - 后果:统计永远显示"筛掉 0 张 IoU + 0 张哈希",看起来像去重没生效。但去重逻辑本身一直是对的,只是计数显示错。
- 修复:加
+ 1。commitd55f029
bug 3 · 2 个失败的单元测试(均与本次修改无关的旧断言问题)
test_subtitle_frame:切片比例写错(注释说 1% 实际取了 10%),修改前就在失败。改arr[:100,:10]→arr[:10,:10]。test_ratio_ok_but_max_brightness_too_low:亮度阈值从 200→240 后,亮度 220 的像素不再算白像素,旧断言没同步。改断言为white_ratio == 0.0。- 修复:commit
82973a7,17/17 全过。
四、验收数据(已核对,数字闭环)
本次 dry-run 全帧去向(1620 帧):
| 类别 | 张数 |
|---|---|
| 空白帧(blank) | 227 |
| IoU 重复(duplicate-iou) | 321 |
| 哈希重复(duplicate-hash) | 764 |
| 首帧保留(kept) | 1 |
| 关键帧(keyframe-hash) | 307 |
| 合计 | 1620 ✅ |
- 最终关键帧 = 1 + 307 = 308 张,与
frames/实际文件数一致。 - 旁证:demo 这期约 300 条字幕,关键帧 308 ≈ 字幕数,基本一对一,说明去重准确(每条字幕保留一张、砍掉重复画面)。
- 人工验收:制片人手动翻遍 frames/,确认无任何纯黑帧。
- 单元测试:17/17 通过。
五、遗留小尾巴(不影响完工,有空再收)
test_ratio_ok_but_max_brightness_too_low这个测试名与它现在实际测的行为对不上了(白像素阈值提到 240 后,原本想测的"白像素够但亮度不够"场景已构造不出来,断言被改成了 white_ratio==0)。建议以后让 Cline 给这个测试改名或重构。纯属测试整洁度,不影响流水线正确性。
六、重要更正 · OCR 选型(覆盖 PRD v2 的 Q1 表述)
PRD v2 写的"DeepSeek 有 OCR 模型 + Vision 识图模式(官方 API endpoint)"——这条事实有误,作废。
查证结果(2026-06-15,DeepSeek 官方文档):
- DeepSeek 官方 API 只有
deepseek-v4-flash/deepseek-v4-pro两个模型,纯文本,不收图像输入(功能仅:文本对话 / Tool Calls / JSON 输出 / FIM)。Cline 里 DeepSeek 预设没有 image 选项是正常的,不是配置漏项。 DeepSeek-OCR(3B,中文文档识别强)是开源模型,只能本地部署(vLLM 或 Ollama),没有现成云端 API,需自备 GPU。- 因此制片人手上的 DeepSeek API key 调不了 OCR。
新方向(已与制片人确认):本地部署 DeepSeek-OCR,经 Ollama 运行。
- 理由:制片人有 RTX 4090D 24GB(跑 3B OCR 模型富余);零调用成本、不限量;栏目全年 52 期常态化使用,长期划算;且制片人另有一个离线小机房,只能用本地方案,云端 API 调不通。
- Windows 上优先 Ollama(原生支持、免 WSL),不碰 vLLM(Windows 上一般要 WSL,门槛高)。
候选备选(若本地部署受阻):MiniMax-VL 云端 API、讯飞 OCR。但离线小机房只能本地。
七、下一步(P2 / OCR 阶段)
- 本地部署 DeepSeek-OCR(Ollama):在制片人栏目主机上搭起来,确认能识别黑底白字字幕关键帧;之后同样流程部署到离线小机房。
- OCR 适配层
ocr_adapter.py:把 308 张关键帧批量送入本地 OCR 服务,产出带[Nm Ns]时间戳的 B 稿 txt(格式必须与旧版完全一致,下游 P3 才零侵入)。 - 去掉
--dry-run,跑正式 OCR,产出 B 稿 + audio_16k.wav + keyframes.json,P1 整体产物齐活。 - 之后才进 P2 的讯飞 ASR 适配、P3 的 Claude 融合层。
八、关键决策(已锁,沿用)
| 项 | 值 |
|---|---|
| 字幕裁切区域 | crop=iw:ih*0.2:0:ih*0.8(全宽 × 下方 20%),写死,全年 52 期一致 |
| 抽帧密度 | 1fps |
| 哈希算法 | dHash 阈值 5,pHash 阈值 2 |
| IoU 保底阈值 | 0.95 |
| 空白帧双条件 | max_brightness >= 240 AND white_pixel_ratio >= 0.005 |
| 凭证管理 | doco 自管 doco/.env,主仓库根 docs/api_credentials_inventory.md 只记元信息 |
| OCR 提供方 | 本地 DeepSeek-OCR(经 Ollama) ← 本次更正,原 PRD 的"DeepSeek 云端 Vision API"作废 |
| ASR 提供方 | 讯飞录音文件转写标准版(P2 才用) |
| AI 融合层 | Claude Sonnet 4.6(P3 才用) |
| 抽帧/抽音轨 | subprocess 调系统 ffmpeg,不引入 ffmpeg-python |
| Git workflow | 按宪法直接推 main,不开分支 |
九、环境信息
- Windows + Python 3.12.10 +
.venv(主项目共享虚拟环境) - VS Code + Cline 插件(编程模型已从 Minimax M3 换为 deepseek-v4-pro,响应更快)
- 仓库根:
E:\tps-dashboard\(VS Code 必须打开仓库根,不能打开子目录) - 主仓库:
simonkoson/tps-dashboard(自部署 git,localhost:3000) - ffmpeg:winget 安装,系统 PATH
- GPU:NVIDIA RTX 4090 D 24GB(本地 OCR 部署用)
- 另有一台离线小机房(无外网,本地部署的主要落地环境之一)
- 正确 CLI:
doco split --episode-id XXX --input-video XXX --output-dir XXX [--dry-run]
十、本轮 commit(按时间)
| commit | 内容 |
|---|---|
bc5a30e |
extract_frames:frame_index 从 0-based enumerate 改为 1-based 文件名提取(核心 bug) |
d55f029 |
decision_stats 计数加 + 1(去重计数器恒为 0) |
82973a7 |
修复 2 个测试断言(切片比例 + 阈值适配),17/17 通过 |
P1 至此完工。下一轮从「Ollama 本地部署 DeepSeek-OCR」开始。