Files
vrsub/docs/调研-whisper漏句与decode_full验证.md
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

8.4 KiB
Raw Permalink Blame History

调研记录: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=falsebeam_size=1

2. 实验一:savr-1054 全片 A/BVAD vs 无VAD

素材:/mnt/fnOS/123/savr-1054/4k2.me@savr01054_2_8k.mp41383s,呻吟/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/210sVAD 其实也能识别(只是旧自动 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条)