# 项目协作主控文件 (doco/CLAUDE.md)

<!--
  Claude Code 每次开 session 自动读取。两个角色：

   1. 给 AI 的项目说明书（项目是什么、用什么、怎么跑）

   2. 双账号/多工具之间的"活快照"交接区（现在到哪了、下一步、刚做的决定）
        维护原则：增量更新，不要整篇重写。改动写进对应小节即可。

   3. 每次结束session或通哥明确说结束今天的工作，应由Claude修改更新本文件，交接备注和待确认等部分内容应为最新。

      -->

---

## 🔖 状态栏 (STATUS — 每次结束 session 前必须更新这三行)

- **最后更新**：账号A ｜ 2026-06-17
- **当前状态一句话**：P3-C2 讯飞 ASR 跑通并收口（真转写310句带时间戳，热词命中良好），本轮已 git 提交推 main（9340edc）；**B稿_v2.txt 已就位入库，C3 卡点解除，下一步可直接开 C3**。
- **下一个动手的人从这里开始**：见下方「⏩ 交接备注」

---

## 🤖 给 AI 的工作约定 (READ FIRST)

- 开始任何工作前，先读完本文件，特别是「状态栏」「交接备注」「关键决策」三节。
- 完成一段工作后**增量更新**：「已完成」追加一条、「待办」勾掉或新增、必要时更新「关键决策」，最后改「状态栏」三行。不要重写整份文件，不要删历史，只追加/勾选。
- 涉及发送、发布、删除、改权限、付款等不可逆操作前，先在对话里跟通哥确认。
- **本文件与项目设计文档并列，构成 doco 子项目宪法。冲突时优先级：本文件 STATUS/交接 > `doco_P3续接快照_C1完工C2起步.md` > `doco_P3_设计稿.md` > `doco_project_design.md`（越新越权威，尤其"LLM 提供方"那条以快照为准）。** 新对话接手时连同上述文档一并阅读。

------

**Claude（Opus 高级技术顾问）与制片人刘通协作原则**

1. 全程使用简体中文。
2. 通哥不懂代码编程，解释要简明扼要，说人话，不堆术语。
3. 为了节省Claude的Token，你主要的工作是plan和审核cline的报告，除非cline3次及以上修改过不去的坎，你可以直接动手改代码。
4. 给 Cline 的指令一律用代码块封装，并明确标 ACT / Plan，方便复制。
5. 回复简明扼要，不解释太多中间过程；**独立核验 Cline 自报结果，对着源数据查证，不轻信口头诊断**（本项目已多次靠核验抓到 Cline 偷换模型/术语源、误判字数）。
6. 长批处理（OCR/ASR）放独立终端跑，不要让 Cline 盯。
7. git 直接推 main，不开分支。

---

## 1. 项目概览

- **项目名**：doco 文稿整理模块（《军事科技》TPS 工作台子模块）
- **目标**：把 **A稿（编导定稿）+ B稿v2（屏幕字幕，P2 产出 743 行）+ ASR（口语实况）** 三方交叉融合，产出两个内容一致、形态不同的交付物：
  - **融合B稿**（给爱德华）：碎句 + 密集字幕级时间戳 `[XmYs] 文本`
  - **融合A稿**（给编导）：公文格式 docx，保留【导视】【主持人N】【解说N】【专家N】【隔断】分段
  - 一致性约束：融合A稿**由融合B稿生成**（按 A 稿分段归拢 + 套格式），不是事后比对硬凑。
- **范围边界（别越界去做）**：本模块只做"三方文本 → 终版"。**不做** OCR 识别（P2 已产出 B稿v2）、**不做**音频转码本身（属 ASR 适配层）、**不做**档案入库、**不做**编导确认 UI。

---

## 2. 技术栈与运行方式

- **语言**：Python（openai SDK 走 DeepSeek 兼容端、ffmpeg、python-docx）
- **关键目录**：
  - `src/doco/llm.py` — DeepSeek 统一客户端，`chat(messages, model=None, thinking=None, max_tokens=...)`，从 `doco/.env` 读 key/base_url/model
  - `src/doco/term_extract.py` — C1：规则层 + AI 层提取 + 词典累积 + 热词清洗
  - `src/doco/asr_adapter.py` — C2 讯飞 ASR 适配层（已完工）：`get_hot_words(episode_id)` 读热词表、`transcribe()` 返回 `(句子, raw)`、`write_asr_result()` 落 `asr_v2_timed.txt` + `asr_result_raw.json`
  - `src/doco/video_split.py` — P1：含 `extract_audio()`（16kHz/单声道/16bit WAV），C2 直接复用，不另写 ffmpeg
  - `src/doco/cli.py` — 命令入口（split / terms / asr）
  - `doco/data/term_dict.json` — 累积词典（当前 110 条）
  - `doco/programs/<episode_id>/` — 每期产物（热词表、各阶段输出）
