@bittersmilezzz/dsh-asr-voice 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -34
- package/cordis.patch.yml +11 -7
- package/docs/images/cover.png +0 -0
- package/docs/images/screenshot-idle.png +0 -0
- package/docs/images/screenshot-preview.png +0 -0
- package/docs/images/screenshot-recording.png +0 -0
- package/lib/asr-models.js +5 -3
- package/lib/asr-models.js.map +1 -1
- package/lib/client.js +412 -61
- package/lib/client.js.map +1 -1
- package/lib/http.js +80 -7
- package/lib/http.js.map +1 -1
- package/lib/index.js +20 -3
- package/lib/index.js.map +1 -1
- package/lib/optimize.js +44 -7
- package/lib/optimize.js.map +1 -1
- package/lib/realtime-host.js +74 -4
- package/lib/realtime-host.js.map +1 -1
- package/lib/realtime-tts.js +20 -2
- package/lib/realtime-tts.js.map +1 -1
- package/lib/transcribe.js +113 -59
- package/lib/transcribe.js.map +1 -1
- package/lib/types/asr-models.d.ts.map +1 -1
- package/lib/types/http.d.ts +21 -2
- package/lib/types/http.d.ts.map +1 -1
- package/lib/types/index.d.ts +3 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/optimize.d.ts +2 -1
- package/lib/types/optimize.d.ts.map +1 -1
- package/lib/types/realtime-host.d.ts +25 -1
- package/lib/types/realtime-host.d.ts.map +1 -1
- package/lib/types/realtime-tts.d.ts.map +1 -1
- package/lib/types/settings.d.ts +21 -0
- package/lib/types/settings.d.ts.map +1 -1
- package/lib/types/transcribe.d.ts +1 -0
- package/lib/types/transcribe.d.ts.map +1 -1
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -63,8 +63,10 @@ voice input.*
|
|
|
63
63
|
点停止即整段去识别;可选静音自动停止),可选按住说话
|
|
64
64
|
- 默认快捷键 **Ctrl+Shift+Space**(可配置,支持 macOS 的 Cmd 兼容)
|
|
65
65
|
- 识别后**填入草稿**待确认;可选「识别后自动发送」(push-to-talk 风格)
|
|
66
|
-
-
|
|
67
|
-
|
|
66
|
+
- **语音对话**(默认开,`realtime.enabled`):与麦克风**同一个按钮**——点 = 录音转写,
|
|
67
|
+
长按约 450ms = 进入语音对话(对话中再点 = 打断播报 / 结束对话);关 `realtime.enabled`
|
|
68
|
+
即回到纯整段模式,按钮只剩「点 = 转写」。边说边上字幕 → 停顿即发起 agent 回合 →
|
|
69
|
+
回复按句朗读 → 念完自动回到聆听,半双工、点按可打断
|
|
68
70
|
- 设置卡片:「设置 → 插件 → 配置 → 语音输入」= **三步向导** + 默认折叠的「高级」(BaseURL /
|
|
69
71
|
模型 / 通道 / 多服务商 / 语言 / 优化 / 快捷键 / 用量);改动先进本地草稿,点「保存」才写回,
|
|
70
72
|
写回后按段读回校验
|
|
@@ -125,10 +127,12 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
125
127
|
| 行为 | `behavior.maxRecordMs` | `120000` | 单次录音上限(毫秒,5s~600s):到点自动结束并送识别 |
|
|
126
128
|
| 行为 | `behavior.silenceMs` | `2500` | 静音判定时长(毫秒,200~60000):连续安静这么久即判定说完,需开 `silenceStop` |
|
|
127
129
|
| 行为 | `behavior.silenceRms` | `0.02` | 静音阈值(0~1 响度比例):低于它算安静 |
|
|
128
|
-
| 实时 | `realtime.enabled` | `true` |
|
|
129
|
-
| 实时 | `realtime.engine` | `browser` | 出字来源:`browser`(浏览器 Web Speech,逐字上屏、零 key、不新增本机请求)/ `segmented`(本地能量 VAD 按句切段,每句走一次已有的云端整段转写,需先配好 ASR 服务商)/ `cloud`(16k PCM 帧上行 host 实时通道,SSE 下行驱动字幕与回合,服务端 VAD
|
|
130
|
-
| 实时 | `realtime.
|
|
131
|
-
| 实时 | `realtime.
|
|
130
|
+
| 实时 | `realtime.enabled` | `true` | 语音对话总开关(默认开):开着时麦克风按钮的长按(约 450ms)= 进入语音对话,`realtime.hotkey` 也生效;关掉后长按与对话快捷键都不动作,只剩「点 = 转写」(按钮本身不增删;改动即时生效,无需重载页面) |
|
|
131
|
+
| 实时 | `realtime.engine` | `browser` | 出字来源:`browser`(浏览器 Web Speech,逐字上屏、零 key、不新增本机请求)/ `segmented`(本地能量 VAD 按句切段,每句走一次已有的云端整段转写,需先配好 ASR 服务商)/ `cloud`(16k PCM 帧上行 host 实时通道,SSE 下行驱动字幕与回合,服务端 VAD 判回合;配 `realtime.provider` 选 provider) |
|
|
132
|
+
| 实时 | `realtime.provider` | `builtin` | `engine=cloud` 时走哪个实时 provider:`builtin`(host 端假 provider,开发态、不花配额)/ `dashscope-realtime`(真云端 qwen3-asr-flash-realtime,服务端 VAD 判回合,凭据复用 `DASHSCOPE_API_KEY`) |
|
|
133
|
+
| 实时 | `realtime.tts` | `browser` | 回复播报:`browser`(浏览器 `speechSynthesis`,零配置)/ `cloud`(云端 TTS,qwen3-tts-flash-realtime,凭据复用 `DASHSCOPE_API_KEY`)/ `off`(只出字不出声) |
|
|
134
|
+
| 实时 | `realtime.ttsVoice` | `Cherry` | 云端 TTS 音色(仅 `tts=cloud` 生效):qwen3-tts-flash-realtime 的系统音色名 |
|
|
135
|
+
| 实时 | `realtime.hotkey` | `Ctrl+Shift+Alt+Space` | 进出实时对话的快捷键(空 = 不用快捷键;macOS 上 `Ctrl` 兼容 `Cmd`);与 `behavior.hotkey` 撞键时**对话优先** |
|
|
132
136
|
| 实时 | `realtime.bargeIn` | `false` | **语音插话(全双工)**:播报回复期间继续收音,人声持续超过回声门即打断朗读。默认关(真机回环复测通过前保持半双工),仅 `engine=segmented` 支持 |
|
|
133
137
|
| 实时 | `realtime.turn.settleMs` | `900` | 转写文字静默多久算「说完了」(毫秒,200~10000):到点即提交并发起回合 |
|
|
134
138
|
| 实时 | `realtime.turn.tailMs` | `300` | 判完之后再宽限这么久才提交(毫秒,0~5000):接住最后一个词的迟到结果,0 = 不等 |
|
|
@@ -144,6 +148,8 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
144
148
|
| 实时切段 | `realtime.vad.maxSegmentMs` | `8000` | 单段语音长度上限(毫秒,1000~30000):说不停也强制轮换,同时是单次上传体大小的上限 |
|
|
145
149
|
| 实时切段 | `realtime.vad.maxPending` | `3` | 排队段数上限(1~20):转写慢过说话时丢最旧并提示字幕断裂 |
|
|
146
150
|
| 统计 | `/api/asr-voice/stats` | — | ASR 用量统计(次数/字符/最近时间,进程内) |
|
|
151
|
+
| 实时 | `/api/asr-voice/realtime/*` | — | `engine=cloud` 的 host 实时通道:`session` / `audio` / `events`(SSE) / `close` 四条私有路由 |
|
|
152
|
+
| 实时 | `/api/asr-voice/tts` | — | `tts=cloud` 的云端 TTS:浏览器把待播文本上行,host 用 DSH 凭据合成 PCM 回传(浏览器不持 key) |
|
|
147
153
|
|
|
148
154
|
**API key 不在上表里。** 它存于 DSH 凭据服务,按引用名读取:预置供应商直接用
|
|
149
155
|
`<PRESET>_API_KEY`(`OPENAI_API_KEY` / `GROQ_API_KEY` / `SILICONFLOW_API_KEY` /
|
|
@@ -159,23 +165,28 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
159
165
|
|
|
160
166
|
**怎么用好它**(三步):
|
|
161
167
|
|
|
162
|
-
1.
|
|
163
|
-
|
|
168
|
+
1. **开口即出字,说话而不是打字**:**长按**输入行的麦克风按钮(约 450ms)或按 `realtime.hotkey`,
|
|
169
|
+
说的时候字幕逐字上屏——不用等把话说完:停顿约一秒即判定「说完了」,草稿自动填入并发送。
|
|
170
|
+
你在对 agent 说话。
|
|
164
171
|
2. **回复朗读,随后自动还麦**:回复按句朗读(浏览器语音,或云端 TTS),念完麦克风自动回来听
|
|
165
172
|
下一句。**半双工**保证扬声器里机器自己的声音不会被当成你说的话,回声不会触发奇怪的回合。
|
|
166
|
-
3.
|
|
167
|
-
|
|
168
|
-
|
|
173
|
+
3. **三处打断,随时收放**:再点一次麦克风按钮(对话中点击 = 打断/结束)/ 再按一次快捷键 /
|
|
174
|
+
点提示条上的 `×`,立刻止读、取消在途回合、回到聆听。开启「语音插话」
|
|
175
|
+
(`realtime.bargeIn`,仅按句切段引擎)后更可以直接开口打断朗读——人声持续超过回声门才
|
|
176
|
+
生效,键盘和机器自己的声音不会误触。
|
|
169
177
|
|
|
170
178
|
引擎怎么选:`browser` 零配置零配额,但依赖浏览器语音服务(部分地区被网络屏蔽,遇 `network`
|
|
171
179
|
错误会自动降级到 `segmented`——提示「已自动改用云端识别」后照常说即可,不用手动切引擎);`segmented`
|
|
172
180
|
每句走你已配好的云端 ASR,天然适配国内网络;`cloud` 上传 PCM 到 host 实时通道、服务端判回合,
|
|
173
|
-
|
|
181
|
+
出字延迟最低——已实现,需把 `realtime.provider` 选到 `dashscope-realtime`(真云端
|
|
182
|
+
qwen3-asr-flash-realtime,凭据复用 `DASHSCOPE_API_KEY`),保持默认 `builtin` 则走 host 端
|
|
183
|
+
假 provider(开发态,不花配额)。
|
|
174
184
|
|
|
175
185
|
## 实时语音对话 Realtime voice chat
|
|
176
186
|
|
|
177
187
|
|
|
178
|
-
`realtime.enabled`
|
|
188
|
+
`realtime.enabled` 打开后,麦克风按钮**长按约 450ms** 即进入语音对话(也可用快捷键
|
|
189
|
+
`realtime.hotkey`);按钮不随开关增删,关掉开关只是长按与对话快捷键不再动作。一轮闭环:
|
|
179
190
|
|
|
180
191
|
说 → 字幕逐字上屏 → 静默 `turn.settleMs`(再宽限 `turn.tailMs`)判定说完 → **填入草稿并直接
|
|
181
192
|
发送** → agent 回复按句朗读 → 念完自动把麦克风还回来听下一句。
|
|
@@ -191,8 +202,9 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
191
202
|
`browser`/`segmented` 共用同一套 `realtime.turn.*` 静默判定,切换只改段边界的**来源**,不改
|
|
192
203
|
「什么时候算说完」。`segmented` 连续三次转写失败即判死并结束会话;转写慢过说话时丢最旧的段并
|
|
193
204
|
提示字幕断裂,而不是让字幕越拖越长。
|
|
194
|
-
`cloud` 走 host
|
|
195
|
-
回合边界由**服务端 VAD**
|
|
205
|
+
`cloud` 走 host 实时通道:16k PCM 帧量化后逐帧上行,SSE 下行事件驱动字幕与回合,
|
|
206
|
+
回合边界由**服务端 VAD** 判定(`realtime.provider = builtin` 假 provider,或
|
|
207
|
+
`dashscope-realtime` 真云端 qwen3-asr-flash-realtime),本地不再文字静默判定——逐字延迟
|
|
196
208
|
更低,代价是需要一条 host 实时通道。
|
|
197
209
|
- **半双工(默认)与语音插话(可选)**:默认朗读期间不收音,回声不会被当成你说的话——
|
|
198
210
|
虚拟设备上实测 Chromium AEC 消除率仅 0.42 dB(`echoCancellation` 基本无效),因此真机
|
|
@@ -202,11 +214,13 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
202
214
|
350ms 且显著超过回声门**才打断;键盘/关门等瞬态与 3dB 量级的弱声不会误断。
|
|
203
215
|
- **不做提示词优化**:对话要的是即时,转写文本原样上屏;`optimize.*` 只作用于整段录音模式。
|
|
204
216
|
- **到点自己收**:`realtime.maxSessionMs` 上限到即结束会话并释放麦克风,麦克风不会无人值守常开。
|
|
205
|
-
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
`
|
|
217
|
+
- **实时通道与真云端 provider 均已实现**:host 会话注册表(`sid` 由 host 铸造)+ SSE 下行带
|
|
218
|
+
背压 + `RealtimeProvider` 接缝 + 假 provider(含 undici WebSocket 带 `Authorization` 的真实
|
|
219
|
+
socket 上线证据);`realtime.engine = cloud` 时浏览器把采集帧上行到该通道、SSE 下行驱动字幕/
|
|
220
|
+
回合;真云端 provider 也已落地(`src/realtime-dashscope.ts`,阿里云百炼
|
|
221
|
+
qwen3-asr-flash-realtime,服务端 VAD 判回合),把 `realtime.provider` 选到
|
|
222
|
+
`dashscope-realtime` 即启用,凭据复用 DSH 的 `DASHSCOPE_API_KEY`;云端 TTS 同理
|
|
223
|
+
(`realtime.tts = cloud`)。两者都在 Node 22+ 上运行(依赖全局 WebSocket)。
|
|
210
224
|
|
|
211
225
|
## 云端 ASR 预置 Presets
|
|
212
226
|
|
|
@@ -229,6 +243,11 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
229
243
|
|
|
230
244
|
## 外部依赖 External Dependencies
|
|
231
245
|
|
|
246
|
+
- **Node ≥ 22**(host 半区):云端实时转写与云端 TTS 依赖 Node 内置全局 `WebSocket`
|
|
247
|
+
(undici,Node 22 起稳定)。Node 18/20 上这两条通道不可用——表现为路由 502
|
|
248
|
+
「云端通道不可用」,而不是可读的版本错误,因此 `package.json` 声明 `engines.node >= 22`,
|
|
249
|
+
`scripts/build.sh` 也会先挑一个 ≥22 的 node。其余功能(整段识别 / 优化 / browser、
|
|
250
|
+
segmented 实时引擎)不受影响。
|
|
232
251
|
- 浏览器:Web Speech API(Chrome/Edge;Safari 部分支持)、`getUserMedia` + `MediaRecorder`;
|
|
233
252
|
`realtime.engine = segmented` 另需 `AudioWorklet`(16k PCM 采集,Chrome/Edge/Safari 交集内)
|
|
234
253
|
- 云端 ASR / LLM:你配置的 OpenAI-compatible 服务(网络请求由本机 host 发起)
|
|
@@ -237,18 +256,19 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
237
256
|
## 生命周期脚本 Lifecycle Scripts
|
|
238
257
|
|
|
239
258
|
**无** `preinstall` / `install` / `postinstall` / `prepare` 等安装期脚本;
|
|
240
|
-
`build` / `build:client` / `bundle` / `typecheck`
|
|
259
|
+
`build` / `build:client` / `bundle` / `typecheck` / `pretest` / `test` 仅开发者构建与验证用,
|
|
260
|
+
不参与安装(`pretest` 是 npm 的测试前置钩子,只在本地 `npm test` 时触发,不是安装脚本)。
|
|
241
261
|
|
|
242
262
|
## 权限与已知风险 Permissions & Known Issues(保守披露)
|
|
243
263
|
|
|
244
264
|
| 权限 | 等级 | 说明 |
|
|
245
265
|
|---|---|---|
|
|
246
266
|
| 麦克风 | 高 | 浏览器 `getUserMedia` 需要用户授权;采集只由点击/快捷键发起。整段模式在点击停止或静音判定时结束;**实时对话会持续占用麦克风**,直到你结束会话,或 `realtime.maxSessionMs` 到点自动结束 |
|
|
247
|
-
| 网络 | 中 | 云端 ASR/LLM 时,本机 host 向**你配置的** baseUrl 发起 HTTPS
|
|
248
|
-
| 音频输出 | 低 |
|
|
267
|
+
| 网络 | 中 | 云端 ASR/LLM 时,本机 host 向**你配置的** baseUrl 发起 HTTPS 请求;`realtime.provider = dashscope-realtime` 或 `realtime.tts = cloud` 时另向阿里云百炼发起 WSS(WebSocket)连接 |
|
|
268
|
+
| 音频输出 | 低 | 实时对话把 agent 回复经**系统默认输出设备外放**:`realtime.tts = browser`(默认)走浏览器 `speechSynthesis`,`= cloud` 走云端 TTS 返回的 PCM;两种情况周围人都听得到,且没有单独的音量/静音路由(止声用打断入口) |
|
|
249
269
|
| 设置读写 | 中 | 读写自有 namespace `asr-voice`(**不含密钥**:两个 `apiKey` 字段标了 `role('secret')`,过线即被脱敏) |
|
|
250
270
|
| 凭据读写 | 中 | 只按**自己派生的引用名**读写:`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 落库;**已存的值永不回传浏览器**,设置页只看得到「已配置 / 未配置」 |
|
|
251
|
-
| 文件(诊断落盘) | 中 |
|
|
271
|
+
| 文件(诊断落盘) | 中 | **默认不落盘**:仅当显式设置 `DSH_ASR_DEBUG_KEEP_WAVS=1`(或 `true`/`yes`)时,才把原始录音写入 `~/.dsh/asr-voice-debug/`(可用 `DSH_ASR_DEBUG_DIR` 重定向,按**文件数 100 + 总字节 200MB** 双约束自动裁剪)用于排查采集/转码问题;未开启时连 `?capture=1` 显式抓取也一律拒绝。不执行命令、不读取其他凭据 |
|
|
252
272
|
|
|
253
273
|
已知风险:
|
|
254
274
|
|
|
@@ -287,17 +307,21 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
287
307
|
whether the default flips.*
|
|
288
308
|
- 播报音色与断句取决于操作系统装了什么语音,长句可能出现机械停顿;不接受就 `realtime.tts = off`,
|
|
289
309
|
字幕与自动提交照常。云端实时(PCM 流 + 服务端轮次判定)**已由 `engine=cloud` 接入**:host 实时
|
|
290
|
-
通道(会话注册表 + SSE 下行 + `RealtimeProvider` 接缝 + 假 provider
|
|
291
|
-
|
|
292
|
-
|
|
310
|
+
通道(会话注册表 + SSE 下行 + `RealtimeProvider` 接缝 + 假 provider)+ client 侧 cloud 引擎
|
|
311
|
+
(采集帧上行 + SSE 下行驱动字幕/回合)均已实现;**真云端 provider 也已实现**
|
|
312
|
+
(`src/realtime-dashscope.ts`,阿里云百炼 qwen3-asr-flash-realtime),把 `realtime.provider`
|
|
313
|
+
选到 `dashscope-realtime` 即走真云端,凭据复用 `DASHSCOPE_API_KEY`(需 Node 22+)。
|
|
293
314
|
*Voice quality depends on installed system voices; set `realtime.tts = off` for captions only.
|
|
294
315
|
The host realtime channel (session registry + SSE downlink + `RealtimeProvider` seam + fake
|
|
295
|
-
provider)
|
|
296
|
-
cloud provider
|
|
316
|
+
provider) and the browser half's `engine=cloud` consumer are both implemented, and so is the
|
|
317
|
+
real cloud provider (`src/realtime-dashscope.ts`, Alibaba Bailian qwen3-asr-flash-realtime):
|
|
318
|
+
point `realtime.provider` at `dashscope-realtime` to use it (credential `DASHSCOPE_API_KEY`,
|
|
319
|
+
Node 22+).*
|
|
297
320
|
- API key 存于 DSH 凭据服务(落盘位置与格式由 host 的凭据策略决定),仅本机回环可访问代理路由
|
|
298
|
-
(信任围栏防 CSRF
|
|
321
|
+
(信任围栏防 CSRF:同源判定含端口,本机其它端口上的页面借不了道)。
|
|
299
322
|
*Keys live in the DSH credential store (where and how they are persisted is the host's policy);
|
|
300
|
-
proxy routes are loopback-only (trusted-origin fence against CSRF
|
|
323
|
+
proxy routes are loopback-only (trusted-origin fence against CSRF; the same-origin check
|
|
324
|
+
includes the port, so pages on other local ports cannot borrow it).*
|
|
301
325
|
- **升级自 v0.1/v0.2 的注意**:旧版本的 `apiKey` 是写在 settings 里的明文字段,且曾随
|
|
302
326
|
`settings.describe` 过线到浏览器。本版本首次加载会自动把这些明文迁进凭据并抹掉 settings 里的值;
|
|
303
327
|
若你想立刻处理,可自己删 `~/.dsh/settings.yaml` 中的 `apiKey` 字段。**迁移前已经过线的那把 key
|
|
@@ -315,9 +339,15 @@ dsh plugin --profile <profile> add <本插件路径或 GitHub 仓库>
|
|
|
315
339
|
|
|
316
340
|
## 开发 Development
|
|
317
341
|
|
|
318
|
-
- 构建:`bash scripts/build.sh`(自动选用 Node ≥
|
|
319
|
-
或 `DSH_CHECKOUT
|
|
320
|
-
|
|
342
|
+
- 构建:`bash scripts/build.sh`(自动选用 Node ≥22;依赖树经 junction 链接到已装兄弟插件
|
|
343
|
+
或 `DSH_CHECKOUT`,**仅为构建期**便利,与运行时无关)。脚本会先 type-check client 半区
|
|
344
|
+
(`tsc -p tsconfig.client.json --noEmit`)再跑 tsdown——tsdown 不做类型检查,漏掉这一步
|
|
345
|
+
就会把带类型错误的 `lib/client.js` 提交出去;`npm run build` 同款。
|
|
346
|
+
- 类型检查:`npm run typecheck`(host + client 两个半区;`npm test` 前会自动先编译 host,
|
|
347
|
+
避免测试跑在过期的 `lib/` 上)
|
|
348
|
+
- `lib/` 入库且是发布内容:改了 `src/` 必须重跑构建并把 `lib/` 一起提交;发布工作流
|
|
349
|
+
(`.github/workflows/publish.yml`)会在 `npm publish` 前重跑构建并用 `git diff --exit-code -- lib`
|
|
350
|
+
校验产物与源码一致,不一致即中止发布。
|
|
321
351
|
- 契约:本仓库 AGENTS.md 指向伞仓库 `dsh-plugins/AGENTS.md`(单一来源)
|
|
322
352
|
|
|
323
353
|
## License
|
package/cordis.patch.yml
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
# 优先(免费免 key,Chrome/Edge 双平台),Web Speech 不可用/被网络屏蔽时自动
|
|
6
6
|
# 回落到已配置的云端 OpenAI-compatible ASR(OpenAI / Groq / 硅基流动 /
|
|
7
7
|
# 通义 Qwen-ASR,可自定义 baseUrl + model);也可手动固定 browser / cloud。
|
|
8
|
-
# -
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
8
|
+
# - 实时语音对话(默认开,realtime.enabled):与麦克风**同一个按钮**(点 = 录音转写,
|
|
9
|
+
# 长按约 450ms = 进入对话;对话中点 = 打断播报/结束对话),边说边上字幕 →
|
|
10
|
+
# 停顿即发起 agent 回合 → 回复按句朗读 → 念完自动还麦。半双工,默认
|
|
11
|
+
# engine=browser 时用浏览器 Web Speech + speechSynthesis 实现:不需要任何 key,
|
|
12
|
+
# 也不新增 host 路由;engine=segmented 走已配置的云端整段转写,engine=cloud 走
|
|
13
|
+
# host 实时通道(realtime.provider 选 'builtin' 假 provider 或真云端预置)。
|
|
14
|
+
# - 提示词优化:本地启发式(zh/en 清洗)或可选 LLM 重写(optimize.mode 默认
|
|
15
|
+
# llm,走 DSH 当前所选模型的官方 LLM 通道,host 代理)。
|
|
13
16
|
# - 设置页卡片:「设置 → 插件 → 配置」→「语音输入」(settings.plugin.item,
|
|
14
17
|
# key: asr-voice;host 注册同名 settings namespace 让配置 tab 枚举到卡片)。
|
|
15
18
|
# - API key 只进 **DSH 凭据服务**(预置引用名与官方 LLM 凭据同名),settings 与浏览器
|
|
@@ -18,8 +21,9 @@
|
|
|
18
21
|
#
|
|
19
22
|
# host inject 只列硬依赖(webServer/llm);settings 走 scoped inject(可选,
|
|
20
23
|
# 缺失时仅云端 ASR 无 key、不影响挂载),agentDefaultModel 在优化路由内
|
|
21
|
-
# ctx.get 可选读取。client 侧 settingsScope /
|
|
22
|
-
#
|
|
24
|
+
# ctx.get 可选读取。client 侧 settingsScope / locale / slots 是硬依赖(设置卡与
|
|
25
|
+
# 按钮座位必需),connection / sessions / remote.credentials 是可选 ctx.inject
|
|
26
|
+
# (缺失只让对应能力退化:密钥读写 / 回合打断,不影响挂载)。
|
|
23
27
|
# 注意:inject 项是 Cordis 服务名(非 entry id)。
|
|
24
28
|
#
|
|
25
29
|
# Install: dsh plugin --profile <profile> add <path-or-github>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/asr-models.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { keyRefFor } from "./key-ref.js";
|
|
2
|
-
import { guardRoute, sendJson } from "./http.js";
|
|
2
|
+
import { guardRoute, readUpstreamJson, redactSecret, sendJson } from "./http.js";
|
|
3
3
|
import { resolveApiKey } from "./transcribe.js";
|
|
4
4
|
/** 模型名/ID 判定为 ASR 相关的正则。
|
|
5
5
|
* 只匹配真正的语音识别模型:词边界处的 asr/audio/omni/whisper/transcri,
|
|
@@ -61,14 +61,16 @@ export function registerAsrModelsRoute(register, getProviders, ctx) {
|
|
|
61
61
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
62
62
|
signal: AbortSignal.timeout(LIST_MODELS_TIMEOUT_MS),
|
|
63
63
|
});
|
|
64
|
-
|
|
64
|
+
// 带上限读上游响应(baseUrl 可指向不可信端点):超限抛错 → 502 上游故障。
|
|
65
|
+
const raw = (await readUpstreamJson(upstream));
|
|
65
66
|
if (!upstream.ok) {
|
|
66
67
|
const errObj = raw.error;
|
|
67
68
|
const reason = typeof raw.error === 'string' ? raw.error
|
|
68
69
|
: typeof errObj?.message === 'string' ? errObj.message
|
|
69
70
|
: typeof raw.message === 'string' ? raw.message
|
|
70
71
|
: `failed to list models (HTTP ${upstream.status})`;
|
|
71
|
-
|
|
72
|
+
// 上游文本会经 reason 直通设置页,先脱敏(可能回显 Bearer key / 内部 URL)。
|
|
73
|
+
return sendJson(res, 502, { ok: false, reason: redactSecret(reason) });
|
|
72
74
|
}
|
|
73
75
|
const models = pickAsrModels(raw);
|
|
74
76
|
return sendJson(res, 200, { ok: true, providerId, model: provider.model, models });
|
package/lib/asr-models.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asr-models.js","sourceRoot":"","sources":["../src/asr-models.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"asr-models.js","sourceRoot":"","sources":["../src/asr-models.ts"],"names":[],"mappings":"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"}
|