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

OpenRouter 语音输入 Paprikas/dsh-openrouter-voice

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

用 OpenRouter 转写模型为对话添加语音听写

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
数据截至 2026/11/05·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/05·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 27 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

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

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 6 处,展示前 6 条)
  • 读取本地文件
    lib/index.js:74
    if (!existsSync(path)) return void 0
  • 读取本地文件
    lib/index.js:75
    const parsed = JSON.parse(readFileSync(path, 'utf8'))
  • 写入本地文件
    lib/index.js:91
    mkdirSync(dirname(path), { recursive: true })
  • 写入本地文件
    lib/index.js:92
    writeFileSync(path, `${JSON.stringify(next, null, 2)}\n`, 'utf8')
  • 发起网络请求
    lib/index.js:224
    const response = await fetch(url, { headers: { accept: 'application/json' }, signal: AbortSignal.timeout(30_000) })
  • 发起网络请求
    lib/index.js:328
    response = await fetch(`${settings.baseURL}/audio/transcriptions`, {
扫描于 2026/11/5(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-client-ui-renderer@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-brand@deepseek-ai/dsh-client-store@deepseek-ai/dsh-home-paths@deepseek-ai/dsh-invariants@deepseek-ai/dsh-llm@deepseek-ai/dsh-scope
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 语音听写输入
  • 调用转写模型

README

由 DeepSeek 最新模型翻译生成
dsh-openrouter-voice 为 DeepSeek Harness 提供自包含的语音输入,走 OpenRouter:外观与内置的 composer 语音控件完全一致——位置相同,折叠态的麦克风按钮带「Dictation」提示,展开态的录音行也相同(取消、波形、状态、停止、插入 / 重新录制),图标、样式、文案全都一样。听写期间,标准发送按钮在视觉上会被替换成单个蓝色的「Transcribe and send」按钮:34×34 的尺寸、颜色、上箭头图标、悬停效果、禁用态,全都一模一样。 语音识别直接走插件自己的通道与 OpenRouter 通信,不经过 @deepseek-ai/dsh-experimental-。在公开服务上,客户端需要 connection.rpc(浏览器↔宿主传输)、sessions、conversation、slots、locale,宿主上则需要可选的 credentials:如果未来 Harness 更新改动了其中任何一项,插件会保持静默,而不是让应用启动失败。
展开完整文档(README 剩余 1 节)
dsh-openrouter-voice

为 DeepSeek Harness 提供自包含的语音输入,走 OpenRouter:外观与内置的 composer 语音控件完全一致——位置相同,折叠态的麦克风按钮带「Dictation」提示,展开态的录音行也相同(取消、波形、状态、停止、插入 / 重新录制),图标、样式、文案全都一样。听写期间,标准发送按钮在视觉上会被替换成单个蓝色的「Transcribe and send」按钮:34×34 的尺寸、颜色、上箭头图标、悬停效果、禁用态,全都一模一样。

语音识别直接走插件自己的通道与 OpenRouter 通信,不经过 @deepseek-ai/dsh-experimental-。在公开服务上,客户端需要 connection.rpc(浏览器↔宿主传输)、sessions、conversation、slots、locale,宿主上则需要可选的 credentials:如果未来 Harness 更新改动了其中任何一项,插件会保持静默,而不是让应用启动失败。

职责

| 部分 | 职责 |
| lib/index.js(宿主) | connection.rpc 的 /openrouter-voice 通道:OpenRouter 转写模型目录、模型选择、密钥解析、HTTP POST /audio/transcriptions 调用、WAV 校验、激活埋点 |
| lib/client.js(浏览器) | 标准语音控件(MediaRecorder → 16 kHz 单声道 PCM16 WAV → 通道 → inputActions.insertText)、「Transcribe and send」按钮(寻址 SessionFace.prompt),以及插件页面上的模型选择行 |

UI 挂载点:

Composer —— 插槽 conversation.input.activity,正是内置麦克风所在的位置:一个紧凑操作按钮,紧挨模型选择器的右侧。录音期间,标准发送按钮会被替换成单个蓝色按钮,它停止录音,并把转写文本作为一条独立消息发送到发起会话,同时带上已输入的文字。请求麦克风权限或转写期间,该按钮保持禁用。完成、取消或出错后,标准发送按钮恢复。草稿文本会保留;如果草稿非空,转写文本会以换行追加。宿主确认后,只有当草稿在发送期间未被编辑时才会清空。附件留在草稿里,这个按钮不会发送它们。视觉替换使用内置 CSS 规则和 SVG 箭头的副本;内置按钮通过一个作用域 CSS 选择器隐藏,该选择器绑定到当前 composer 的 capture 行,不改动 Harness 的事件监听器或 DOM 结构。
* 插件 → dsh-openrouter-voice —「转写模型」一行:一个下拉选择框,接入 OpenRouter 实时目录(GET /api/v1/models?output_modalities=transcription),外加一个「Custom ID…」选项,始终显示未保存的草稿。只有自定义模式才会在选择框下方显示独立的整行 ID 输入框。切到目录模型再切回来时,输入框的值会保留,包括未保存的文本,只要这个页面还开着。单独的 Save 和 Refresh 文字按钮负责保存选择(带保存中状态)。

模型选择存在 $DSH_HOME/openrouter-voice.json,同时记录宿主生命周期节点:imported → applied → injected → registered(外加 routes、base),失败时则记录 failed,附原因和 inert。有了这个文件,排查启动问题不用再翻进程日志。

录制不受焦点影响

说话时录制持续进行,与窗口焦点无关:窗口 blur 和 visibilitychange(切换浏览器标签页、最小化窗口)都不会中断采集——MediaRecorder 在后台继续编码,时长限制照常生效。波形动画只是进入后台休眠(隐藏标签页里 requestAnimationFrame 会暂停),你回来时再恢复。

切换标签页保留上下文

录制和转写属于模块,不属于挂载的 React 组件。开始采集时,插件通过公开的 sessions.retain 保留发起会话;切换标签页不会释放它。「转写并发送」会针对那个确切的会话调用 SessionFace.prompt,并等待宿主确认。当前草稿文本从它常驻的 conversation.input.for(binding.ctx).state 读取,绝不从屏幕上当前可见的输入框读取。完成、出错或显式取消后,会话保留被释放。

普通「Stop」在转写之后把文本插入当前光标位置:captureInsertion() 紧接在 insertText() 之前调用。录制/转写期间的编辑完全支持。如果输入框被正在进行的发送锁定,或发生错误,识别出的文本会留在插件内存里,供你在原会话中手动插入。

停止录制的方式有:Stop 按钮、「转写并发送」按钮、Escape、Cancel 按钮,或达到时长上限。

回到某个标签页时,采集行仍保持整行完全展开:输入框维护自己的展开状态标志,并在每个布局周期断言它。

新聊天立即可用

Harness 里的「New Chat」按钮会复用工作区中已有的空聊天,而聊天只有在宿主接受第一条提示词后才标记为非空。语音转写要花几秒,这段时间里聊天仍是空的——以前点「New Chat」会把你带回正在口述的那个聊天。
插件用同一个调用(sessions.create({ workspaceId }))预留工作区下一个空聊天,Harness 在没有空聊天时也用它。按钮先找到预留的聊天,打开一个干净的新会话,而音频转写继续处理,进入原来的会话。

以下情况不预留:
* 聊天已有消息历史;
* 列表里已经有空聊天行排在听写聊天之前。

配置档挂载

这个包是配置档依赖,行通过配置档的用户层(cordis.patch.yml)挂载:

- insert:
- id: openrouter-voice
name: 'dsh-openrouter-voice'

安装(本地开发用 link:,这样 lib/ 里的改动立即生效):

cd ~/.dsh/profiles/desktop
pnpm add link:../dsh-openrouter-voice

行的配置字段全部可选:

- id: openrouter-voice
name: 'dsh-openrouter-voice'
config:
model: google/gemini-3.5-transcribe # initial model if no state file exists
language: auto # auto or ISO-639-1 hint
baseURL: https://openrouter.ai/api/v1
apiKeyRef: OPENROUTER_API_KEY # credential reference or env var
maxAudioBytes: 8388608
maxDurationSeconds: 180
inferenceTimeoutMs: 120000
modelsCacheMs: 600000

API key 从 credentials 服务($DSH_HOME/.credentials.yaml)读取,读不到就回退到环境变量,所以轮换 key 后下次录音即生效,不用重启。

传输

浏览器通过共享的 /api 通道通信(connection.rpc.call('/api', …)),宿主在它下面拥有精确的 Fetch 路由:/api/openrouter-voice/<endpoint>。

使用标准载体帧格式:
请求:{ type: 'client-request', rpcId, method, payload }
响应:{ type: 'server-response', rpcId, result },其中 result 是插件信封。

端点响应遵循 { ok: true, value } 或 { ok: false, error: { code, message, details } }:

| 端点 | 载荷 | 值 |
| config | {} | 当前模型、API key 是否存在标志、大小与时长限制、目录缓存 |
| models | { force?: boolean } | OpenRouter 转写模型列表 |
| set-model | { model } | 已保存的配置 |
| reset-model | {} | 使用默认模型的配置 |
| transcribe | { audioBase64, model?, language? } | { text, audioSeconds, inferenceSeconds, model } |

兼容性

conversation.input.activity 槽位只能占一个:如果配置档里启用了实验性的 @deepseek-ai/dsh-experimental-voice-input-bundle,它已经占了这个槽位。想用这个插件并保持标准外观,就禁用实验性语音包。

测试

pnpm test # node test/host.mjs && node --import ./test/register.mjs test/client.mjs
* test/host.mjs —— Channel 协议、catalog 缓存、状态文件、WAV 解析、OpenRouter 请求构造、带 mock 网络的错误映射。
* test/client.mjs —— 通过伪造的 window.__ModuleLoader__ 挂载真实 bundle,配合 React 与 DSH 原语、SlotCore、jsdom,以及 mock 的麦克风栈:slot 注册、折叠按钮 → 展开录音行并显示波形、Stop(插入但不发送)、带 host 确认的定向发送、会话保留、模型行(catalog 选择、自定义 ID 模式、保存/刷新)、窗口失焦/可见性行为,以及 Escape 取消。
* test/live.mjs —— 用 $DSH_HOME/.credentials.yaml 里的 key 对 OpenRouter 做实时测试:

say -o /tmp/voice.aiff 'DeepSeek Harness OpenRouter voice check.'
afconvert -f WAVE -d LEI16@16000 -c 1 /tmp/voice.aiff /tmp/voice.wav
node test/live.mjs /tmp/voice.wav
预览分享卡片长什么样 ↓Paprikas/dsh-openrouter-voice
分享 · DeepSeek Harness Hub
Paprikas/dsh-openrouter-voice

用 OpenRouter 转写模型为对话添加语音听写

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