🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

实时朗读 PRTSPro/dsh-read-aloud

DeepSeek Harness
PRTSPro76 天前有提交已提供中文文档扫描:含敏感能力

边生成边朗读 AI 回复,解放双眼专注聆听

24/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/23 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add PRTSPro/dsh-read-aloud
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · other
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 76 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 18 处,展示前 17 条)
  • 写入本地文件
    src/index.ts:92
    mkdirSync(dirname(logFile), { recursive: true })
  • 写入本地文件
    src/index.ts:93
    appendFileSync(logFile, '[' + new Date().toISOString() + '] ' + msg + '\n')
  • 读取本地文件
    src/index.ts:103
    const raw = JSON.parse(readFileSync(STATE_FILE, 'utf8')) as Record<string, unknown>
  • 写入本地文件
    src/index.ts:114
    mkdirSync(dirname(STATE_FILE), { recursive: true })
  • 写入本地文件
    src/index.ts:115
    writeFileSync(STATE_FILE, JSON.stringify(s), 'utf8')
  • 读取本地文件
    src/speaker.ts:147
    if (existsSync(c)) {
  • 读取本地文件
    src/speaker.ts:164
    if (c === 'edge-tts' || existsSync(c)) {
  • 读取本地文件
    src/speaker.ts:189
    if (!existsSync(script)) return false
  • 执行外部命令来自配置/变量
    src/speaker.ts:192
    const d = spawn(this.opts.pythonPath || 'python', [script], {
  • 执行外部命令固定命令
    src/speaker.ts:378
    spawn('taskkill', ['/PID', String(d.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true })
  • 执行外部命令固定命令
    src/speaker.ts:405
    spawn('taskkill', ['/PID', String(c.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true })
  • 读取本地文件
    src/speaker.ts:555
    if (ok && !existsSync(file)) {
  • 读取本地文件
    src/speaker.ts:572
    if (!ok || !existsSync(file)) {
  • 读取本地文件
    src/speaker.ts:578
    if (ok && existsSync(file)) return [file]
  • 删除本地文件
    src/speaker.ts:607
    rmSync(p, { force: true })
  • 删除本地文件
    src/speaker.ts:631
    rmSync(file, { force: true })
  • 执行外部命令来自配置/变量
    src/speaker.ts:650
    child = spawn(exe, args, { stdio: 'ignore', windowsHide: true })
扫描于 2026/11/4(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-session@deepseek-ai/dsh-client-ui-slots
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DeepSeek Harness 对话实时朗读插件:流式朗读 AI 回复(OneCore 即时 / edge-tts 神经语音),非文本清洗,关键词控制

README

由 DeepSeek 最新模型翻译生成
dsh-read-aloud DeepSeek Harness(DSH)对话实时朗读插件(hybrid:host 朗读引擎 + client 对话栏按钮):监听当前会话的流式输出,把 DeepSeek 的正常回复逐句朗读出来——边生成边读,解放双眼。对话输入栏(composer)左侧有一个朗读开关小图标按钮,朗读中图标动态波动,点击即可开关朗读。 - ✅ 只读正文(text-delta),不读思维链(reasoning-delta)、不读工具调用、不读子代理会话 - ✅ 预合成管线:播放批 i 时后台合成批 i+1(双文件槽轮换),批间无停顿;edge-tts 常驻合成进程预热,首批/断流恢复 ~2s - ✅ 双引擎(两段式):edge-tts 神经语音(晓晓等,音质接近真人,首选)/ 本地 OneCore 兜底 - ✅ 10 层非文本清洗:URL、路径、哈希、代码块、表格线、emoji 等不会被逐字符机械朗读 - ✅ 符号静音:/、\、()、-、——、"、_、&、# 等符号不读(括号内容保留,"(见上文)"读成"见上文";some_var 读成 "some var";state-of-the-art 读成 "state of the art") - ✅ 对话栏按钮(conversation.input.left):待命 / 朗读中波动 / 已关闭三态,点击开关
展开完整文档(README 剩余 1 节)
dsh-read-aloud

DeepSeek Harness(DSH)对话实时朗读插件(hybrid:host 朗读引擎 + client 对话栏按钮):监听当前会话的流式输出,把 DeepSeek 的正常回复逐句朗读出来——边生成边读,解放双眼。对话输入栏(composer)左侧有一个朗读开关小图标按钮,朗读中图标动态波动,点击即可开关朗读。

- ✅ 只读正文(text-delta),不读思维链(reasoning-delta)、不读工具调用、不读子代理会话
- ✅ 预合成管线:播放批 i 时后台合成批 i+1(双文件槽轮换),批间无停顿;edge-tts 常驻合成进程预热,首批/断流恢复 ~2s
- ✅ 双引擎(两段式):edge-tts 神经语音(晓晓等,音质接近真人,首选)/ 本地 OneCore 兜底
- ✅ 10 层非文本清洗:URL、路径、哈希、代码块、表格线、emoji 等不会被逐字符机械朗读
- ✅ 符号静音:/、\、()、-、——、"、_、&、# 等符号不读(括号内容保留,"(见上文)"读成"见上文";some_var 读成 "some var";state-of-the-art 读成 "state of the art")
- ✅ 对话栏按钮(conversation.input.left):待命 / 朗读中波动 / 已关闭三态,点击开关
- ✅ 只读当前打开的会话:对话栏按钮自动上报当前会话,多会话并存时不交错混读
- ✅ 朗读进度横条:对话栏上方显示一条"🔊 朗读中 {当前句}",随朗读滚动,与输入区一体
- ✅ 状态持久化:静音/引擎选择存 ~/.dsh/super-injector/dsh-read-aloud-state.json,host 重启自动恢复
- ✅ 标准装配:host 半由 profile cordis.patch.yml 的 - insert 装载,client 半由 client-modules 自动装载——重启/热重载自动加载,无需注入器
- ✅ 关键词控制:别读了 / 继续朗读 / 切换音色引擎
- ✅ 失败静默降级(edge 断网自动回落本地),绝不干扰对话本身

快速开始

标准 profile 装配(无需注入器;本机已在 ~/.dsh/profiles/web/cordis.patch.yml 配置) host 半:- insert { id: dsh-read-aloud, name: '@dsh-external/dsh-read-aloud' } client 半:client-modules 按 package.json 的 dsh.client 声明自动装载

构建(host + client 双产物)
npm run build # host:scripts/build.sh(WSL bash + tsc,src/ → lib/index.js)
npm run build:client # client:build-client.mjs → lib/client.js(ModuleLoader bundle)
npm pack # 发布/分发用 → .tgz

改代码后生效:host 需重启 DSH(node .../@deepseek-ai/dsh/lib/bin.js web); client 重建后浏览器刷新一次(pnpm run dev:web watcher 在跑则 HMR 联动)

依赖:Windows + dotnet 9 运行时(OneCore 宿主)+ 本机 ffplay + edge-tts(~/.local/bin/edge-tts.exe,edge 档)。

对话栏按钮

- 位置:输入框卡片左下工具排(conversation.input.left slot,plan 右侧),30px 图标按钮。
- 视觉:已开启=喇叭+声波弧(品牌色);朗读中=喇叭呼吸 + 右滑三根音量条波动(CSS 动画);已关闭=喇叭+斜线(灰、半透明)。
- 交互:点击即 toggle(静音↔恢复,静音时打断当前播放);每 300ms 轮询 host RPC state 驱动动画;host 不可达时图标降透明(offline 兜底)。
- 无障碍:aria-label / aria-pressed,支持 prefers-reduced-motion。
- 通信:host 注册 /@dsh-external/dsh-read-aloud/api 前缀路由(state/toggle/stop/resume),client 经 fetch POST 调用。

控制词(短消息生效,防误触发)

| 说 | 效果 |
| 别读了 / 停止朗读 / 安静 / 静音 | 立即停止并清空队列(按钮同步显示已关闭) |
| 继续朗读 / 接着读 / 开始朗读 | 恢复(按钮同步显示已开启) |
| 用晓晓读 / 用云端 / 高质量 | 切 edge-tts 流式(晓晓) |
| 用本地读 / 用慧慧 / 即时档 | 切回本地 OneCore |

配置(src/index.ts 的 DEFAULTS)

| 项 | 默认 | 说明 |
| engine | edge | edge 神经语音 / onecore 本地即时 |
| voice | Huihui | OneCore 音色(慧慧/瑶瑶/康康) |
| rate | 1 | OneCore 语速 0~3 |
| edgeVoice | zh-CN-XiaoxiaoNeural | edge 音色(晓晓/晓伊/云希…) |
| edgeRate | +0% | edge 语速(+10% 形式) |
| edgeTts | 自动探测 | edge-tts 可执行(~/.local/bin/edge-tts.exe 优先);纯合成不播放 |
| maxQueue | 24 | 队列上限;满时丢最旧句保新句(跟读跟上最新) |
| maxSentenceLen | 200 | 单句强制切分上限 |
| fallbackToLocal | true | edge 合成失败自动降级 OneCore |

注:engine/静音状态由 state.json 持久化(运行时切换会覆盖代码默认值);其余配置项仍为代码常量。

工作原理

DeepSeek 流式输出 → DSH session/event 火线(assistant/chunk) → 主会话过滤(跳过 subagent)→ 仅取 text-delta → 句子切分 + 10 层非文本清洗(splitter) → FIFO 队列 → 预合成管线(speaker)合成器(后台,串行): edge-tts --write-media / onecore-host 播放器(前台): ffplay,播放批 i 时预合成批 i+1 → 扬声器

对话栏按钮通过 host webServer RPC 读取 Speaker.getState()(muted/speaking/engine),并与关键词控制走同一套 stop()/resume()/toggle() 状态机——按钮与「说一句话」完全等价。

关键点:DSH 的流式事件不直接以 assistant/chunk 广播,而是包在 session/event 火线的 {type, seq, time, data} 信封里;火线只推送实时 append,历史重放不上火线(天然满足「不读历史」)。

目录

src/index.ts 插件入口(订阅/控制词/装配 + webServer RPC + 状态持久化) src/splitter.ts 句子切分 + 非文本清洗管线 src/speaker.ts 预合成管线(合成器/播放器分离 + 双缓冲)+ 双引擎 + 降级链 + 打断 src/client/index.ts 对话栏按钮 UI(conversation.input.left slot,纯 JS body) scripts/build.sh WSL 构建 host(checkout 探测 + tsc) scripts/build-client.mjs 把 src/client/index.ts 抽成 lib/client.js(ModuleLoader bundle) var vendor/onecore-host/ dotnet 9 OneCore 合成宿主 docs/ idea 调研文档(含全部实测结论) AGENTS.md Agent 开发指引(架构事实 Hub)

构建(host + client 双产物)

npm run build # → scripts/build.sh 编译 host:src/ → lib/index.js
npm run build:client # → lib/client.js(ModuleLoader bundle)
npm pack # → .tgz

lib/client.js 由 src/client/index.ts 抽取生成:文件顶层保留 export const inject = ['slots','timer'] + const __mirror = ... 镜像(供构建预检锚点),build-client.mjs 提取 __mirror 内 body 包裹进 window.__ModuleLoader__.load({ id, factory })。改 UI 源后必须重跑 npm run build:client(否则 client bundle 过期)。

已知限制

- 首批/断流恢复需等网络合成(~2s,edge-tts 常驻进程预热后);之后批间无缝(预合成管线,批粒度 6 句/180 字保证播放时长 > 合成时长)
- 跟读滞后:LLM 输出(~2 句/s)远快于播放(~0.36 句/s),队列满(24)时丢最旧句、保最新内容——长回复会「跳读」中间部分(旧版丢新句同样跳读且丢最新)
- 只读当前会话依赖 GUI:client 按钮上报当前会话;若 host 无 web GUI 页面加载(activeSessionId 为空)则回退为朗读全部会话
- 对话栏上方进度横条为近似:当前句按字符权重估算(无字幕时间轴),±1 句误差
- edge-tts 依赖微软在线服务,断网自动降级 onecore
- 只读实时流;表格退化为连续词朗读;超长句按 200 字强制切
- 关键词控制依赖用户消息文本,长消息内的控制词会被忽略(防误触发)
- 浏览器页面已打开时新增/升级 UI 需刷新一次才能看到按钮(client bundle 经 HMR 联动,但首装需重载页面)

License

BSD-3-Clause
预览分享卡片长什么样 ↓PRTSPro/dsh-read-aloud
分享 · DeepSeek Harness Hub
PRTSPro/dsh-read-aloud

边生成边朗读 AI 回复,解放双眼专注聆听

这是你的仓库?认领条目

回到顶部