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

本地语音输入 Real-WangLe/dsh-voice-local

DeepSeek Harnessv0.4.1
Real-WangLe45 天前有提交已提供中文文档扫描:含敏感能力

DeepSeek Harness Web UI 的本地离线语音输入插件,由 SenseVoice 驱动。

37.4/100
综合分
13
GitHub 星标
176
npm 周下载
—/5
用户评分

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-voice-local
npm 源 · dsh-voice-local 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · ui
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 45 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-voice-local @ 0.4.1
✓Node 引擎要求 >=18 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 16:39:24

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 47 处,展示前 45 条)
  • 发起网络请求
    dist/client.js:797
    const res = await window.fetch(`${API_BASE}/model/status`);
  • 发起网络请求
    dist/client.js:806
    const res = await window.fetch(`${API_BASE}/model/download`, { method: 'POST' });
  • 发起网络请求
    dist/client.js:827
    const res = await window.fetch(`${API_BASE}/transcribe`, {
  • 读取本地文件
    dist/transcriber.js:55
    const [modelStat, tokensStat] = await Promise.all([stat(model), stat(tokens)]);
  • 读取本地文件
    dist/model.js:108
    const s = await stat(path);
  • 读取本地文件
    dist/model.js:119
    return (await stat(path)).size > 0;
  • 写入本地文件
    dist/model.js:148
    await mkdir(dirname(dest), { recursive: true });
  • 删除本地文件
    dist/model.js:164
    await rm(tmp, { force: true }).catch(() => {});
  • 写入本地文件
    dist/model.js:227
    const file = createWriteStream(destPath);
  • 删除本地文件
    dist/model.js:270
    await rm(dest, { force: true }).catch(() => {});
  • 写入本地文件
    dist/model.js:271
    await rename(src, dest);
  • 读取本地文件
    dist/model.js:279
    const s = await stat(path);
  • 读取密钥环境变量
    dist/model.js:313
    const tokensSha256 = options.tokensSha256 ?? process.env.DSH_VOICE_TOKENS_SHA256 ?? '';
  • 写入本地文件
    dist/model.js:362
    await mkdir(extract, { recursive: true });
  • 写入本地文件
    dist/model.js:439
    await mkdir(dir, { recursive: true });
  • 读取本地文件
    dist/model.js:449
    await access(model);
  • 读取本地文件
    dist/model.js:450
    await access(tokens);
  • 读取本地文件
    dist/model.js:456
    await access(model);
  • 删除本地文件递归
    dist/model.js:480
    await rm(temp, { force: true, recursive: true }).catch(() => {});
  • 读取本地文件
    dist/arch.js:51
    platformResolved = candidates.some((dir) => existsSync(join(dir, 'sherpa-onnx.node')));
  • 读取本地文件
    dist/audio-filter.js:51
    return (await stat(path)).size > 0;
  • 发起网络请求
    dist/dictation.js:37
    const res = await window.fetch(`${API_BASE}/model/status`);
  • 发起网络请求
    dist/dictation.js:46
    const res = await window.fetch(`${API_BASE}/model/download`, { method: 'POST' });
  • 发起网络请求
    dist/dictation.js:67
    const res = await window.fetch(`${API_BASE}/transcribe`, {
  • 读取本地文件
    lib/arch.js:51
    platformResolved = candidates.some((dir) => existsSync(join(dir, 'sherpa-onnx.node')));
  • 读取本地文件
    lib/audio-filter.js:51
    return (await stat(path)).size > 0;
  • 发起网络请求
    lib/dictation.js:37
    const res = await window.fetch(`${API_BASE}/model/status`);
  • 发起网络请求
    lib/dictation.js:46
    const res = await window.fetch(`${API_BASE}/model/download`, { method: 'POST' });
  • 发起网络请求
    lib/dictation.js:67
    const res = await window.fetch(`${API_BASE}/transcribe`, {
  • 读取本地文件
    lib/model.js:108
    const s = await stat(path);
  • 读取本地文件
    lib/model.js:119
    return (await stat(path)).size > 0;
  • 写入本地文件
    lib/model.js:148
    await mkdir(dirname(dest), { recursive: true });
  • 删除本地文件
    lib/model.js:164
    await rm(tmp, { force: true }).catch(() => {});
  • 写入本地文件
    lib/model.js:227
    const file = createWriteStream(destPath);
  • 删除本地文件
    lib/model.js:270
    await rm(dest, { force: true }).catch(() => {});
  • 写入本地文件
    lib/model.js:271
    await rename(src, dest);
  • 读取本地文件
    lib/model.js:279
    const s = await stat(path);
  • 读取密钥环境变量
    lib/model.js:313
    const tokensSha256 = options.tokensSha256 ?? process.env.DSH_VOICE_TOKENS_SHA256 ?? '';
  • 写入本地文件
    lib/model.js:362
    await mkdir(extract, { recursive: true });
  • 写入本地文件
    lib/model.js:439
    await mkdir(dir, { recursive: true });
  • 读取本地文件
    lib/model.js:449
    await access(model);
  • 读取本地文件
    lib/model.js:450
    await access(tokens);
  • 读取本地文件
    lib/model.js:456
    await access(model);
  • 删除本地文件递归
    lib/model.js:480
    await rm(temp, { force: true, recursive: true }).catch(() => {});
  • 读取本地文件
    lib/transcriber.js:55
    const [modelStat, tokensStat] = await Promise.all([stat(model), stat(tokens)]);
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

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

功能亮点

  • 本地离线语音输入
v0.4.12026-09-18
· 安装与发布 · dist/ 改为随仓库提交。官方「添加插件」对话框支持三种来源,其中「GitHub 仓库地址」直接从 git 仓库取包且不执行任何构建,产物必须随仓库提供。此前 dist/ 被 .gitignore 忽略,用该方式安装会得到一个 main 指向不存在文件的包——安装显示成功、插件却加载不出来(静默故障)。本次为纯产物提交,dist/ 与已发布的 0.4.0 逐字节一致。 · 新增 CI 作业 dist-fresh:每次 push / PR 重新构建并校验 dist/ 与 lib/ 同步,防止「改完 lib/ 忘了 build」再次让 git 安装方式取到坏包。 · 记录一条安装方式约束:git 安装下 pnpm 会拦下包自身的构建脚本,而官方插件管理的「允许这些脚本并重试」只对 registry 包生效——git 包会直接硬报 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 且不写入待批准占位符,prepare 路径还会在 npm install(peer 解析)上二次失败。这就是本插件不采用 prepare 脚本、改为提交产物的原因。 · 文档 · README 安装章节改写为官方插件接口的两种来源(包名 / GitHub 仓库地址),补「生效时机」:新增安装即时生效(profile 热插拔),仅覆盖安装同名包时才需重启 dsh web。 · 本版本除文档与打包方式外不改变任何运行时代码(dist/ 与 0.4.0 逐字节一致)。
v0.4.02026-09-14
· 修复 · 人声守门对“首次安装即 0.3.0”的用户 100% 失效(P0 回归):corePipeline 把整段音频一次性交给 Silero VAD,违反上游 AcceptWaveform 的“每次约一个 window(512 样本)”契约,语音起点被锚定在缓冲区尾部,判定值塌缩为常数(与真实语音长度无关)→ 每段都被权威拦截、识别器从不被调用、界面永远不出字。现改为按 VAD_WINDOW_SIZE = 512 分块喂入(含尾部余数)并在末尾 flush() 弹出未闭合语音段;实测同一 7.01s fixture:修复前整段喂入恒判 314ms(拦截),修复后 3442ms(3 段 [1958,774,710],放行),其前 3s 切片 2074ms,纯稳态噪声仍判 0ms(只修“漏”、不引入“误”)。0.2.x 升级用户此前因从未触发过滤器下载而走 fail-open 才显得正常,这正是“只有新用户报障”的原因。 · GTCRN 降噪模型下载地址错配:0.3.0 起指向 asr-models 标签,直连与镜像恒 404,降噪能力从未在真实环境生效。现按发布标签分区(VAD 保持 asr-models,GTCRN 改为 speech-enhancement-models);某资产全部候选地址失败时,错误信息携带每条候选 URL 与各自失败原因。 · 存量用户的过滤器资产自动补齐:主模型已就绪但过滤器资产缺失或为 0 字节时,录音前 fire-and-forget 触发一次幂等补下载,不重复下载主模型、不阻塞录音。 · 发送手势不停麦:录音中在主输入框按 Enter/Ctrl+Enter 发送后,麦克风仍在录、迟到的识别文本落进新建空草稿。现在发送手势立即停麦并丢弃未定稿尾段,且与“键盘输入自动关闭麦克风”开关无关;Shift+Enter 与提问卡回车不触发。 · 识别文本含控制字符:写入前去除回车符、把换行折叠为空格。 · 快捷键主键匹配对修饰键/键盘布局敏感:只比 event.key 会让 macOS 上 Option+V(event.key 是 '√')与 AltGr 布局下的组合“绑得上却按不出来”;改为以物理键位 event.code(KeyV/Digit1/Space/F11)优先推导主键,event.key 仅作回退。 · 新增 · 语音快捷键:默认 Ctrl/Cmd+Alt+V(macOS ⌘⌥V,V for Voice)。触发语义与点击麦克风完全一致(空闲开始 / 录音中停止并冲刷 / 启动中取消 / 转写或下载中忽略);停止不依赖焦点。⋮ 菜单内新增「快捷键」行,行内直接捕获改绑(Esc 取消、✕ 恢复默认、保留键当场拒绝、Space 系等冲突组合允许绑定但提示),localStorage 持久化;键名大小写不敏感。主键以物理键位(event.code)优先匹配,macOS Option 组合与非美式布局下同样可用。默认键位由原计划的 Ctrl+Shift+Space 改为一组双修饰键 + 字母,因为手测发现 Ctrl+Shift+Space 被 Chrome 翻译类扩展(Google Translate 等)默认占用并吞掉按键,表现为"按了没反应"。 · 快捷键目标按焦点解析:提问卡回答框 → 该卡;主输入框或页面无焦点 → 主输入框;其他可编辑控件 → 不触发、不劫持按键。按钮与快捷键共用同一份“当前可否开始录音”判定(canStart),接管卡片弹出或提交事务状态下不会“闪一下”。 · 守门可观测面:/health 暴露 judgedRuns / emptyRuns / recentSpeechMs(最近 10 次)与按组件的 runs / errors / lastError;debug: true 时 /transcribe 的 meta 新增 gateReason 与 denoiseFailed。守门短路响应在保持 { ok, text } 结构的前提下无需开 debug 即附带 gateReason,客户端连续两段判空时给出一次可读提示。 · 插入安全:目标处于输入法组合中时写入延后到组合结束(有界 1s,超时或期间进入提交事务状态则丢弃该段);明确“程序化写入不触发宿主发送/提交手势”并有断言回归;新增只读审计钩子 window.__dshVoiceLocalDebug(默认关闭,供 issue 复现时 dump)。 · 测试与发布 · 新增跨调用累计语义的假 VAD(旧 fake“一次调用即一段”,对“一次喂多少”天然免疫,0.3.0 的 P0 正是从这个缺口漏出去的)+ 喂入契约断言(每次调用 ≤ 512、按序拼接覆盖完整输入、调用次数 > 1)。 · 新增真模型守门回
v0.3.02026-08-26
· 新增 · 噪声全链路过滤:环境杂音不再污染草稿。浏览器端静音检测升级为自适应门控(噪声底跟踪 + 双门限迟滞 + 触发前 250ms 回带 + 最短人声门);宿主端新增 GTCRN 神经降噪(可选)与 Silero VAD 人声守门——累计人声不足的段不送识别、直接不落笔。 · 文本幻觉兜底:"谢谢观看。"类识别残留、单字符超长重复、孤立标点在返回前被规则拦空,正常中英文直通。 · 过滤器模型管理:Silero VAD(~2.2MB)与 GTCRN(<2MB)随首次使用自动后台下载,支持镜像;下载完成即生效、无需重启;/health 与 /model/status 如实暴露可用/缺失/降级状态。 · 改进 · fail-open 降级语义:过滤器模型缺失或推理异常时自动旁路,听写主链路永不受影响;降噪可经配置一键关闭。 · 并发安全:recognizer / VAD / 降噪器三处懒加载统一互斥,消除并发首请求重复加载模型的竞态。 · 麦克风采集补齐 autoGainControl。 · 模型资产 · 新增运行时下载:silero_vad.onnx、gtcrn_simple.onnx(同 sherpa-onnx 官方 release,镜像机制与 SenseVoice 一致;模型依旧不打包进 npm 包)。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-voice-local DeepSeek Harness(dsh)Web UI 本地语音输入插件。 - 全程本地离线:录音与转写都在本机完成,音频不出本机、不依赖云端 API/API Key。 - 引擎:SenseVoice(sherpa-onnx-node,CPU 推理),支持中文自动标点及中/英/日/韩/粤多语言。 - 句子级实时:浏览器端静音检测断句,说一句自动回填一句,可继续说话;识别文本按光标位置插入。 - 安全:宿主路由只允许 loopback / trustedHosts 访问,非本机请求返回 403。 - 安装:标准 DSH bundle(dsh.bundle.patch),走 DSH 自带插件接口,支持包名与 GitHub 仓库地址两种来源,见安装。 安装 DSH 自带插件接口,两种来源任选其一:填进「包名或地址」,点安装,装完再点立即启用。(入口:Web GUI 侧边栏「插件」页 → 「添加插件」。) 方式一:包名(推荐) dsh-voice-local 也可以钉版本,例如 dsh-voice-local@0.4.1(不加版本号即装最新版,推荐)。这条走 npm registry,需要包已发布(本插件已发布)。
展开完整文档(README 剩余 1 节)
dsh-voice-local

DeepSeek Harness(dsh)Web UI 本地语音输入插件。

- 全程本地离线:录音与转写都在本机完成,音频不出本机、不依赖云端 API/API Key。
- 引擎:SenseVoice(sherpa-onnx-node,CPU 推理),支持中文自动标点及中/英/日/韩/粤多语言。
- 句子级实时:浏览器端静音检测断句,说一句自动回填一句,可继续说话;识别文本按光标位置插入。
- 安全:宿主路由只允许 loopback / trustedHosts 访问,非本机请求返回 403。
- 安装:标准 DSH bundle(dsh.bundle.patch),走 DSH 自带插件接口,支持包名与 GitHub 仓库地址两种来源,见安装。

安装

DSH 自带插件接口,两种来源任选其一:填进「包名或地址」,点安装,装完再点立即启用。(入口:Web GUI 侧边栏「插件」页 → 「添加插件」。)

方式一:包名(推荐)

dsh-voice-local

也可以钉版本,例如 dsh-voice-local@0.4.1(不加版本号即装最新版,推荐)。这条走 npm registry,需要包已发布(本插件已发布)。

方式二:GitHub 仓库地址

https://github.com/Real-WangLe/dsh-voice-local

想跟进尚未发版的改动时用这条。仓库里已包含构建产物 dist/,因此安装过程不执行构建、也不需要授权任何安装脚本。

生效时机

装完一般立即生效——DSH 的 profile 是热插拔的,新增插件会当场加载,不需要重启。若界面没变化,先刷新一下浏览器页面。

只有成功界面出现「已安装,下次启动后加载。」时才需要重启 dsh web。这种情况出现在覆盖安装同一个包时,例如从 dsh-voice-local 换成 dsh-voice-local@0.4.1、或换个来源重装同名插件——模块已经在进程里,必须重启才能换成新代码。

命令行等价写法

dsh plugin --profile web add dsh-voice-local # 方式一:包名
dsh plugin --profile web add github:Real-WangLe/dsh-voice-local # 方式二:GitHub 仓库
新增安装立即生效;覆盖安装同名包需重启 dsh web

首次点击麦克风会自动在后台下载 SenseVoice 模型(约 230MB),并显示进度提示;下载完成后即可开始录音。

手动下载 / 离线导入

如果自动下载在你的网络环境下较慢,可以手动下载模型文件后放到固定目录,插件检测到后不会再触发下载:

mkdir -p ~/.dsh/voice/sensevoice
cd ~/.dsh/voice/sensevoice
用浏览器/IDM/迅雷等工具下载官方 tar.bz2 并解压: https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2 解压后确认目录中有: model.int8.onnx tokens.txt

也可以使用 DSH_VOICE_MIRROR_URL 或 DSH_VOICE_MIRRORS 指定更快镜像后运行:

DSH_VOICE_MIRROR_URL="https://your-mirror/...tar.bz2" node tools/download-model.mjs

使用

1. 打开任意会话,点击输入框工具行麦克风按钮开始录音。
2. 说话;检测到停顿时自动转写并插入输入框光标位置(光标在末尾时等价追加),光标随新文本后移。
3. 再次点击麦克风按钮停止录音,未定稿的剩余语音会完成最后一次转写。
4. 识别文本不会自动发送,发送前可编辑。

语音快捷键

默认 Ctrl+Alt+V(macOS 为 ⌘⌥V,V for Voice),触发语义与点击麦克风按钮完全一致:空闲时开始、录音中停止并冲刷尾段、启动中取消;键名不区分大小写。

- 改绑:麦克风旁的 ⋮ 菜单 → 「快捷键」行,点击后显示「请按下快捷键…」,按下组合即绑定并持久化(刷新后仍生效);行内 ✕ 恢复默认。
- 目标按焦点解析:焦点在提问卡回答框 → 录向该卡;焦点在主输入框(含麦克风按钮本身)或页面空白 → 录向主输入框;焦点在设置页搜索框等其他可编辑控件 → 不触发、不劫持按键。停止录音不依赖焦点:录音中只要焦点还在页面内,按快捷键即停止并冲刷尾段(焦点在 DevTools 或浏览器地址栏时任何网页都收不到按键)。
- 保留键当场拒绝(Ctrl/⌘ + W/T/N/Tab/L、F11/F12、Alt+F4、只按修饰键);Space 系组合(Ctrl+Space、Ctrl+Shift+Space)允许绑定但会提示可能被输入法/系统/浏览器扩展占用——Ctrl+Shift+Space 是 Chrome 翻译类扩展(Google Translate 等)的默认占位,会被吞掉导致"按了没反应",因此默认键位已改为一组双修饰键 + 字母。
- 主键按物理键位匹配:macOS 的 Option 组合(event.key 会变成 √ 等符号)与非美式键盘布局下同样可用。
- 输入法组合过程中的按键、按住不放的自动重复都不会触发;录音中按回车发送时麦克风自动停止(见下)。

键盘自停(默认开启)

麦克风旁的 ⋮ 按钮 打开语音设置菜单(右上角弹出),内含说明与开关「键盘输入自动关闭麦克风」:

- 开启(默认):录音期间打字 / 粘贴 / 中文输入法 / 撤销重做会立即停止录音(未定稿尾段丢弃,避免迟到转写插进手打内容之后)。
- 关闭:保留 v1 边说边打工作流,录音不中断,转写跟随光标插入。

回车发送即停(与上面的开关无关):主输入框录音中按下不带 Shift 的 Enter 或 Ctrl/⌘+Enter(= 宿主的发送手势)会立即停止录音并丢弃未定稿尾段——消息已经发出,迟到的识别文本不应落进发送后新建的空草稿。Shift+Enter(换行)与提问卡回答框里的回车不触发。
提问卡片的回答框、审批/计划审阅卡弹出时同样适用自动停止逻辑。

另外,主输入框录音中若弹出提问 / 审批 / 计划审阅卡片,会自动停止录音并把尾段落回草稿,避免「隐形录音」。

提问卡片语音回答

智能体通过 ask-user_question 提问时,自定义回答输入区旁会出现同一枚麦克风:说话即插入当前题回答框光标处,不改变已选项、不自动提交;翻页自动跟随。若 DSH 升级后入口消失(锚点变化),插件静默降级不影响卡片本身,可用 npm run doctor 查看 q-anchor 诊断。

噪声过滤(默认开启)

插件内置两级噪声漏斗,环境杂音(风扇、键盘、背景音乐)不再被写成文字:

- 浏览器端自适应门控:持续跟踪环境噪声底,双门限迟滞判定说话起止;触发前自动回带 250ms 保证句首完整,短促敲击类声音不足最短人声时长直接不上传。
- 宿主端人声守门:每段音频上传后先经 GTCRN 神经降噪(可选),再由本地 Silero VAD 判定人声——累计人声不足 400ms 的段直接返回空文本,不会调用识别模型。
- 文本幻觉兜底:「谢谢观看。」、字幕署名、单字符超长重复等识别残留被规则拦空,正常中英文直通。

两个过滤器模型(Silero VAD ~2.2MB、GTCRN <2MB)与主模型一样不打包进 npm,首次使用时自动后台下载;两者位于不同的官方发布标签(VAD 在 asr-models,GTCRN 在 speech-enhancement-models)。它们是增强组件:缺失或加载失败时自动旁路(fail-open),听写照常可用,npm run doctor 与 /health 会如实标注状态。

存量资产自动补齐:主模型已就绪但过滤器资产缺失或为 0 字节时(例如从 0.3.0 升级、GTCRN 曾因地址错配从未下载成功),插件会在下次录音时后台触发一次补下载;不重复下载主模型、不阻塞录音,补齐后无需重启即生效。

/health 的 filters.vad 暴露守门运行计数与最近 10 次判定值(judgedRuns / emptyRuns / recentSpeechMs)、filters.denoiser 暴露运行次数与最近错误,可一眼辨识「判定值恒为常数」或「组件每次都失败」这类静默失效;守门判空时 /transcribe 响应(无需开 debug)会附带 gateReason,客户端在同一会话内连续两段判空时给出一次可读提示,而不是静默无反应。

配置

可选环境变量:

| 变量 | 说明 | 默认 |
| DSH_HOME | dsh 数据目录,模型存到 $DSH_HOME/voice/sensevoice | ~/.dsh |
| DSH_VOICE_MODEL_DIR | 模型目录覆盖 | 默认目录 |
| DSH_VOICE_MODEL_URL | 模型下载主 URL | 官方 GitHub release |
| DSH_VOICE_MIRROR_URL | 单个镜像 URL(最先尝试) | 无 |
| DSH_VOICE_MIRRORS | 逗号分隔的镜像 URL 列表(按顺序尝试) | 内置 ghfast.top/gh-proxy.com + hf-mirror 直连文件 |
| DSH_VOICE_MODEL_SHA256 | 模型归档 SHA256(可选强校验) | 内置值(若已发布) |
| DSH_VOICE_MODEL_FILE_SHA256 | 直连文件模式下 model.int8.onnx 的 SHA256(可选) | 无 |
| DSH_VOICE_TOKENS_SHA256 | 直连文件模式下 tokens.txt 的 SHA256(可选) | 无 |

也可以在 profile 的 cordis.patch.yml 中覆盖:

- insert:
- id: dsh-voice-local
name: dsh-voice-local
config:
modelUrl: 'https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/...'
mirrorUrl: 'https://your-mirror/...' # 单个首选镜像
mirrors: ['https://mirror-a/...', 'https://mirror-b/...'] # 按顺序尝试
modelDir: '/absolute/path/to/model'
sha256: '<sha256>'
噪声过滤(均可选,默认即启用)
vad: { enabled: true, minSpeechMs: 400 } # 人声守门;低于门限的段不送识别
denoise: { enabled: true } # GTCRN 降噪后再识别(含噪环境准确率更高)
debug: false # true 时 /transcribe 附带 meta 诊断字段

宿主路由

| 方法 | 路径 | 说明 |
| GET | /dsh-voice-local/v1/health | 插件/原生模块/模型状态 |
| GET | /dsh-voice-local/v1/model/status | 模型文件与下载进度 |
| POST | /dsh-voice-local/v1/model/download | 启动后台模型下载 |
| POST | /dsh-voice-local/v1/transcribe | 上传 WAV,返回识别文本 |
| GET | /dsh-voice-local/v1/diagnose | 原生模块/重采样器诊断 |

所有路由仅允许本机回环或 DSH trustedHosts 来源访问。

诊断

node scripts/doctor.mjs # 完整诊断
node scripts/doctor.mjs --json # 机器可读
node tools/download-model.mjs # 手动下载模型

开发

npm install
npm run build # 构建 dist/:复制 lib/ 并拼接浏览器 bundle dist/client.jsbash
npm test # 单元 + 路由集成测试
npm run test:e2e # jsdom 浏览器端 e2e(快捷键/目标解析/回车自停/IME 延后)
node scripts/smoke.mjs [wav] [expected.txt] # 真实模型慢速冒烟(无参默认用 test/fixtures/voice-zh-16k.wav)

dist/ 随仓库提交:官方「GitHub 仓库地址」安装方式直接从 git 取包、不执行构建,产物必须随仓库提供。改完 lib/ 请运行 npm run build 并提交 dist/——CI 的 dist-fresh 作业会重新构建并校验它与 lib/ 同步。

慢速真模型 lane 也会在打 v* tag / 发布 Release 前由 .github/workflows/smoke.yml 自动触发,不拖累每次 PR。

License

本项目采用 MIT License。

致谢

本项目部分改编自社区插件包 dsh-voice-input。参考包元数据标注的来源为 fuzhailv,原始实现采用 MIT License。

本项目保留了原始 MIT 许可声明,并对 SenseVoice 转写封装、原生模块诊断、模型管理、宿主路由以及浏览器端录音与断句逻辑进行了改造和扩展。

由于目前无法核验原始参考包的公开仓库地址,本项目不附未经确认的外部链接。
预览分享卡片长什么样 ↓Real-WangLe/dsh-voice-local
分享 · DeepSeek Harness Hub
Real-WangLe/dsh-voice-local

DeepSeek Harness Web UI 的本地离线语音输入插件,由 SenseVoice 驱动。

这是你的仓库?认领条目

回到顶部