Files
vrsub/docs/调研-whisper漏句与decode_full验证.md
T
cat-shark 966f3e6b4b docs: AGENTS.md 只保留代理规则,项目信息迁入 README 与 docs/
把 AGENTS.md(545 行)中的项目知识按性质拆开,只留下对代理的要求:

- AGENTS.md(176 行)只写规则:读文档指引、提交许可、等待规则、TDD、
  测试规则(模块边界/三段结构/功能覆盖优先)、注释规范、目标运行环境、
  PowerShell 规则、文档维护规则;
- 项目信息新建 docs/ 专题:architecture、node-protocol、workflows、
  configuration、operations、testing、decisions;
- README 改为项目索引(定位、快速开始、文档导航、目录、工作流、结论摘要);
- 修正旧文档错误:README 的"详细约定见 AGENTS.md"与"100% 行覆盖率"
  (pytest 已移除该门槛);环境变量表补齐 WOV_AUTO_VAD 等 3 项。

新增 scripts/check_doc_links.py 校验相对链接与锚点,当前 14 个文档全部可达。
2026-09-13 15:40:31 +08:00

139 lines
8.4 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.
# 调研记录:whisper "说话没识别" 漏句问题 与 decode_full 方案验证
> 本文档记录 2026-09 对"转写时有人说话但没识别出来(漏句/漏识别)"问题的完整调研过程、
> 实验数据与结论修正。调研中发现**早期结论被后续更严谨的验证推翻**,特此如实记录,
> 供后续对话继续推进时参考,避免重复踩坑。
>
> 状态:**调研暂告段落,方案未定稿,代码改动未提交**。详见文末"当前状态"。
---
## 1. 问题背景
用户反馈:whisper 转写时**动态配置参数**(自动 VAD 调参),生成的字幕中有时出现
"有人说话但没识别出来"的情况,怀疑与动态参数配置有关。
链路(当时为 demo/learn-translatedemo 已于 2026-09 移除):提音(ffmpeg-extract) → 转写(faster-whisper) → 翻译(llm) → ASS。
whisper 节点关键动态逻辑(改动前):
- `vad_filter=true`(默认开启)
- `WOV_AUTO_VAD=1`(默认):每视频信号分析 → 动态生成 `vad_parameters`
`nodes/vad_profiler.py`,按静音比例/BGM 覆盖/长停顿 四分支给 threshold/min_silence/speech_pad
- `chunk_seconds=60` 分块、`condition_on_previous_text=false``beam_size=1`
---
## 2. 实验一:savr-1054 全片 A/BVAD vs 无VAD
素材:`/mnt/fnOS/123/savr-1054/4k2.me@savr01054_2_8k.mp4`1383s,呻吟/BGM 密集)。
| 配置 | 全片条数 | 覆盖时长 | 幻觉长段 |
| --- | --- | --- | --- |
| 生产 VADvad_filter=true+自动VADthreshold0.5/ms1000/pad200 | 115 | 621s | 0 |
| 无 VADdecode_full 前身) | 369 | 983s | 有(119-149s、600-630s 30s"ご視聴…" |
- 无 VAD 确实**大幅增加召回**115→369),其中 65-135s 的"入ってるところ見える?
/奥までジュボジュボ入ってるよ"等与线上 CN.srt 空洞吻合 → **当时判定为"救回真话"**
- 但无 VAD 副作用明显:119-149s/600-630s 出现 30s 长"ご視聴ありがとうございました"幻觉。
### 2.1 人声分离(demucs)实验
- `htdemucs --two-stems=vocals` 分离后:**vocals 轨 VAD 切段与混音几乎一样**(瓶颈是
silero 对呻吟/轻语本身概率低,不是底噪);
- 分离 vocals + 无VAD 与混音无VAD 召回相当(16 vs 15 条/窗口)→ **人声分离不解决问题**
只是把音乐底噪去掉,呻吟/轻语仍是低概率语音。
### 2.2 min_silence / threshold 扫描
- 固定 threshold=0.5 只调 min_silence(300→2000ms):真话召回**不变**450s 窗口恒 1 条、
546s 窗口恒 1 条)→ **只调 min_silence 无效**(它只决定断句,不能把 silero 没标成
语音的弱语音变成语音段);
- 调 threshold(0.3~0.6):覆盖仅 44%→45%,真话也救不回(呻吟/BGM 混叠使 silero 切段能力
天然不足)。
### 2.3 每片独立 VAD / 精细能量分段 模拟
- "每 60s 块独立调参"24 块中 11 块会落到 bgm 分支(thr0.3),但段切更碎、覆盖不升,
**NO_VAD 降级反而新增 60s/36s/20s 空洞 + 幻觉**sim_perchunk 318 条,1080-1140s 整段空);
- 精细能量分段(RMS>900 切语音候选段):连真实说话段都定位错(1065-1115s 只找到 3 小段、
解码出幻觉)→ **能量/VAD 前置切段对混叠声学都不可靠**
---
## 3. 关键结论修正(重要)
### 3.1 "能量低=幻觉" 是错的
savr-1174 上精确验证:**938s 轻语真话 mean -40dBVAD 与无VAD 都能稳定识别**;
而 120s/140s/210s 真话区 mean 仅 -45~-48dB(整片录音电平低),**whisper 仍稳定识别**。
### 3.2 "稳定性(跨配置一致)= 真话" 是相对可靠的判据
- 真话(938s"吸い付かないでよ"、1065s"そういうプレイ好きな人?"):VAD/无VAD/beam1/beam5
**多配置稳定复现同一句**
- 幻听(1260s"手ついてたら…"):VAD 配置下变"おやすみなさい"、无VAD 才出该句 → 内容
跨配置**不稳定** = 无真实语音锚点。
### 3.3 置信度字段无法区分真幻
faster-whisper segment 的 `avg_logprob` / `no_speech_prob`:真话 60s(avg_logprob -0.42) 比
幻觉 1260s(-0.63) 还高;no_speech_prob 幻觉 330s(0.28) 比真话 1065s(0.30) 还低 → **不可用**
### 3.4 "decode_full 救回 VAD 漏掉的真话 2.7 倍" —— 被推翻
savr-1174 全片:decode_full(beam1) 463 条 vs 生产 VAD 170 条,早期结论是"救回弱语音"。
**逐条 + 分层抽样 VAD 复查后**
- decode_full 新增内容中,**大量(抽样 45 条中 20 条 VAD 静默)是 VAD 静默段的幻听**,
beam1 把噪声/重复碎片劣化转写成"词句"(如"何がやばいんだ"实为"何?何?何?"、2243s
beam1/beam5 结果不同=不稳定);
- 真正被救回的低电平真话(120s/140s/210s**VAD 其实也能识别**(只是旧自动 VAD 参数
或分块把它们漏了)→ 说明问题在**旧自动 VAD 参数选取**而非 VAD 机制本身。
### 3.5 无法用单一信号完美区分真幻
| 信号 | 效果 |
| --- | --- |
| 能量/RMS | 无效:savr-1174 录音电平低,真话-45dB vs 幻听-51dB 难分;高响度(如-22dB 效果音段)也可能是幻听 |
| avg_logprob/no_speech | 无效(见 3.3 |
| 寒暄词表 | 有效但覆盖面窄(savr-1174 decode_full 后寒暄类已 0 命中,即已被清干净) |
| **VAD 复查**decode_full 后逐条用 VAD 复查,VAD 能识别才保留) | **相对最可靠**,但会误删 VAD 漏掉的短真语气词(うん/はい/んー),且切窗不准会误删响亮真话 |
---
## 4. 代码改动现状(未提交)
以下改动已写入工作区(`git status` 可见),**未经用户确认提交**
| 文件 | 改动 | 状态 |
| --- | --- | --- |
| `nodes/subtitle_cleanup.py` | 幻觉清洗改为**整条删除式**`remove_hallucination_entries`:≥15s 命中寒暄词表 → 序号+时间轴+文本全删、剩余重编号);新增日语词表 `JAPANESE_HALLUCINATION_TOKENS` | 已改 |
| `nodes/whisper.py` | 新增 `decode_full` 参数(默认 false):true 时无VAD 整段解码 + 跳过自动VAD + 日语幻觉整条删除 | 已改 |
| `nodes/llm.py` | `clean_srt_text` 由替换 `-` 占位改为整条删除;回滚了临时的 `-` 跳过逻辑 | 已改 |
| `workflows/learn-translate.json` | 新工作流"学习资料转译+翻译字幕"decode_full=true;每参数 `_note_<名>` 标注理由+正反例;`_node_help` 参数手册 | 新增 |
| `tests/*` | test_hallucination_mask 重写为删除式;whisper decode_full 测试;learn-translate 加载/标注测试;test_seed 计数 3→4 | 已改 |
| `AGENTS.md` | decode_full 说明、工作流表、参数标注约定 | 已改 |
测试:相关 97 passed(全量 357 passed / 5 个既有环境失败与本次无关:ffmpeg 4.2 不支持
`force_divisible_by` 滤镜、home 目录解析)。
**端到端已验证**savr-1174 前 200s decode_full → 幻觉整条删除(无 0-90s 占位重叠)、
真实内容 60.03s 起时间轴正确、翻译 36 条、ASS 72 Dialogue 0 噪点。
---
## 5. 待决问题(新对话继续)
1. **decode_full 是否值得作为默认增强**savr-1174 显示其对呻吟/BGM 密集视频**弊大于利**
(新增大量幻听),但对纯对话/低电平场景(120s 真话)有效。可能只适合特定声学;
2. **"VAD 复查过滤"方案是否落地**:可保留 decode_full 救回的真话并剔幻听,但需解决
短真语气词误删与切窗不稳问题;实现成本中等;
3. **旧自动 VAD 参数为何漏低电平真话**(120s 这类 VAD 单窗能识别但整片 A 漏了)——
可能是分块边界/自动参数分支误判,值得单独排查;
4. **现有代码改动去留**subtitle_cleanup 整条删除式、whisper decode_full、learn-translate
工作流——保留、调整还是回滚待定;
5. **如何真正"听"音频验证**(本调研最大局限:未实际听音,靠多配置转写交叉推断)。
### 实验产物(临时文件,可复用)
```
/tmp/savr1054_2.wav savr-1054 全片 16k 音频
/tmp/savr1054_2_vocals16k.wav demucs 分离 vocals 轨
/tmp/run_A_vad.srt savr-1054 生产VAD 全片 (115条)
/tmp/run_B_novad.srt savr-1054 无VAD 全片 (369条)
/tmp/savr1174_1.wav savr-1174 全片 16k 音频
/tmp/savr1174_A_vad.srt savr-1174 生产VAD 全片 (170条)
/tmp/savr1174_B_decodefull.srt savr-1174 decode_full beam1 (463条)
/tmp/savr1174_D.srt savr-1174 decode_full beam5 (336条)
```