From e95699b21b619e1af50102bd51da837921987ae4 Mon Sep 17 00:00:00 2001 From: ssurui Date: Mon, 5 Oct 2026 17:40:53 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=AE=B0=E5=BD=95=20TTS=20=E4=B8=AD?= =?UTF-8?q?=E9=80=94=E5=BC=80=E5=85=B3=E6=BC=8F=E6=92=AD=E5=8F=8A=20contex?= =?UTF-8?q?tBridge=20=E5=86=BB=E7=BB=93=E5=AF=B9=E8=B1=A1=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E8=B8=A9=E5=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补充"生成中途打开 TTS 只从当前位置播报"的根因和修复方式,以及 调试时发现的 contextBridge 暴露对象默认冻结、渲染进程里 monkey-patch 拦截调用会静默失败的教训,供以后排查类似问题参考。 Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01QeoAy5KmkHuKWHAktpEsaN --- CLAUDE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 32a292d..2cc0c6e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -203,6 +203,9 @@ const vectors = await Promise.all(texts.map((t, i) => fetchOne(t, i))) - **`append()` 里必须是 `this.buffer += pending` 而不是 `=`**。LLM 流式增量很碎(常几个字一个 chunk),用赋值会把上一次还没凑够一句、尚未送去朗读的残留直接冲掉,实际效果是整段正文都丢了、只念出 `flush()` 时残留的一个句号。 - **加粗文本会被念两遍**,根因是 `markdownToPlain()` 每次都从头重新解析整段 `rawText`,而 `**` 闭合前后同一段文字的纯文本结果不一样(未闭合时星号当普通字符,闭合后星号被去掉)。提前把这段还不稳定的文字记为"已朗读",闭合符号一到就会被当成新内容重念。`findStableBoundary()` 因此只处理到最后一个已闭合的 `**` 为止,未闭合的尾巴留到下次;`flush()` 时生成已结束,不再有这顾虑,直接处理完。 - **"开始播报"提示音要单独入队**(`announceStart()`),不能碰流式缓冲区状态。 +- **生成中途才打开 TTS,会漏掉开关之前已生成的正文**。`append()` 开头是 `if (!this.options.enabled) return`,TTS 关闭期间每次 `onDelta` 调用都被直接挡掉,内部 `rawText`/`lastSpokenPlain` 完全不累积;中途打开后下一次 `onDelta` 只送来新增量,等于从打开那一刻"之后"才开始播。`ChatPanel.vue` 的 `toggleTts()` 因此在 `store.querying` 为真时,除了 `announceStart()` 还要补一次 `ttsPlayer.append(store.rawAnswer)`,把已生成的全文"补喂"一遍,相当于告诉播放器"这就是从头到现在的内容",之后的增量在这个基础上正常追加、不会重复。 + +**调试这类"实际发声内容对不对"的问题时的教训**:想在渲染进程 monkey-patch `window.electronAPI.xxx` 来拦截调用做验证是无效的——`contextBridge.exposeInMainWorld` 暴露的对象默认被冻结,赋值会静默失败、不报错,很容易误判成"这条代码路径没走到"。真正能验证的办法是去主进程对应的 `ipcMain.handle(...)` 里临时加 `console.log`(验证完记得删),或者用 CDP 的 `Input.dispatchMouseEvent` 模拟真实点击、`Runtime.evaluate` 读 DOM/计算样式——这两种都是从"实际发生的效果"验证,不依赖能否篡改渲染进程里的 API 对象。 ### 系统提示词:查不到内容时的答复