dsh-asr-voice — 语音输入(Voice Input)
dsh-asr-voice — DSH 语音输入插件
开口即成文,落键即送达。
Speak, and the words are already written.
关于 About
说话,然后文字已经写好。— Say it; the words are already written.
dsh-asr-voice 是 DeepSeek Harness 的语音输入之翼:以云端之耳倾听,以优化之手成文,
让每一次开口都直接落为可用的提示词。对着麦克风说出想法,插件把口语转成干净、可直接发送的提示词,
体验如 Codex 语音输入般顺滑。
A voice-input companion for DeepSeek Harness: it listens with cloud ears and drafts with a
polishing hand, turning every utterance into a clean, send-ready prompt — as fluid as Codex
voice input.
特色 Highlights
-
混合识别,进退自如 — Hybrid ASR, always a way out
浏览器 Web Speech 优先(免费、免 key、Chrome/Edge 双平台);不可用或被网络屏蔽时
自动回落到已配置的云端。云端支持多供应商:小米 MiMo / OpenAI / Groq / 硅基流动 /
通义 Qwen-ASR 可同存并蓄。设置页是一张三步向导:选方式 → 点服务商 → 看密钥状态,
点「测试连接」即自检并把该端点真实可用的模型灌进模型下拉。
Web Speech first, with automatic fallback to your cloud ASR. Multiple providers (MiMo, OpenAI,
Groq, SiliconFlow, Qwen-ASR) can coexist. Settings is a three-step wizard: pick the engine,
click a provider, check the key — “Test connection” self-checks and lists real models.
-
开口即对话 — Talk to the agent, not at a text box
开启实时对话后:边说边上字幕,停顿即发起回合,agent 回复按句朗读,念完自动把麦克风还回来
听下一句。半双工——朗读期间不收音,按钮 / 快捷键 / 提示条 × 三处都能打断;零 key 零配置。
Speak, see live captions, and a pause sends the turn; the reply is read back sentence by
sentence, then the mic comes back. Half-duplex — capture is gated while it speaks, and three
affordances interrupt. No key, no setup.
-
优化润于无声 — Polished without interrupting
停止录音,约一秒即把清洗版填入草稿;LLM 优化在后台润色,完成自动替换,不覆盖你的编辑。
Stop recording and the cleaned draft lands in about a second, while LLM polish happens in the
background and replaces it only when done — your edits are never overwritten.
-
隐私自守 — Privacy by design
API key 只落在 DSH 凭据服务(与 LLM 共用同一份凭据体系),既不进插件 settings、也不进
浏览器 DOM,设置页只显示「已配置 / 未配置」。录音在本地完成格式转换后再上传,浏览器仅经
/api/asr-voice/* 私有 JSON 代理而行。
API keys live in the DSH credential store only — never in the plugin's settings document nor
the browser DOM (the UI shows “configured / not configured”, nothing more). Audio is converted
locally before upload, and the browser talks through a private local proxy.
-
处处顺手 — Thoughtful touches
结果一键复制剪贴板(默认开)、完整替换或末尾追加、快捷键与按住说话、用量统计一目了然。
One-tap clipboard, replace-or-append insertion, hotkey & hold-to-talk, and a glanceable usage stats.
-
独立干净 — Zero third-party runtime
运行时只依赖官方 @deepseek-ai/* peer 包,可单独用、可组合用。
Runs on official @deepseek-ai/ peers only — usable alone or alongside other plugins.*
功能 Features
- 输入框工具行麦克风按钮(
conversation.input.right):点击开始/结束(默认手动关麦,
点停止即整段去识别;可选静音自动停止),可选按住说话
- 默认快捷键 Ctrl+Shift+Space(可配置,支持 macOS 的 Cmd 兼容)
- 识别后填入草稿待确认;可选「识别后自动发送」(push-to-talk 风格)
- 语音对话(默认开,与麦克风并列第二个按钮;关
realtime.enabled 即回到纯整段模式):边说边上字幕 →
停顿即发起 agent 回合 → 回复按句朗读 → 念完自动回到聆听,半双工、点按可打断
- 设置卡片:「设置 → 插件 → 配置 → 语音输入」= 三步向导 + 默认折叠的「高级」(BaseURL /
模型 / 通道 / 多服务商 / 语言 / 优化 / 快捷键 / 用量);改动先进本地草稿,点「保存」才写回,
写回后按段读回校验
快速开始 Quick start
三步,多数情况下一个 key 都不用填:
- ① 识别方式 选「云端」(只想用浏览器识别的选「仅浏览器」,后面两步直接跳过)。
- ② 服务商 点一个 chip(OpenAI / Groq / 硅基流动 / 小米 MiMo / 阿里云百炼 / 自定义),
BaseURL、模型、调用通道自动填好。
- ③ 密钥与自检 看这一行的状态:
- 显示
✓ 已使用 DSH 凭据 OPENAI_API_KEY → 已经复用了你在 DSH 里配过的同名 LLM 凭据,无需任何输入。
- 显示未配置 → 把 key 粘进输入框点「保存密钥」;key 只写入 DSH 凭据,不回显、不进配置文件。
- 点「测试连接」自检(列一次该端点的模型:一次验掉 key + BaseURL + 网络,且不用麦克风)。
- 点「保存」→ 刷新页面确认仍在,即可对着输入框旁的麦克风开说。
自定义服务商的凭据引用名为 ASR_VOICE_<显示名>_API_KEY(显示名参与派生,改名等于换一把 key)。
Your existing DSH LLM credential for the same provider is reused automatically — most users never
type a key. “Test connection” verifies key + base URL + network in one click without the mic.
效果 Preview
安装 Install
dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
浏览器端依赖官方 client 包(由 DSH 提供),无需额外安装。
The browser side relies on official DSH client packages — nothing extra to install.
设置项 Settings(namespace asr-voice)
| 分组 | 字段 | 默认 | 说明 |
|---|
| 识别引擎 | asr.provider | auto | auto(浏览器 Web Speech 优先,失败自动切云端)/ browser(Web Speech)/ cloud(OpenAI-compatible) |
| 云端 | asr.cloud.providers | [] | 多供应商列表:每个含 {id, preset, name, baseUrl, model, mode};name 是显示名,也是自定义供应商凭据引用名的派生依据 |
| 云端 | asr.cloud.active | 空 | 当前使用的供应商 id(空 = 取第一个);向导第 ② 步即切换 |
| 云端 | asr.cloud.preset / .baseUrl / .model / .mode | openai / 预置自动填 | v0.1 的旧单配置:providers 为空时作为回退读取,新配置一律走 providers |
| 云端 | asr.cloud.providers[].apiKey / asr.cloud.apiKey | 空 | 过渡字段(role('secret')):只为读走旧文档里的明文 key,首次加载即迁往 DSH 凭据并抹掉;除此之外 settings 与浏览器都不再持有任何密钥 |
| 优化 | optimize.mode | llm | llm(默认,用当前所选 LLM 重写)/ heuristic(本地启发式) |
| 优化 | optimize.preview | false | false(默认):停止录音立即填入清洗版文本,LLM 优化后台完成后自动替换;true:等优化完成,预览 原始→优化 后确认填入 |
| 优化 | optimize.llm.provider / .model | 空 | 可选:从 DSH 已配置模型列表指定;留空则用当前所选 LLM。自定义须先到 DSH 模型列表添加 |
| 语言 | language | auto | auto / zh-CN / en-US |
| 行为 | behavior.autoSend | false | 识别后自动发送 |
| 行为 | behavior.silenceStop | false | 静音自动停止(默认关 = 手动点击/快捷键结束录音,点停止即整段去识别) |
| 行为 | behavior.holdToTalk | |
API key 不在上表里。 它存于 DSH 凭据服务,按引用名读取:预置供应商直接用
<PRESET>_API_KEY(OPENAI_API_KEY / GROQ_API_KEY / SILICONFLOW_API_KEY /
MIMO_API_KEY / DASHSCOPE_API_KEY)——与官方 LLM 凭据同名,因此配过该服务商 LLM 的人
零输入即可用;自定义供应商用 ASR_VOICE_<显示名>_API_KEY。解析顺序:过渡期 settings 里的
残留明文 → credentials.resolve(ref) → 环境变量 ref。
实时对话演示 Realtime demo
一句话闭环:开口 → 字幕逐字上屏 → 停顿即自动发起回合 → 回复按句朗读 → 念完麦克风自动回来听下一句。
怎么用好它(三步):
- 开口即出字,说话而不是打字:点输入行的声波按钮或按
realtime.hotkey,说的时候字幕逐字
上屏——不用等把话说完:停顿约一秒即判定「说完了」,草稿自动填入并发送。你在对 agent 说话。
- 回复朗读,随后自动还麦:回复按句朗读(浏览器语音,或云端 TTS),念完麦克风自动回来听
下一句。半双工保证扬声器里机器自己的声音不会被当成你说的话,回声不会触发奇怪的回合。
- 三处打断,随时收放:再按一次按钮 / 再按一次快捷键 / 点提示条上的
×,立刻止读、取消
在途回合、回到聆听。开启「语音插话」(realtime.bargeIn,仅按句切段引擎)后更可以直接
开口打断朗读——人声持续超过回声门才生效,键盘和机器自己的声音不会误触。
引擎怎么选:browser 零配置零配额,但依赖浏览器语音服务(部分地区被网络屏蔽,遇 network
错误会自动降级到 segmented——提示「已自动改用云端识别」后照常说即可,不用手动切引擎);segmented
每句走你已配好的云端 ASR,天然适配国内网络;cloud 上传 PCM 到 host 实时通道、服务端判回合,
出字延迟最低(需 DASHSCOPE_API_KEY)。
实时语音对话 Realtime voice chat
realtime.enabled 打开后,输入行多出第二个按钮(快捷键 realtime.hotkey)。一轮闭环:
说 → 字幕逐字上屏 → 静默 turn.settleMs(再宽限 turn.tailMs)判定说完 → 填入草稿并直接
发送 → agent 回复按句朗读 → 念完自动把麦克风还回来听下一句。
- 停顿即发起回合:实时模式恒等于「自动发送」,与
behavior.autoSend 无关——那一次点击
换成了每句的静默判定,草稿框里的内容会真的被提交执行。behavior.textMode 仍然生效:
append 保留你已敲的文字,replace 覆盖草稿。
- 三种引擎,回合判据同源:
browser 用浏览器 Web Speech 连续识别,逐字上屏,不新增任何本机
host 请求、不需要云商 key(识别由浏览器自己的语音服务完成,音频出机方式见下节披露,因此同样受
Firefox 无 Web Speech 的限制)。segmented 用本地能量 VAD 把连续麦克风切成句,每句走一次已有的
云端整段转写:要先配好 ASR 服务商,出字节奏是「说完 vad.silenceMs + 一个往返」而非逐字,
换来的是不依赖浏览器语音服务、且电平表由真实麦克风电平驱动。
browser/segmented 共用同一套 realtime.turn.* 静默判定,切换只改段边界的来源,不改
「什么时候算说完」。segmented 连续三次转写失败即判死并结束会话;转写慢过说话时丢最旧的段并
提示字幕断裂,而不是让字幕越拖越长。
cloud 走 host 实时通道(I3 交付):16k PCM 帧量化后逐帧上行,SSE 下行事件驱动字幕与回合,
回合边界由服务端 VAD 判定(I3 假 provider / I5 真云端),本地不再文字静默判定——逐字延迟
更低,代价是需要一条 host 实时通道。
- 半双工(默认)与语音插话(可选):默认朗读期间不收音,回声不会被当成你说的话——
虚拟设备上实测 Chromium AEC 消除率仅 0.42 dB(
echoCancellation 基本无效),因此真机
回环复测通过前不冒然默认全双工。打断三入口——再按一次按钮、再按一次快捷键、点提示条
×——任一都立刻止住朗读、取消在途回合、回到聆听。开启 realtime.bargeIn 后(仅
engine=segmented):播报期间继续收音,TTS 回声被能量门当背景学习,人声持续
350ms 且显著超过回声门才打断;键盘/关门等瞬态与 3dB 量级的弱声不会误断。
- 不做提示词优化:对话要的是即时,转写文本原样上屏;
optimize.* 只作用于整段录音模式。
- 到点自己收:
realtime.maxSessionMs 上限到即结束会话并释放麦克风,麦克风不会无人值守常开。
- I3/I4 已交付实时通道 + 浏览器侧 cloud 引擎:host 会话注册表(
sid 由 host 铸造)+ SSE
下行带背压 + RealtimeProvider 接缝 + 假 provider 已实现并全量测试(含 undici WebSocket 带
Authorization 的真实 socket 上线证据);realtime.engine = cloud 时浏览器把采集帧上行到该
通道、SSE 下行驱动字幕/回合(7 例单测)。接入真云端 provider 属于后续阶段,届时只替换 host 的
createProvider。
云端 ASR 预置 Presets
| 预置 | baseUrl | 默认模型 | 通道 | 凭据引用名(与 LLM 共用) |
|---|
| OpenAI | https://api.openai.com/v1 | whisper-1 | whisper 式 /audio/transcriptions | OPENAI_API_KEY |
| Groq | https://api.groq.com/openai/v1 | whisper-large-v3 | whisper 式 /audio/transcriptions | GROQ_API_KEY |
| 硅基流动 SiliconFlow | https://api.siliconflow.cn/v1 | FunAudioLLM/SenseVoiceSmall | whisper 式 /audio/transcriptions | SILICONFLOW_API_KEY |
| 小米 MiMo | https://api.xiaomimimo.com/v1 | mimo-v2.5-asr | chat + input_audio | MIMO_API_KEY |
| 通义/阿里云百炼 Qwen-ASR | https://dashscope.aliyuncs.com/compatible-mode/v1 | qwen3-asr-flash | chat + input_audio | DASHSCOPE_API_KEY |
| 自定义 | 你填 | 你填 | 按模型选 | ASR_VOICE_<显示名>_API_KEY |
两条调用通道(设置项 asr.cloud.mode,默认 auto):
- whisper 式
transcriptions:multipart 上传到 /audio/transcriptions(OpenAI / Groq / 硅基流动 / 本地部署)。
- chat + input_audio
chat:base64 data URI 走 /chat/completions——小米 MiMo-V2.5-ASR、通义 Qwen-ASR 等音频大模型的 OpenAI 兼容姿势。
- auto:按模型名自动判定(模型名含
asr/audio/omni/sensevoice 走 chat,否则 whisper 式)。
自定义端点兼容任何 OpenAI-compatible 服务(按模型选对应通道)。
Any OpenAI-compatible endpoint works — pick the channel to match your model.
外部依赖 External Dependencies
- 浏览器:Web Speech API(Chrome/Edge;Safari 部分支持)、
getUserMedia + MediaRecorder;
realtime.engine = segmented 另需 AudioWorklet(16k PCM 采集,Chrome/Edge/Safari 交集内)
- 云端 ASR / LLM:你配置的 OpenAI-compatible 服务(网络请求由本机 host 发起)
- 运行时不依赖任何第三方 DSH 插件(与 dsh-ui-tweaks 等完全独立,可单独用、可组合用)
生命周期脚本 Lifecycle Scripts
无 preinstall / install / postinstall / prepare 等安装期脚本;
build / build:client / bundle / typecheck 仅开发者构建用,不参与安装。
权限与已知风险 Permissions & Known Issues(保守披露)
| 权限 | 等级 | 说明 |
|---|
| 麦克风 | 高 | 浏览器 getUserMedia 需要用户授权;采集只由点击/快捷键发起。整段模式在点击停止或静音判定时结束;实时对话会持续占用麦克风,直到你结束会话,或 realtime.maxSessionMs 到点自动结束 |
| 网络 | 中 | 云端 ASR/LLM 时,本机 host 向你配置的 baseUrl 发起 HTTPS 请求 |
| 音频输出 | 低 | 实时对话用浏览器 speechSynthesis 经系统默认输出设备外放 agent 回复:周围人听得到,且没有单独的音量/静音路由(止声用打断入口) |
| 设置读写 | 中 | 读写自有 namespace asr-voice(不含密钥:两个 apiKey 字段标了 role('secret'),过线即被脱敏) |
| 凭据读写 | 中 | 只按自己派生的引用名读写:OPENAI_API_KEY / GROQ_API_KEY / SILICONFLOW_API_KEY / MIMO_API_KEY / DASHSCOPE_API_KEY / ASR_VOICE_*_API_KEY。预置引用名与官方 LLM 凭据同名(刻意复用,代价是共用同一把 key 与配额)。页面上输入的 key 仅在保存那一次经 connection RPC 送到 host 落库;已存的值永不回传浏览器,设置页只看得到「已配置 / 未配置」 |
| 文件(诊断落盘) | 中 | 转写失败 / 识别结果异常短 / 显式诊断抓取时,将原始录音写入 ~/.dsh/asr-voice-debug/(可用 DSH_ASR_DEBUG_DIR 重定向,自动裁剪至 100 个);不执行命令、不读取其他凭据 |
已知风险:
- 若见「未检测到声音」之语,请将浏览器地址栏站点设置中的输入设备选为「内置麦克风」——
远程控制/直播软件安装的虚拟音频设备常被误选,徒留静音寂寂;插件静音守卫会拦截此类录音并明言相告,
不向云端虚报。
If you see "no sound detected", pick the built-in microphone as the input device in the
browser's site settings — virtual audio devices are often selected by mistake and record silence.
The silence guard blocks such recordings and tells you plainly instead of wasting a cloud call.
- 浏览器 Web Speech 在 Firefox 不可用(提示改用云端);识别质量取决于浏览器/服务商。
Web Speech is unavailable on Firefox (it will prompt you to use cloud ASR); recognition quality
varies by browser and provider.
- 云端转写会把你的语音上传到所配置的服务商,请确认其隐私政策。
Audio is uploaded to your configured provider for transcription — review their privacy policy.
- 实时对话会在你没有再点击的情况下发起回合。 每句的静默判定就是提交点,草稿里的内容
直接进 agent;若该会话配了工具或审批,你说出的每一句都可能真的触发执行。共享终端上、
或开着高权限工具时,不要把
realtime.enabled 打开。
Realtime chat starts agent turns without another click — the pause is the send. Keep it off on
shared machines or when high-privilege tools are armed.
engine=browser(默认):实时对话期间麦克风持续流经浏览器自己的在线语音识别服务
(Chrome / Edge / Safari 各自的后端,非本插件的服务器),比整段模式的占用时长长得多。
本插件不经手、不落盘这段音频。
While a browser-engine session is open, audio streams continuously to the browser's own speech
service — not to this plugin's servers, which neither handle nor store it.
engine=segmented:每说完一句,该句音频就作为一次独立转写请求上传到你配置的云端 ASR
(与整段模式同一服务商、同一凭据),并按句消耗其配额;一次对话 = N 次请求,而不是 1 次。
VAD 只认响度,安静环境里的呼吸、键盘声若超过 vad.rms 也会照发一次(调高它即可,趋零的段
由静音守卫当场拦下、不上游)。
With the segmented engine, every utterance becomes one upload to your configured cloud ASR and
consumes quota per sentence; raise vad.rms if breaths or keystrokes are being billed.
- 语音插话需真机复测:浏览器回声消除在假设备管路线上实测不生效(消除率 0.42 dB),
因此
realtime.bargeIn 默认关。打开后打断走软件回声门(纯能量,不依赖 AEC);真机
(真实扬声器 + 麦克风回环)复测脚本就位后在真实声学下确认误断率,再考虑翻转默认。
Barge-in is off by default: Chromium's AEC measured 0.42 dB on virtual devices, so acoustic
interruption uses a software echo gate. Turn it on to try; a real-device retest will decide
whether the default flips.
- 播报音色与断句取决于操作系统装了什么语音,长句可能出现机械停顿;不接受就
realtime.tts = off,
字幕与自动提交照常。云端实时(PCM 流 + 服务端轮次判定)已由 engine=cloud 接入:host 实时
通道(会话注册表 + SSE 下行 + RealtimeProvider 接缝 + 假 provider)随 I3 交付,client 侧 cloud
引擎(采集帧上行 + SSE 下行驱动字幕/回合)随 I4 交付;真云端 provider(如 qwen3-asr-flash-realtime)
仍是后续阶段。
Voice quality depends on installed system voices; set realtime.tts = off for captions only.
The host realtime channel (session registry + SSE downlink + RealtimeProvider seam + fake
provider) shipped in I3, and the browser half now consumes it via (I4); a real
cloud provider is still a later stage.
开发 Development
- 构建:
bash scripts/build.sh(自动选用 Node ≥18;依赖树经 junction 链接到已装兄弟插件
或 DSH_CHECKOUT,仅为构建期便利,与运行时无关)
- 类型检查:
node_modules/.bin/tsc -p tsconfig.host.json --noEmit && node_modules/.bin/tsc -p tsconfig.client.json --noEmit
- 契约:本仓库 AGENTS.md 指向伞仓库
dsh-plugins/AGENTS.md(单一来源)
License
MIT