Files
vrsub/docs/workflows.md
cat-shark 2c8bbb6469 feat: 转写支持静音段幻觉抑制参数(HST)
无 VAD 的 decode_full 会在无语音段"编"出字幕(`こんにちは`/`おはようございます`/
`東京都交通局8800形電車`)。实测这类幻觉与"呻吟间隙里的真实短台词"在
`no_speech_prob`、`avg_logprob`、silero VAD 与音频能量四个维度上都不可分,
只能用 faster-whisper 自带的 `hallucination_silence_threshold`(HST)抑制:
怀疑幻觉时跳过超过阈值的静音部分(需 `word_timestamps=True`)。

- `nodes/whisper.py` 透传 `word_timestamps` / `hallucination_silence_threshold` /
  `no_speech_threshold` / `log_prob_threshold` / `compression_ratio_threshold`,
  未配置的键不传,保持 faster-whisper 默认值与改造前行为。
- `learn-translate` 默认 HST=2.0 + word_timestamps:同一片头 120 秒无对话段由 15 条
  字幕降到 4 条且无套话幻觉残留,呻吟段基本保留;代价转写约慢 1.8×。
- 实测数据与取舍记录见 docs/workflows.md#decode_full-与幻觉呻吟清洗。
2026-09-18 23:41:32 +08:00

