Files
tps-dashboard/doco/CLAUDE.md
T
2026-06-22 14:37:52 +08:00

184 lines
28 KiB
Markdown
Raw 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.
# 项目协作主控文件 (doco/CLAUDE.md)
<!--
Claude Code 每次开 session 自动读取。两个角色:
1. 给 AI 的项目说明书(项目是什么、用什么、怎么跑)
2. 双账号/多工具之间的"活快照"交接区(现在到哪了、下一步、刚做的决定)
维护原则:增量更新,不要整篇重写。改动写进对应小节即可。
3. 每次结束session或通哥明确说结束今天的工作,应由Claude修改更新本文件,交接备注和待确认等部分内容应为最新。
-->
---
## 🔖 状态栏 (STATUS — 每次结束 session 前必须更新这三行)
- **最后更新**Claude Code 2026-06-22(晚,收摊)
- **当前状态一句话**:**ep002(潜艇仿生)P1→P2→C1→C2→C3 已完成,C4 compose 正在由 Cline 跑**MiMo 2.5 Pro)。C4 跑完后需审核报告(硬校验/空段/标点回退)。ep004 上游仍全空。另有一个待做事项:为编导制作 doco 全流程可视化图(HTML),方便试用前培训。
- **下一个动手的人从这里开始**:见下方「⏩ 交接备注」
---
## 🤖 给 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. 技术栈与运行方式
- **语言**Pythonopenai 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/fusion_review.py` — C3:B稿v2 ⊕ ASR 交叉复审 → 融合B稿(743行) + fusion_review.csv
- `src/doco/cli.py` — 命令入口(split / terms / asr / fuse
- `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(已实现):`doco fuse --episode-id <id> [--no-ai] [--batch-size 35]`
- C4:待实现
- **环境变量 / 密钥**:只放 `doco/.env`(已在 `.gitignore`)。需要的 key`LLM_API_KEY` / `LLM_BASE_URL` / `LLM_MODEL`(已切换到小米 MiMo 2.5 Pro)、`XFYUN_APP_ID` / `XFYUN_SECRET_KEY`。**代码与对话里只引用变量名,绝不出现真值。**
---
## 3. 当前进度(核心交接区,以最新快照为准)
- **正在做**:批量化首批三期。**ep002 已完成 P1→P2→C1→C2→C3**C3 融合B稿 733行/10条review/专名无同音替换),**C4 compose 正在 Cline 跑**。ep004 上游仍全空(只有骨架)。
- **卡点 / 待解**:无硬卡点。C4 跑完后需审核(下个 session 首要任务)。
---
## 4. 已完成(只追加,最新在最上)
- [2026-06-22 Claude Code] **ep002 C3 融合通过**。融合B稿 733行(零偏移),review 10条(5 minor_edit 全是 OCR 错字修正,专名无同音替换)。C4 compose 交 Cline 跑中。
- [2026-06-22 Claude Code] **ep002(潜艇仿生)P1→P2→C1→C2 完成**。P1 全量抽帧 1620 帧(不做 dHash/IoU 去重,全部进 OCR);P2 OCR 4路并发首秀通过(~50帧/分钟,约串行3倍),Stage B 文本去重出 B稿v2 733行;C1 术语提取 68 条热词(词典累积至 235 条);C2 讯飞 ASR 411 句。下一步 C3 fuse。
- [2026-06-22 Claude Code] **标点层 prompt 修复 + ep003 重跑出稿**`PUNCTUATE_SYSTEM_PROMPT` 加第5条规则(陈述句结尾用句号)+ 错误/正确示范。ep003 逗号占比从 88% 降至 76%,句号从 70 涨到 118。红线未破(strip_punct 硬校验通过)。commit `fd2ef1a`
- [2026-06-22 Claude Code] **LLM 提供方从 DeepSeek 切换到小米 MiMo 2.5 Pro**。环境变量名 `DEEPSEEK_*``LLM_*`(通用化),涉及 llm.py / term_extract.py / video_split.py。API 已验证连通。commit `9948b7d`
- [2026-06-22 Claude Code] **Ollama 并发配置完成**`OLLAMA_NUM_PARALLEL=4` + 重启)。4090D 24G 显存充裕(OCR 时 GPU 利用率仅 2%),后续可提到 8 路。
- [2026-06-18 晚 |账号A] **ep003(小尺寸大讲究)批量首期·全流程端到端跑通**P1→P2→C1→C2→C3→C4 六阶段)。产出 `20260331枪械设计中的小尺寸大讲究_孙逸昊_融合A稿.docx`。逐阶段实测数:P1/P2 出 **B稿_v2.txt 698 行**OCR 串行,未用并发);C1 出 **60 热词**(词典累至 172 条,AI 候选回查 A稿无幻觉);C2 讯飞真转写 **278 句带时间戳**(热词偏置生效,型号命中良好);C3 fuse 698 行零偏移、仅 1 处 minor_edit、留痕 1 条;C4 compose 20 段、硬校验**汉字零改逐段通过**、1 处标点回退(seg_6)。**核验三连**:① **4 个空段(seg1518:主持人7/解说8/主持人8/解说9)确认是播出剪掉的 VSS 微声狙击枪 + NTW-20 南非大炮整段**——融合B稿里 VSS/NTW/南非/消音/反器材**零出现**seg14 边界抽查(593681 全 HK416、682 起进结束语)证对齐正确,非 bug;② **C3 同音字坑已抓修**LLM 把权威 B稿"斯泰尔"按 ASR 同音盖成"斯太尔"(519 行),已改回,与 487 行及 A稿一致;③ **出稿命名生效**——`{原A稿stem}_融合A稿.docx`,不覆盖原始定稿。**本期间改的代码**:(a) `stage_a_extract_ocr.py` 修 GBK 崩溃(ffmpeg 子进程加 `encoding=utf-8,errors=replace`)+ 去掉 A3 硬编码 ep001 台词断言改通用中文冒烟检查 + **加并发 OCR(ThreadPoolExecutor/`OCR_NUM_WORKERS`默认4/idx-set 续跑)**——并发**未在 ep003 实跑**(ep003 走串行)ep002 首秀;(b) `fusion_align.py` a_candidates glob 排除"融合/批改"稿(防重跑把自己输出当输入) + 出稿改名带原稿信息。
- [2026-06-18 |账号A] **A稿解析器升级:正则 → LLM分段骨架 + 人工确认 + ignore合并**。起因:量产三期(ep002/003/004) A稿格式与 ep001 天差地别(冒号头/正文同段、`【固摇轨】`镜头标记酷似段头、正文整段加粗、小剧场对话角色头),原 `parse_a_segments` 纯正则(`^【.+?】$`)必散架。新机制(`fusion_align.py`)`extract_a_paragraphs`(带 bold/align 样式) → `extract_skeleton_llm`(thinking=True/max_tokens足量,**LLM 只判结构不碰正文**,输出 type/role_label/para 区间 JSON) → `validate_skeleton_coverage`(全覆盖硬校验,抓 LLM 数错下标/JSON 截断) → 落 `<id>_a_skeleton.json` + 人类预览表 → `parse_a_segments` 改读骨架按下标原样抽正文(inline 头切冒号、standalone 头取后续段、**ignore 段丢弃**、**相邻同 role_label 仅隔 ignore 的 normal 段合并**)。新命令 `doco skeleton --episode-id <id> --a-script <docx>`。**三期骨架已产并人工核验通过**:人名零泄露(刘通/孙逸昊/左鑫/穆佩弦/主持人真名都没混进 role_label)、覆盖完整、ep002 四隔断认对、ep003 九个`(出枪柜)`等归 ignore 且主持人被运镜切断后正确合并(37→20段)、ep004 小剧场卡/斯角色保留。ep001 无骨架时仍走旧正则 fallback,不受影响。
- [2026-06-18 |账号A] **P3-C4 第一批(保守版)收口**`fusion_align.py` 把融合B稿743行碎句按 A稿 28 段(含 4 隔断)对齐归拢,套公文 docx 出稿 `融合A稿.docx`。**两条铁律守死**:①汉字零改——正文 100% 来自融合B稿;②标点由 LLM 按语义增删(一逗到底→正常断句)。机制:(a) **AI 对齐层**喂完整 A稿正文、seg_id 单调不减、thinking=True/4096、缓存 `.c4_cache/batch_N.json`(b) **标点层** `punctuate_segment` 用 STRICT prompt(只许插标点、禁增删改字)+ 硬校验 `strip_punct(出)==strip_punct(入)` 不过即 3 次重试、再不过回退裸文本进 review,缓存 `punct_seg_N.json`thinking=False/3000。**红线核验脚本逐段 strip_punct 比对 28/28 全过**diff 全 equal)。隔断按 `^隔断:【(.+?)】` 正则识别、独立成段、line_count=0、位置正确(解说1/主持人2/3/4 后各一)。标点 `punct_ok` 26/28seg8(专家2)、seg27(专家7) 两段 LLM 顽固插连接词触发回退、已落裸文本+标记"需人工",归第二批。产物:`融合A稿.docx` + `c4_alignment.csv`32行对齐表,含 start/end_line、confidence、punct_ok、note)。命令 `doco compose --episode-id <id>`
- [2026-06-17 |账号A] **P3-C3 收口**`fusion_review.py` 逐行复审 B稿v2 ⊕ ASR(22 批×35行=743行),产 `融合B稿.txt`(行数/时间戳零偏移)+ `fusion_review.csv`(5条真OCR纠错留痕)。关键机制:断点缓存 `.c3_cache/batch_N.json` 可复用;硬校验行数/时间戳/change_type枚举不过不写文件;后处理修正 `final_text==B原文` 被 LLM 误标为 `minor_edit` 的行(19→5)。`--no-ai` 全 unchanged 可验证管道。
- [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 |本轮之前] 本地 OCRDeepSeek-OCR/Ollama+ 扒词流水线,产出 **B稿_v2.txt 743 行**
- [P1 |本轮之前] 帧筛流水线完工。
---
## 5. 待办(按优先级,做完打勾)
- [x] **C3**:B稿v2 ⊕ ASR 交叉复审 → 融合B稿(743行时间戳零偏移) + fusion_review.csv(5条留痕)。
- [x] **C4(全部收口)**:融合B稿按 A稿28段对齐归拢 → 融合A稿 docx(公文格式)。汉字零改 + LLM 按语义加标点,红线 28/28 段逐字一致。`doco compose --episode-id <id>`。**OCR 漏字决定不补**(讨论见关键决策);seg8/seg27 两段标点接受一逗到底。
- [x] **A稿解析器升级**:正则 → LLM分段骨架+人工确认+ignore合并;三期骨架已产并核验通过。`doco skeleton`
- [~] **批量化首批三期·跑完整流水线(下一步主线)**ep003 已全流程跑通。**ep002 已完成 P1→P2→C1→C2,下一步 C3 fuse → C4 compose**。ep004 上游仍全空(只有骨架),需跑完整 P1→C4。stage 脚本从 ep003 复制。
- [x] **【已完成】标点层 prompt 修复**:加第5条规则+示范,ep003 逗号占比 88%→76%commit `fd2ef1a`
- [x] **【已完成】配 Ollama 并发**`OLLAMA_NUM_PARALLEL=4`ep002 OCR 4路实跑通过,~50帧/分钟。
- [ ] **【产品 backlog】原稿缺【专家N】/【三维动画N】标签**:ep003 复查发现编导原稿里就没有专家、后续三维动画的分段标注,骨架如实反映=融合A稿里也没有(通哥手工补了高亮)。不赖程序(原稿零信号,LLM 与人一样猜不准),**不让程序猜**。治本=提醒编导/责编原稿把【专家N】等段头标全;50 期前在导入须知里写清。
- [ ] **【backlog】C3 prompt 收紧**:专有名词(厂名/型号/番号)遇 ASR 同音异写,必须以 B稿v2/A稿为准、不许采 ASR——ep003 已踩"斯泰尔→斯太尔",50 期批量前在 prompt 里收紧防复发。
- [ ] **串一键脚本**:把 C1→C2→C3→C4 串成"一条命令跑一期"(薄壳,各阶段已有断点缓存),验 2-3 期稳定后再谈监控文件夹/绑定界面。
- [ ] **骨架小瑕疵 backlog(不拦路,后期顺手或跳过)**:ep002 演播室主持人 vs 主持人 是否统一;ep004 小剧场角色编号乱(斯9/斯通纳10、卡8跨场)直接改 JSON 即可,不必重调 LLM;ep003 行内`【固摇轨】`留在参照正文(无害,不进输出)。
- [x] **C2** 讯飞 ASR 适配层(密钥外置 + asr_adapter 并入 + `doco asr` 命令 + 真转写310句)
- [x] P3-C1 术语提取 + 词典 + 热词表
- [x] P2 本地 OCR + B稿v2
- [x] P1 帧筛
---
## 6. 关键决策(为什么这么做 — 跨 session 最易丢,别推翻)
- [2026-06-18] **A稿段头识别改用「LLM 判结构 + 人工核骨架」,不用死正则。** 编导写法千变万化(方括号/冒号/前缀杂质`Xr`/`【固摇轨】`镜头标记/小剧场对话头),正则分不清`【固】`(镜头)与`【主持人1】`(段头)——这是语义判断,交 LLM。**铁律:LLM 只输出结构(type/role_label/para 区间),绝不复述正文;正文一律代码按下标从 docx 原样抽**(护住"汉字零改"红线)。配两道闸:① `validate_skeleton_coverage` 全覆盖硬校验(title 后每段恰好被覆盖一次,自动抓 LLM 数错下标/JSON 截断);② 人类预览表给制片人肉眼核(重点抓真人姓名泄露/ignore 漏多/隔断认全)。`doco compose` 无骨架即报错(ep001 例外走正则)。
- [2026-06-18] **role_label 只标"段落类型",严禁带任何真人姓名/配音员/编导署名。** 解说词只标【解说N】,不标谁配音(踩过 Cline 把"解说:刘通"标错)。但**小剧场里被演绎的历史人物/角色保留**(卡=卡拉什尼科夫、斯=斯通纳、小剧场N-主持人)——那是剧情内容不是配音员实名。有借鉴价值的修饰也留(三维动画解说/演播室主持人),只清杂质(`Xr`/编号/空格)。
- [2026-06-18] **解析层合并"被 ignore 隔断的同角色段"。** 编导用`(出枪柜)(换枪)`镜头切换把一个主持人的话从中间切断(ep003),骨架会切成两个同名`【主持人N】`。parse 后处理:相邻 normal 段 role_label 全等、中间仅隔 ignore,则合并(正文顺序拼接、ignore 内容丢弃),避免输出里冒重复段头。合并条件要严,ep002/004 无 ignore 不受影响。
- [2026-06-18] **OCR 漏字决定不补(通哥拍板),不让 LLM 补词。** 三条理由:① 漏字的根在**上游抽帧/OCR**——缺的"那么/此外/一方面"都是两三字单独一屏、停留短被整屏漏掉,是真实信息丢失,文稿层无法"还原";② **LLM 补词=猜词=破"汉字零改"红线**,对专业性强、最贴近播出版的稿子风险不可接受;③ 口子守不住——seg8/seg27 标点回退正是 LLM 一有机会就想塞连接词被硬校验拦下,证明给余地它就动手。**真要科学补,唯一正路是 ASR 回捞**(这些连接词主持人/解说真说了,大概率在 ASR 310 句里),而非 LLM 猜,但属 C3 级返工、本期不值;真做时先验 ASR 有无再说。**治本=提醒编导/责编别让两三字单独一屏**;本期连接词缺了能读懂,接受。
- [2026-06-18] **`融合A稿_批改.docx`(通哥手批)只当"看缺了什么"的参照,绝不当"让 docx 去贴它"的对齐目标。** 手批稿可能含其他润色,一旦去对齐就等于润色,违背"只守零改汉字+加标点、不润色其他部分"。
- [2026-06-18] **seg8(专家2 行169-216)/seg27(专家7 行584-608) 两段标点接受一逗到底(通哥选 B)。** 这是标点没点好,不是缺字,不碰汉字;若日后要美化由人工手点。
- [2026-06-18] **C4 红线由"汉字润色"转为"汉字零改、标点交 LLM 按语义增删"**(通哥拍板:"转变后的红线更精准、更科学")。理由:润色会让关键军事表述有不准确风险;保守做法正文 100% 来自融合B稿,只在字符间插标点。**硬校验 `strip_punct(LLM输出)==strip_punct(输入)`** 是这条红线的机器守门员(strip_punct 去掉所有 unicode 'P' 类标点+空白),不过即重试、再不过回退裸文本。**第一批先做保守版,润色/漏字回填留第二批。**
- [2026-06-18] **thinking 要按任务分用,不是越开越好——这是 C1"thinking不关content为空"的孪生坑。** 两个独立故障:(a) **开 thinking 时 max_tokens 必须给足**thinking 与正文 `content` 共享同一配额,配额不够 thinking 吃光 → 正文空输出(C4 标点层 @2000 实测吐 0 字);(b) **浅层活(标点/抽取)开 thinking 会又慢又被推理空转吃光**:标点这种活开 thinking 单段 10+ 分钟还超时,关掉 thinking/3000 单段 6.9s 通过。**规则:语义对齐/融合这类深推理开 thinking 且给足 tokenC4 对齐 4096);标点、抽取这类浅层确定性活必须关 thinking。**
- [2026-06-18] **A稿分段编号有重复(解说2/解说10 各出现两次)——任何按段头文本做 key 的字典都会把两次出现合并,必须按"文档出现顺序"切块/取块。** C4 红线核验脚本初版犯此错(解说2 行61-77 与行151-168 被并成一段、误报破线),改用 occurrence 队列后 28/28 全过。对齐表 c4_alignment.csv 用 seg_id 区分,不用段头文本。
- [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-22] **AI 融合层 LLM 已从 DeepSeek v4-pro 切换到小米 MiMo 2.5 Pro。** 环境变量名通用化:`LLM_API_KEY` / `LLM_BASE_URL` / `LLM_MODEL`(旧 `DEEPSEEK_*` 已废弃,代码不再读取)。接入:OpenAI 兼容,`/chat/completions`,模型名 `mimo-v2.5-pro`。thinking 关闭方式与 DeepSeek 相同(`extra_body={"thinking":{"type":"disabled"}}`)。Cline 端也已换 MiMo 2.5 Pro。**(此条覆盖先前 DeepSeek v4-pro 的决策。)**
- [2026-06-22] **抽取类任务必须关 thinking(规则不变,适用于 MiMo)。** 做法:`chat(..., thinking=False)``extra_body={"thinking":{"type":"disabled"}}`,给足 `max_tokens`C1 用 4000)。**C4 语义融合可开 thinking**(单轮调用,质量优先)。
- [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。
- [2026-06-18 晚] **C3 会拿 ASR 同音字盖权威 B稿专名——必须核验留痕、专名一律以 B稿/A稿为准。** ep003 实证:B稿"斯泰尔"(奥地利厂名)被 C3 LLM 按 ASR 同音改成"斯太尔",造成 487/519 行不一致。已手改回。这正是上条权威规则的反例落地:**厂名/型号/番号遇 ASR 同音异写,零容忍采 ASR**。50 期批量前应在 C3 prompt 收紧(见待办 backlog);每期 fuse 后扫一眼 `fusion_review.csv` 的 minor_edit 是不是专名同音改。
- [2026-06-18 晚] **C4 出现空段≠对齐 bug,先查"是不是播出剪了这段"。** ep003 有 4 个空段(seg1518 整段 VSS 微声狙击枪 + NTW-20),一度疑似对齐错乱。核验路径:去**融合B稿**里 grep 该段专属词(VSS/NTW/南非/消音/反器材),零命中=播出确实剪了;再抽查相邻实段边界确认没把别段内容错塞过来。结论是 C4 如实留空、对齐正确。**空段是常态(播出删戏),别当 bug 去"修"。**
- [2026-06-18 晚|通哥复查] **C4 标点层整篇偏保守是真缺陷,须在批量铺开前修——但不破红线。** ep003 复查实测逗号 511 vs 句号 70(断句标点 88% 逗号),语义该断处全逗号。根因:标点层关 thinking + STRICT prompt 只强调"别改字"未强调"句子结尾用句号"。**红线(汉字零改)由 strip_punct 守着没破,所以标点层尽可放开 prompt 让它正常断句、不怕越界**。修复列 ep002 前必做,修完重跑 ep003 compose 刷 docx。这条把先前"seg8/seg27 一逗到底可接受"的范围收窄:个别段一逗到底可接受,但整篇 88% 逗号不可接受、必须修。
- [设计期] **分层不变**:OCR 错字纠正、术语统一、时间戳对齐走**规则层**(确定性);段落归属、整段删除判定、编导笔误识别走 **AI 层**(需语义判断)。
- [设计期] **顺序约束**:术语提取(C1,产热词)必须在 ASR(C2)之前——已成立。
- [2026-06-17] **`fusion_review.csv` 定位 = 留痕档案(给爱德华/复核),不是编导读物。** 编导读的是 C4 docx。CSV 可读性不优化,只看 final_text 准不准。
- [2026-06-17] **`final_text==B原文` 强制归 `unchanged` 不进 review。** LLM 有时把"考虑后决定保留 B 稿原文"标成 `minor_edit`,但实际没改字。`fusion_review.py``_normalize_unchanged_when_no_edit()` 在写文件前修正(review 19→5)。
- [2026-06-17] **`change_type``minor_edit`/`editor_typo` 边界 LLM 把握不稳**(OCR 错字两类混标)。仅 metadata 标签不一致,`final_text` 全对,不影响融合B稿正文。本轮决定忽略;若 C4/爱德华按 `change_type` 做逻辑分流,届时在 prompt 里收紧两个枚举的边界定义。
- [工程纪律] 各阶段解耦、中间产物落缓存、可断点续跑、可单独重跑;长批处理放独立终端。
---
## 7. ⏩ 交接备注(写给下一个接手的 session)
> 下次开工读完这段应能 0 摩擦续上。接手后可清空重写。**(2026-06-22 重写)**
- **大局**ep001 + ep003 两期已全流程跑通。**ep002 已完成 P1→P2→C1→C2**,下一步跑 C3 fuse → C4 compose 即可出稿。ep004 上游仍全空(只有骨架)。
- **ep002 现状**`ep002_20260127_qianting_fangsheng`(潜艇仿生)目录下已有:A稿 docx + mp4 + skeleton + `frames_v2/`(1620帧) + `audio_16k.wav` + `ocr_raw.jsonl`(1620行) + `B稿_v2.txt`(733行) + `本期热词表.txt`(68条) + `c1_term_candidates.json` + `asr_v2_timed.txt`(411句) + `asr_result_raw.json` + stage 脚本。
- **第一句话该干的****审核 ep002 C4 compose 报告**Cline 正在跑或已跑完)。检查:硬校验是否全过、空段数、标点回退段数。通过后 ep002 全流程完工,转 ep004。若 C4 还没跑完,等它跑完再审。
- **ep002 C3 已审核通过**10条review/专名无同音替换),不用重审。
- **ep004 现状**`ep004_20260526_qiangwang_duijue`(枪王对决,最难·小剧场密)。只有 A稿 docx + mp4 + skeleton。需跑完整 P1→P2→C1→C2→C3→C4。stage 脚本从 ep003 复制。
- **LLM 已切换**:代码和 Cline 都已从 DeepSeek 切到**小米 MiMo 2.5 Pro**。环境变量名 `LLM_API_KEY` / `LLM_BASE_URL` / `LLM_MODEL`(旧 `DEEPSEEK_*` 已废弃)。
- **Ollama 并发已配**`OLLAMA_NUM_PARALLEL=4`,ep002 实测 ~50帧/分钟(串行的3倍)。4090D 显存余量大(GPU 利用率仅 2%),ep004 可考虑提到 8 路。
- **P1 抽帧硬约束****不做 dHash/IoU 去重**,全部帧进 OCR,去重交 Stage B 按文本做(P2 完工快照铁律)。`doco split` 的去重逻辑是过时的,不要用。
- **量产坑(务必记住)**
1. 每期热词/术语不同,**C1 每期重跑**;A稿分段编号各有各的重复/空格脏,**按出现顺序走、别假设单调唯一**。
2. **C3 fuse 后必扫 `fusion_review.csv`**:专名(厂名/型号/番号)若被 ASR 同音字改了要打回(ep003 踩过"斯泰尔→斯太尔",见关键决策)。
3. **C4 出现空段先别当 bug**:多半是播出剪了那段戏,去融合B稿 grep 该段专属词确认(见关键决策)。
4. **OCR 漏字本期不补**(通哥拍板)——根在抽帧/OCR 漏两三字单屏,LLM 补词=破红线。
5. **ASR 花讯飞额度**;长转写/OCR 放独立终端别让 Cline 盯。
6. Cline 会偷换模型/术语源、误判字数、口头猜错根因——**自报结果一律对源数据核验**。
7. **thinking 分任务用**:语义对齐/骨架开、标点/抽取/融合关(见关键决策)。
- **出稿命名**`{原始A稿stem}_融合A稿.docx`(不覆盖原始定稿)。
- **字体坑(C4 出稿)**:大标题方正小标宋_GBK(商业字体),出稿前确认已装,否则脚本回退。
---
## 8. 待确认 / 开放问题(需通哥拍板,AI 别自行假设)
- ~~**B稿_v2.txt 就位**~~:已完成(通哥已拷进 episode 目录并随 9340edc 入库)。
- ~~**讯飞旧 key 轮换**~~:已完成(新值已在 `doco/.env`,旧 appid `84eff996` 代码内无残留)。
- **方正小标宋字体可用性**:C4 出稿前确认两台机器是否已装。
- ~~**OCR 并发提速**~~:已完成,4路并发实测通过(ep002),后续可提到 8 路。
- **讯飞单源依赖**(远期):是否接阿里云 ASR 做备份/交叉验证。