bitterSmilezzz/dsh-asr-voice0

dsh-asr-voice

开口即成文 · Speak-to-prompt for DeepSeek Harness:云端 ASR 语音识别 + 提示词优化 + 填入草稿/自动发送,跨平台 macOS / Windows。

包名
dsh-asr-voice
版本
0.3.0
许可证
MIT
最近更新
2026年9月12日

安装

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:bitterSmilezzz/dsh-asr-voice

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 都不用填

  1. ① 识别方式 选「云端」(只想用浏览器识别的选「仅浏览器」,后面两步直接跳过)。
  2. ② 服务商 点一个 chip(OpenAI / Groq / 硅基流动 / 小米 MiMo / 阿里云百炼 / 自定义), BaseURL、模型、调用通道自动填好
  3. ③ 密钥与自检 看这一行的状态:
    • 显示 ✓ 已使用 DSH 凭据 OPENAI_API_KEY → 已经复用了你在 DSH 里配过的同名 LLM 凭据,无需任何输入
    • 显示未配置 → 把 key 粘进输入框点「保存密钥」;key 只写入 DSH 凭据,不回显、不进配置文件。
    • 点「测试连接」自检(列一次该端点的模型:一次验掉 key + BaseURL + 网络,且不用麦克风)。
  4. 点「保存」→ 刷新页面确认仍在,即可对着输入框旁的麦克风开说。

自定义服务商的凭据引用名为 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

输入框麦克风按钮录音中(红色扩散 + 实时频谱)LLM 优化预览
输入框麦克风按钮录音中LLM 优化预览

安装 Install

dsh plugin --profile 
 add 

浏览器端依赖官方 client 包(由 DSH 提供),无需额外安装。 The browser side relies on official DSH client packages — nothing extra to install.