91 lines
6.6 KiB
Markdown
Raw Permalink 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.
# 内置工作流
工作流是**数据**:默认定义存放在 `workflows/*.json`,启动时由 seed 写入
workflow_versions 表;切换模型或调整链路只改数据,不改代码。
## 工作流一览
| ID | 名称 | 链路 | 说明 |
| --- | --- | --- | --- |
| `zh-direct` | 中文直出字幕 | 提音 → 中文转写 → ASS | 中文直出模型,无 LLM 步骤 |
| `ocr-subtitle` | 字幕OCR提取 | 抽帧 → 逐帧 OCR → 汇总 SRT → LLM 过滤 | 提取烧录字幕做基准数据;前端框选 crop;LLM 过滤多余/无意义字幕 |
| `learn-translate` | 学习资料转译+翻译字幕 | 提音 → 转写(decode_full) → LLM 翻译 → ASS | 面向讲解/学习类视频;应用 decode_full 无 VAD 整段解码 + 日语幻觉清洗,优先"说了的话不漏"(弱语音/快速讲解召回),再由幻觉清洗移除无语音段长套话 |
## 工作流参数标注约定
JSON 不支持注释,因此"参数理由"以节点 `params``_note_<参数名>` 键存放
`_` 前缀说明键,节点执行时只读真实参数键、忽略 `_note_*`,零运行影响);
节点级参数手册放 `params._node_help`(多行字符串,含关键参数解释与正反例)。
`WorkflowNode.from_dict` 会完整保留 params 全部键(不清洗未知键),seed 入库/
前端展示均不丢。查看方式:管理后台/工作流编排页打开工作流 definition JSON
即可见每个参数旁的理由说明。该约定由 learn-translate 示范,可复用到任何工作流。
## decode_full 与幻觉/呻吟清洗
**decode_full 参数**faster-whisper 节点):默认 `false`(保持 VAD 现状);
`true` 时强制无 VAD 整段解码并跳过自动 VAD 分析,救回被 silero VAD 当非语音剔除的
弱语音/呻吟/BGM 混叠人声(实测 savr-1054 全片 115 条 → 340 条),副作用为无语音段
长时寒暄幻觉,处理方式:whisper 转录后立即**连带时间戳把整条 cue 删除**(剩余重编号,
`nodes/subtitle_cleanup.py``clean_japanese_hallucinations`),不留下 `-` 占位污染
下游(占位会渲染进 ASS 成可见减号);llm-translate 翻译后同样整条删除中文长时寒暄
幻觉(`clean_srt_text`)。短时(≤15s)相同词可能是剧情真实道晚安,保留。
**短呻吟过滤**2026-09):decode_full 救回的弱语音中混有大量**纯语气词碎片**
(あ…/ん?/はぁ…/あ!あ!/んふふ 等 ≤3 假名),影响字幕观感;whisper 转录后按
'全部字符 ∈ 纯呻吟字符集合(`MOAN_CHARS`)且有效假名数 ≤ `short_moan_max_chars`(默认 3,设 0 关闭)'
判据**整条删除**`remove_short_moan_entries`)。集合刻意排除 そ/こ/ね/や/ば/だ
等假名,真实短对话(そこ/やばい/ねえ/やだ/えへへ)天然不命中。仅 decode_full
生效,learn-translate 等 VAD 链路不受影响。
**重复伪影过滤**2026-09):whisper 在单个窗口内卡住重复时,会把一个单元写满整条
cue(实测 30 秒、重复 74–446 次,如 `チン`×111);这种正文会让下游 LLM 跟着重复、
把输出预算耗在思考上而报结构错误(表现为 `translation alignment failed …
Expecting value: line 1 column 1 (char 0)`),也会直接渲染成超长字幕行。whisper
转录后按**模式判据**(无字符词表)**整条删除**(`remove_repetition_entries`):
展示时长 ≥15s 且同一 1–6 字单元连续重复 ≥6 次且覆盖正文 ≥70%;真实短促呻吟
`ぇ`×15、`ああああああ`)靠时长区分,零误删。VAD 开关都会生效。
**静音段幻觉抑制**2026-09):decode_full 的固有副作用是"无语音段照样写字幕"——
whisper 会在静音/音乐段输出 `こんにちは``おはようございます``東京都交通局8800形電車`
这类短幻觉。实测这类幻觉与"呻吟间隙里的真实短台词"在 `no_speech_prob``avg_logprob`
silero VAD 与音频能量四个维度上**都不可分**(数据见 `data/experiments/regen_plan/REPORT.md`),
所以走 faster-whisper 自带的 `hallucination_silence_threshold`HST,需
`word_timestamps=True`):怀疑该段是幻觉时,跳过超过阈值的静音部分。learn-translate
默认 `hallucination_silence_threshold=2.0` + `word_timestamps=true`:同一片头 120 秒
无对话段由 15 条字幕降到 4 条(无套话幻觉残留),呻吟段基本保留;代价是转写约慢 1.8×。
参数由工作流直接传给节点(`_guard_transcribe_params` 透传 `word_timestamps` /
`hallucination_silence_threshold` / `no_speech_threshold` / `log_prob_threshold` /
`compression_ratio_threshold`,未配置的键保持 faster-whisper 默认值)。
调研过程与结论见 [调研-whisper漏句与decode_full验证.md](./调研-whisper漏句与decode_full验证.md)。
## 切换模型不改代码
- 模型是工作流 DAG 中 asr 节点的 `model_path` 参数(**数据**),内置工作流
均已显式声明:learn-translate 用 `faster-whisper-large-v2`
zh-direct 用中文直出模型。
- 切换模型 = 改 `workflows/*.json` 或管理页面 DAG JSON → 保存新版本 → 发布,
全程不涉及代码;新库启动时从 JSON 重新 seed。
- 默认工作流定义存放在 `workflows/*.json`(数据文件),代码只负责加载。
- 模型解析顺序与本地权重目录见
[node-protocol.md](./node-protocol.md#模型权重解析本地优先)。
## 最终产物命名
最终产物按 `上传文件名.标识.时间戳` 命名(如 `test01.zh-CN.20260815123000.srt`),
标识优先取节点的 `target_language` 参数,否则用产物别名。**审查 R03 修复**:
保留节点原始文件及 URI,把成品副本存入 `runs/<run_id>/finals/output-<编码别名>/`
时间戳固定取 run 创建时间,重复收尾覆盖相同路径,多个别名分目录避免冲突。
复制先写同目录临时文件,再原子替换目标,失败不登记残缺文件;`final_outputs`
声明的引用或文件缺失时任务失败,不能标完成。learn-translate 声明三份最终产物:
`ja_srt`(asr 节点清洗后的日语转写,翻译前的归档)、`cn_srt`(中文译文)、`ass`(双目)。
旧版本原文件已改名但最终别名记录
仍指向有效文件时允许复用;原文件与成品都丢失时明确报错。批量场景下成品还会
复制到视频旁,命名约定见 [operations.md](./operations.md#文件夹批量处理)。
## 相关文档
- 节点参数与 I/O[node-protocol.md](./node-protocol.md)
- 默认模型选择与例外:[decisions.md](./decisions.md)
- 环境变量(`LLM_MODEL` 等):[configuration.md](./configuration.md)