- **常用命令**：
  - C1（已实现）：`doco terms --episode-id <id> --a-script <path> [--no-ai]`
  - C2（已实现）：`doco asr --episode-id <id> --input-video <绝对路径mp4> --output-dir <绝对路径 doco/programs/<id>>`（`--skip-asr` 只分离不转写）。**务必传绝对 `--output-dir`，否则落到当前工作目录的 `programs/` 会与 doco 产物分家。**
  - C3/C4：待实现
- **环境变量 / 密钥**：只放 `doco/.env`（已在 `.gitignore`）。需要的 key：`DEEPSEEK_API_KEY` / `DEEPSEEK_BASE_URL` / `DEEPSEEK_MODEL`、`XFYUN_APP_ID` / `XFYUN_SECRET_KEY`。**代码与对话里只引用变量名，绝不出现真值。**

---

## 3. 当前进度（核心交接区，以最新快照为准）

- **正在做**：C2 已收口并推 main，准备进 C3（B稿v2 ⊕ ASR 交叉复审）。
- **卡点 / 待解**：无。C3 三路输入均已就位于 `doco/programs/ep001_20260612_fangkong_fandao/`：`B稿_v2.txt`（743行，P2）、`asr_v2_timed.txt`（310句，C2）、A稿 docx。

---

## 4. 已完成（只追加，最新在最上）

- [2026-06-17 ｜账号A] **P3-C2 收口**：密钥外置三验收点全过（硬编码已删/读 .env/已 gitignore）+ 旧 key 已轮换；`asr_adapter.py` 并入讯飞上传·轮询·解析，复用 P1 `extract_audio` 分离 16kHz/单声道/16bit WAV；新增 `doco asr` 命令读 C1 64条热词。**真转写《现代防空反导大对决》27分钟音频 → 310句带时间戳**，萨德×6/塔米尔/爱国者/箭二箭三/见证者等术语命中良好，raw json 730KB 落盘。（顺带修 `extract_audio` 在 Windows 的 `text=True` 解码崩溃。）
- [2026-06-16 ｜账号A] **P3-C1 收口**：A稿→规则+DeepSeek AI 提取→累积词典110条→热词清洗→本期热词表64条；AI 44 候选已逐个回查 A 稿原文无幻觉，算术对账一致。
- [P2 ｜本轮之前] 本地 OCR（DeepSeek-OCR/Ollama）+ 扒词流水线，产出 **B稿_v2.txt 743 行**。
- [P1 ｜本轮之前] 帧筛流水线完工。

---

## 5. 待办（按优先级，做完打勾）

- [ ] **C3（下一步，输入已齐）**：B稿v2 ⊕ 新ASR 交叉复审 → 融合B稿（保持743行碎句粒度 + 密集时间戳原样，ASR只复审纠错不改行结构）+ `fusion_review.csv`。
- [ ] **C4**：融合B稿 + A稿语义对齐 → 融合A稿（公文 docx，用 docx skill，GB/T 9704 格式）。
- [x] **C2** 讯飞 ASR 适配层（密钥外置 + asr_adapter 并入 + `doco asr` 命令 + 真转写310句）
- [x] P3-C1 术语提取 + 词典 + 热词表
- [x] P2 本地 OCR + B稿v2
- [x] P1 帧筛

---

## 6. 关键决策（为什么这么做 — 跨 session 最易丢，别推翻）

