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

按住说话 Tony250-officeteam/dsh-voice-hotkey

DeepSeek Harness
Tony250-officeteam14 天前有提交已提供中文文档扫描:未发现敏感能力

按住 F9 说话,松开自动识别并插入当前输入框

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 14 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

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

静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。

发起外部网络请求
查看扫描证据(共 2 处,展示前 2 条)
  • 发起网络请求
    client.js:475
    return fetch(TRANSCRIBE_URL, {
  • 发起网络请求
    client.js:824
    fetch(STATUS_URL).then(function (r) { return r.json(); }).then(function (payload) {
扫描于 2026/11/4(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 插件:按住 F9 说话,松开后用本地 SenseVoice 识别器转写,并插入当前聚焦的输入框

README

由 DeepSeek 最新模型翻译生成
dsh-voice-hotkey 按住 F9 说话 → 松开自动识别 → 文字插入当前获得焦点的输入框。 DSH 的语音输入插件(Host + Client 两半)。按住 F9 说话,松开后自动用本机 SenseVoice 识别,把文字插入当前获得焦点的输入框 —— 对话输入栏、提问卡片的主观作答框、或页面上任何 input / textarea / contenteditable。 English: README.en.md 为什么不用内置的语音输入 内置插件 @deepseek-ai/dsh-experimental-client-ui-voice-input 把麦克风按钮挂在 conversation.input.activity 槽位。但 ask_user_question 的提问卡片弹出时会接管整个输入栏(conversation.composer 槽位被 dsh-client-ui-user-questions 顶替),麦克风按钮随之消失,主观作答框就没法语音输入。 本插件不占用任何槽位,直接在 window 上以捕获阶段监听快捷键 —— 在哪个输入框里按,就插到哪个输入框。
展开完整文档(README 剩余 1 节)
dsh-voice-hotkey

按住 F9 说话 → 松开自动识别 → 文字插入当前获得焦点的输入框。

DSH 的语音输入插件(Host + Client 两半)。按住 F9 说话,松开后自动用本机 SenseVoice 识别,把文字插入当前获得焦点的输入框 —— 对话输入栏、提问卡片的主观作答框、或页面上任何 input / textarea / contenteditable。

English: README.en.md

为什么不用内置的语音输入

内置插件 @deepseek-ai/dsh-experimental-client-ui-voice-input 把麦克风按钮挂在 conversation.input.activity 槽位。但 ask_user_question 的提问卡片弹出时会接管整个输入栏(conversation.composer 槽位被 dsh-client-ui-user-questions 顶替),麦克风按钮随之消失,主观作答框就没法语音输入。

本插件不占用任何槽位,直接在 window 上以捕获阶段监听快捷键 —— 在哪个输入框里按,就插到哪个输入框。

前置条件

依赖 DSH 内置的语音 Bundle 提供识别器:

- @deepseek-ai/dsh-experimental-voice-input-bundle 需在 profile 的 dsh.profile.bundles 里;
- 识别模型 SenseVoiceSmall INT8(约 230 MB)需已下载到 $DSH_HOME/speech-to-text(首次启用语音 Bundle 时自动下载)。

没有语音 Bundle 时插件仍能正常加载,只是 /status 会报服务不可用、/transcribe 返回 503。

安装

从 GitHub 安装
dsh plugin --profile desktop add github:<your-user>/dsh-voice-hotkey

或从本地目录
dsh plugin --profile desktop add link:/path/to/dsh-voice-hotkey

然后:

1. Host 半侧随 profile 的 patchReload: live 即时生效;
2. 浏览器半侧需要刷新一次页面才加载。

配置

DSH 的 loader 只给客户端插件传 { name: id },拿不到 profile 里的 config,因此配置从 localStorage['dsh-voice-hotkey'] 读:

localStorage.setItem('dsh-voice-hotkey', JSON.stringify({
key: 'F9', // KeyboardEvent.code
modifiers: [], // 例如 ['ctrl','shift']
holdToTalk: true, // false = 按一下开始、再按一下结束 maxSeconds: 120, showIndicator: true }))

缺省即上表。F9 若被别的软件全局占用,改 key 即可(用 event.code 命名,如 F8、KeyG)。

HTTP 路由(Host 半侧)

| 方法 | 路径 | 说明 |
| GET | /api/dsh-voice-hotkey/status | 识别器状态,诊断用 |
| POST | /api/dsh-voice-hotkey/transcribe | body {audioBase64, providerId?, language?} → {ok, text} |

两条路由都只接受回环地址(req.socket.remoteAddress 必须是 127/8 或 ::1,含 ::ffff: 映射形式,且 Host 头也须解析为 localhost/127.x/[::1]),否则 403。

鉴权说明:dsh-client-connection 用 prefix 路由占住 /api 做浏览器 cookie 鉴权,而 webServer 的匹配是「先查 exact 表,未命中才走 prefix」。本插件注册的是 exact 路由,会优先命中并绕过浏览器鉴权 —— 这正是必须自己做回环校验的原因。

/transcribe 在把音频交给识别器之前先做结构校验:解析 RIFF/WAVE 块,要求 fmt(PCM / 16 bit / 16 kHz / 单声道)、非空 data、恰好 44 字节头的规范形态,并算时长;不符合返回明确的 400/413。上限 6 MB body / 120 秒。

识别服务用 ctx.get('speechToText') 惰性获取:语音 Bundle 被禁用时插件仍能正常加载,只是 /status 报服务不可用、/transcribe 返 503。

三个最容易踩的坑(实现里都有对应处理)

1. WAV 必须是 44 字节头的规范形态。 Windows TTS 产出的 WAV 是 18 字节 fmt 块(实测确认),provider 的 validateWave 要求恰好 16,会直接拒绝。浏览器侧用 OfflineAudioContext(1, frames, 16000) 重采样成 16 kHz 单声道后,手工编码成 44 字节头 PCM16 WAV。

2. Lexical 的 execCommand 是异步提交。 对话输入框是 Lexical。execCommand('insertText', false, text) 会派发 beforeinput,Lexical 拦下并 preventDefault(),然后在微任务里自己提交 DOM 更新。于是:

execCommand(...) -> 返回 true
element.textContent -> 同步看「没变」 element.textContent -> 一个 tick 后出现了这段文字

若按「同步检查没变 → 判定失败 → 回退手动插入」,编辑器自己的提交和回退插入会同时落地,同一句话被插两遍。正确策略是「只要编辑器动过就绝不再插」:只调用一次 execCommand → 只要 textContent 有任何变化(同步或异步都算)就立刻收手 → 给编辑器 3 个宏任务的宽限后仍无变化,才补一次纯 DOM 插入(且刻意不派发 input 事件)。判定用「有没有变化」而不是「有没有包含这段文字」—— 编辑器可能对文字做归一化(合并/拆分文本节点),用「包含」判定会误判失败而重复插入。

3. 配置只能走 localStorage,因为 loader 不给客户端插件传 config。

其他行为

- 插入目标优先级:按下快捷键那一刻的 document.activeElement(若仍 connected)→ 当前 document.activeElement → 提问作答框 [data-question-key] textarea → 对话输入框 [data-composer-input]。
- / 用原型上的原生 value setter 写入(React 受控组件才会同步),再 setSelectionRange 定位光标,最后派发 input 事件。
- 输入法组合中(isComposing 或 keyCode === 229)不抢键;event.repeat 忽略。
- 窗口 blur、document.hidden、按 Escape 一律取消录音,避免麦克风一直开着。
- 状态浮标:顶部胶囊,平时 pointer-events: none 以免挡住底部输入栏。录音中红点 + 音量波形(AnalyserNode 算 RMS);识别中黄点脉冲;成功绿点显示文字、约 1.5 秒后消失;出错红点、约 4 秒后消失且可点击关闭。
- 区分两类空结果:音频 < 0.5 秒 →「录音太短了…」;有音频但识别为空 →「没有识别到语音…」;麦克风权限被拒(NotAllowedError)有专门提示。

刻意不做

自动发送、常开麦克风、唤醒词、流式字幕。快捷键在页面失焦时不生效(浏览器收不到键盘事件)。

诊断

插件每走一步都会把状态写进 localStorage['dsh-voice-hotkey-probe'],出问题时先看它:

JSON.parse(localStorage.getItem('dsh-voice-hotkey-probe'))
// { phase: 'inserted', extra: '今天天气不错', at: '...', href: '...' }

常见 phase:listeners-installed → recording-start → stop-requested → transcribing → wav-encoded → inserted。若停在 failed / getusermedia-failed,extra 里是原因。

License

MIT
预览分享卡片长什么样 ↓Tony250-officeteam/dsh-voice-hotkey
分享 · DeepSeek Harness Hub
Tony250-officeteam/dsh-voice-hotkey

按住 F9 说话,松开自动识别并插入当前输入框

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部