设置项 Settings(namespace asr-voice

分组字段默认说明
识别引擎asr.providerautoauto(浏览器 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 / .modeopenai / 预置自动填v0.1 的旧单配置providers 为空时作为回退读取,新配置一律走 providers
云端asr.cloud.providers[].apiKey / asr.cloud.apiKey过渡字段(role('secret'):只为读走旧文档里的明文 key,首次加载即迁往 DSH 凭据并抹掉;除此之外 settings 与浏览器都不再持有任何密钥
优化optimize.modellmllm(默认,用当前所选 LLM 重写)/ heuristic(本地启发式)
优化optimize.previewfalsefalse(默认):停止录音立即填入清洗版文本,LLM 优化后台完成后自动替换;true:等优化完成,预览 原始→优化 后确认填入
优化optimize.llm.provider / .model可选:从 DSH 已配置模型列表指定;留空则用当前所选 LLM。自定义须先到 DSH 模型列表添加
语言languageautoauto / zh-CN / en-US
行为behavior.autoSendfalse识别后自动发送
行为behavior.silenceStopfalse静音自动停止(默认关 = 手动点击/快捷键结束录音,点停止即整段去识别)
行为behavior.holdToTalkfalse按住快捷键说话、松开结束
行为behavior.textModereplace文本输入模式:replace(完整替换草稿)/ append(在已有文字后追加)
行为behavior.copyToClipboardtrue识别/优化后自动把结果复制到剪贴板
行为behavior.hotkeyCtrl+Shift+Space快捷键(空 = 关闭)
行为behavior.maxRecordMs120000单次录音上限(毫秒,5s~600s):到点自动结束并送识别
行为behavior.silenceMs2500静音判定时长(毫秒,200~60000):连续安静这么久即判定说完,需开 silenceStop
行为behavior.silenceRms0.02静音阈值(0~1 响度比例):低于它算安静
实时realtime.enabledtrue语音对话总开关(默认开):开着才出现第二个按钮与 realtime.hotkey(改动即时生效,无需重载页面)
实时realtime.enginebrowser出字来源:browser(浏览器 Web Speech,逐字上屏、零 key、不新增本机请求)/ segmented(本地能量 VAD 按句切段,每句走一次已有的云端整段转写,需先配好 ASR 服务商)/ cloud(16k PCM 帧上行 host 实时通道,SSE 下行驱动字幕与回合,服务端 VAD 判回合)
实时realtime.ttsbrowser回复播报:browser(浏览器 speechSynthesis,零配置)/ off(只出字不出声)
实时realtime.hotkey进出实时对话的快捷键(空 = 不用快捷键);与 behavior.hotkey 撞键时对话优先
实时realtime.bargeInfalse语音插话(全双工):播报回复期间继续收音,人声持续超过回声门即打断朗读。默认关(真机回环复测通过前保持半双工),仅 engine=segmented 支持
实时realtime.turn.settleMs900转写文字静默多久算「说完了」(毫秒,200~10000):到点即提交并发起回合
实时realtime.turn.tailMs300判完之后再宽限这么久才提交(毫秒,0~5000):接住最后一个词的迟到结果,0 = 不等
实时realtime.maxSessionMs600000单次对话上限(毫秒,30s~3600s):到点自动结束并交还麦克风
实时realtime.speech.firstSentenceMinChars12首句最少字数:太短就与后句并成一段再起音,避免「好的。」这类碎片开头
实时realtime.speech.utteranceWatchdogMs60000单句朗读看门狗(毫秒):浏览器不回 onend 时按念完处理,防止麦克风被永久扣住
实时切段realtime.vad.frameMs40采集帧长(毫秒,10~500,仅 engine=segmented):越小越省延迟,越大越省调度开销
实时切段realtime.vad.rmsAutotrue有声阈值自动校准:实际判据 = max(rms, 静音期噪声底 ×3)——安静环境更灵、嘈杂环境不乱切句,换设备免重校
实时切段realtime.vad.rms0.02RMS 判有声阈值(0~1):rmsAuto 关闭时是唯一判据;开启时是下限
实时切段realtime.vad.silenceMs700连续静音多久切一段(毫秒,200~5000):也是每句上屏的固定延迟
实时切段realtime.vad.prerollMs200段前多保留多久音频(毫秒,0~1000):不留就会切掉第一个音节
实时切段realtime.vad.minSpeechMs250实际语音短于此不成为一段(毫秒,100~3000):杂音不该花一次上游配额
实时切段realtime.vad.maxSegmentMs8000单段语音长度上限(毫秒,1000~30000):说不停也强制轮换,同时是单次上传体大小的上限
实时切段realtime.vad.maxPending3排队段数上限(1~20):转写慢过说话时丢最旧并提示字幕断裂
统计/api/asr-voice/statsASR 用量统计(次数/字符/最近时间,进程内)

API key 不在上表里。 它存于 DSH 凭据服务,按引用名读取:预置供应商直接用 _API_KEYOPENAI_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

一句话闭环:开口 → 字幕逐字上屏 → 停顿即自动发起回合 → 回复按句朗读 → 念完麦克风自动回来听下一句。

怎么用好它(三步):

  1. 开口即出字,说话而不是打字:点输入行的声波按钮或按 realtime.hotkey,说的时候字幕逐字 上屏——不用等把话说完:停顿约一秒即判定「说完了」,草稿自动填入并发送。你在对 agent 说话。
  2. 回复朗读,随后自动还麦:回复按句朗读(浏览器语音,或云端 TTS),念完麦克风自动回来听 下一句。半双工保证扬声器里机器自己的声音不会被当成你说的话,回声不会触发奇怪的回合。
  3. 三处打断,随时收放:再按一次按钮 / 再按一次快捷键 / 点提示条上的 ×,立刻止读、取消 在途回合、回到聆听。开启「语音插话」(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 共用)
OpenAIhttps://api.openai.com/v1whisper-1whisper 式 /audio/transcriptionsOPENAI_API_KEY
Groqhttps://api.groq.com/openai/v1whisper-large-v3whisper 式 /audio/transcriptionsGROQ_API_KEY
硅基流动 SiliconFlowhttps://api.siliconflow.cn/v1FunAudioLLM/SenseVoiceSmallwhisper 式 /audio/transcriptionsSILICONFLOW_API_KEY
小米 MiMohttps://api.xiaomimimo.com/v1mimo-v2.5-asrchat + input_audioMIMO_API_KEY
通义/阿里云百炼 Qwen-ASRhttps://dashscope.aliyuncs.com/compatible-mode/v1qwen3-asr-flashchat + input_audioDASHSCOPE_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 + MediaRecorderrealtime.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 engine=cloud (I4); a real cloud provider is still a later stage.
  • API key 存于 DSH 凭据服务(落盘位置与格式由 host 的凭据策略决定),仅本机回环可访问代理路由 (信任围栏防 CSRF)。 *Keys live in the DSH credential store (where and how they are persisted