- [2026-06-17] **C2 音频分离复用 P1 `video_split.extract_audio()`，不另写 ffmpeg。** WAV 落 `programs/<episode>/audio_16k.wav`，已存在则复用（避免 1GB 视频重复解码）。实测产物 `pcm_s16le/16000Hz/1ch/16bit/1620s`，符合讯飞硬要求。
- [2026-06-17] **`doco asr` 不传 `--output-dir` 会落到当前工作目录的 `programs/`**（命令在 repo 根 `E:\tps-dashboard` 跑时尤其坑），与 doco 产物分家。**命令一律用绝对 `--input-video` + 绝对 `--output-dir`。**
- [2026-06-17] **ASR 输出是口语形态，型号不规范属正常**（如「箭二箭三」非「箭-3」、「高超音速/高超声速」混用）。按设计稿口语信 ASR、型号规范信 A/B 稿，**这些归一交给 C3，别回头改 C2**。
- [2026-06-16] **AI 融合层 LLM = DeepSeek v4-pro，不是 Claude。** 制片机无 Anthropic key；DeepSeek key 现成。接入：OpenAI 兼容，`base_url=https://api.deepseek.com`、`/chat/completions`、模型名走 `DEEPSEEK_MODEL=deepseek-v4-pro`。C1、C4 都用它。**（此条覆盖 `doco_P3_设计稿.md` 里写的 Claude API。）**
- [2026-06-16] **抽取类任务必须关 thinking。** DeepSeek V4 默认开 thinking，不关则正文 `content` 为空（已踩坑）。做法：`chat(..., thinking=False)` → `extra_body={"thinking":{"type":"disabled"}}`，给足 `max_tokens`（C1 用 4000）。**C4 语义融合可开 thinking**（单轮调用，质量优先）。
- [2026-06-16] **旧模型名 `deepseek-chat`/`deepseek-reasoner` 禁用**（2026-07-24 退役且现指向 flash）。只认 `deepseek-v4-pro`。Cline 曾擅自退回 deepseek-chat，已纠正。
- [2026-06-16] **C1 术语源 = A稿（规范写法），不是 B稿。** Cline 曾擅自换成 B稿v2，已纠正。
- [2026-06-15] **讯飞用「录音文件转写标准版」，不要大模型版**（免费包阉割 `language` 参数，会报误导性 `language verify fail`）。参数锁定：`pd=mil`、`eng_smoothproc=true`、`eng_colloqproc=true`、`hotWord=<C1热词>`、`language=cn`。签名 `signa=base64(HmacSHA1(MD5(appid+ts), secretKey))`；`/upload` 拿 orderId，轮询 `/getResult` 到 status=4。
- [2026-06-15] **B稿v2 权威升级**：屏幕术语/型号/番号 **B稿v2 ≈ A稿 并列权威**（B稿是屏幕实打的字，更贴近播出）。口语/语序/语气信 ASR；书面结构/分段信 A稿；同音事实错（美以→美伊）用 A稿/B稿v2 覆盖 ASR。
- [设计期] **分层不变**：OCR 错字纠正、术语统一、时间戳对齐走**规则层**（确定性）；段落归属、整段删除判定、编导笔误识别走 **AI 层**（需语义判断）。
- [设计期] **顺序约束**：术语提取（C1，产热词）必须在 ASR（C2）之前——已成立。
- [工程纪律] 各阶段解耦、中间产物落缓存、可断点续跑、可单独重跑；长批处理放独立终端。

---

## 7. ⏩ 交接备注（写给下一个接手的 session）

> 下次开工读完这段应能 0 摩擦续上。接手后可清空重写。

- **第一句话该干的**：C2 已收口推 main，C3 三路输入已齐（`B稿_v2.txt` 743行 / `asr_v2_timed.txt` 310句 / A稿 docx，都在 `doco/programs/ep001_20260612_fangkong_fandao/`）。直接给 Cline 出 C3 的 ACT 指令开工。
- **C3 目标**：B稿v2 ⊕ asr_v2_timed 交叉复审 → 融合B稿（**保持 743 行碎句 + 密集时间戳原样，ASR 只复审纠错不改行结构**）+ `fusion_review.csv`。权威优先级见关键决策「B稿v2 权威升级」那条。
- **重跑真转写命令**（复用已分离 WAV，27分钟音频讯飞轮询等几分钟别中断）：
  `doco asr --episode-id ep001_20260612_fangkong_fandao --input-video "E:\tps-dashboard\doco\programs\ep001_20260612_fangkong_fandao\现代防空反导大对决VA0.mp4" --output-dir "E:\tps-dashboard\doco\programs\ep001_20260612_fangkong_fandao"`
- 通哥连轴转了几轮，回复要紧凑。
- **已知坑（务必记住）**：
  1. **A稿真实约 6500–7300 汉字**（栏目常态 6000–8000），**不是 2.2 万**——那是用 `wc -m` 把 UTF-8 字节当字数的乌龙（一个汉字 3 字节）。docx 无文本框无表格，`python-docx` 提取的 ~7.5k 字符就是全文。
  2. **A稿分段编号有坑**：解说2/解说10 各出现两次、主持人4/5 带空格、专家1–8 齐全。分段对齐**别假设编号单调或唯一，按出现顺序走**（顾问曾误说"跳6号"，作废）。
  3. Cline 会偷换模型/术语源、误判字数——**自报结果一律对源数据核验**。
- **C1 已知小尾巴（评估后不修，无害）**：热词条数报告 64、顾问数 65，差 1，远在 200 上限内；几对技术前缀未合并（光学红外/红外、诱饵弹前缀等），再收敛有过度合并风险，故止步。
- **C4 字体坑**：大标题用方正小标宋（商业字体），出稿前确认制片机/编导机已装，否则脚本里配回退（标宋→宋体加粗）。

---

## 8. 待确认 / 开放问题（需通哥拍板，AI 别自行假设）

- ~~**B稿_v2.txt 就位**~~：已完成（通哥已拷进 episode 目录并随 9340edc 入库）。
- ~~**讯飞旧 key 轮换**~~：已完成（新值已在 `doco/.env`，旧 appid `84eff996` 代码内无残留）。
- **方正小标宋字体可用性**：C4 出稿前确认两台机器是否已装。
- **OCR 并发提速**（P2 遗留）：`OLLAMA_NUM_PARALLEL` 4–8 路，预计把 ~30 分钟压到十分钟出头；**correctness 全部验证后再做**，现在不动。
- **讯飞单源依赖**（远期）：是否接阿里云 ASR 做备份/交叉验证。