@bittersmilezzz/dsh-asr-voice 0.3.1
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/LICENSE +21 -0
- package/README.md +325 -0
- package/cordis.patch.yml +32 -0
- package/lib/asr-models.js +83 -0
- package/lib/asr-models.js.map +1 -0
- package/lib/client.js +6706 -0
- package/lib/client.js.map +1 -0
- package/lib/http.js +113 -0
- package/lib/http.js.map +1 -0
- package/lib/index.js +193 -0
- package/lib/index.js.map +1 -0
- package/lib/key-ref.js +25 -0
- package/lib/key-ref.js.map +1 -0
- package/lib/optimize.js +168 -0
- package/lib/optimize.js.map +1 -0
- package/lib/presets.js +98 -0
- package/lib/presets.js.map +1 -0
- package/lib/realtime-dashscope.js +211 -0
- package/lib/realtime-dashscope.js.map +1 -0
- package/lib/realtime-host.js +413 -0
- package/lib/realtime-host.js.map +1 -0
- package/lib/realtime-provider.js +143 -0
- package/lib/realtime-provider.js.map +1 -0
- package/lib/realtime-tts.js +179 -0
- package/lib/realtime-tts.js.map +1 -0
- package/lib/settings.js +155 -0
- package/lib/settings.js.map +1 -0
- package/lib/stats.js +30 -0
- package/lib/stats.js.map +1 -0
- package/lib/transcribe.js +274 -0
- package/lib/transcribe.js.map +1 -0
- package/lib/types/asr-models.d.ts +30 -0
- package/lib/types/asr-models.d.ts.map +1 -0
- package/lib/types/http.d.ts +41 -0
- package/lib/types/http.d.ts.map +1 -0
- package/lib/types/index.d.ts +75 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/key-ref.d.ts +9 -0
- package/lib/types/key-ref.d.ts.map +1 -0
- package/lib/types/optimize.d.ts +41 -0
- package/lib/types/optimize.d.ts.map +1 -0
- package/lib/types/presets.d.ts +64 -0
- package/lib/types/presets.d.ts.map +1 -0
- package/lib/types/realtime-dashscope.d.ts +41 -0
- package/lib/types/realtime-dashscope.d.ts.map +1 -0
- package/lib/types/realtime-host.d.ts +95 -0
- package/lib/types/realtime-host.d.ts.map +1 -0
- package/lib/types/realtime-provider.d.ts +76 -0
- package/lib/types/realtime-provider.d.ts.map +1 -0
- package/lib/types/realtime-tts.d.ts +42 -0
- package/lib/types/realtime-tts.d.ts.map +1 -0
- package/lib/types/settings.d.ts +143 -0
- package/lib/types/settings.d.ts.map +1 -0
- package/lib/types/stats.d.ts +29 -0
- package/lib/types/stats.d.ts.map +1 -0
- package/lib/types/transcribe.d.ts +46 -0
- package/lib/types/transcribe.d.ts.map +1 -0
- package/lib/types/tsconfig.client.tsbuildinfo +1 -0
- package/package.json +146 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-host.js","sourceRoot":"","sources":["../src/realtime-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/** dsh-asr-voice — host 半区:实时转写 provider 接缝 + 假 provider(I3 交付)。
|
|
2
|
+
* `RealtimeProvider` 是 host 与上游实时 ASR 之间的最小契约:浏览器 PCM 上行经
|
|
3
|
+
* `RealtimeHost`(realtime-host.ts)转发到这里,provider 回吐流式事件
|
|
4
|
+
* (speech-started / partial / final / speech-stopped / error),再由 host 经
|
|
5
|
+
* SSE 下行推给浏览器。
|
|
6
|
+
* 为什么要有接缝:I3 阶段没有真云端可连(真 provider 是 I5 的 qwen3-asr-flash-realtime,
|
|
7
|
+
* 走 OpenAI-compatible Realtime API over WebSocket)。接缝让 host 通道先于真实上游
|
|
8
|
+
* 建成并单测,I5 只新增一个 `RealtimeProvider` 实现,接缝与 host 通道一行不改。
|
|
9
|
+
* 假 provider 用能量 VAD 把进来的 PCM 切成「句」:句内周期吐 partial、句尾吐 final +
|
|
10
|
+
* speech-stopped——行为形状对齐真流式通道(先 partial 后 final,服务端 VAD 断句),
|
|
11
|
+
* 因此 I4 用它能端到端验证字幕与播放。纯 Node 标准库,macOS / Windows 双平台。
|
|
12
|
+
*/
|
|
13
|
+
/** 16k 采样率(与 client 的 PCM_SAMPLE_RATE 一致;host 不 import client,本地定义)。 */
|
|
14
|
+
const SAMPLE_RATE = 16_000;
|
|
15
|
+
/** 分析窗长(毫秒):VAD 的时间分辨率,不开放。 */
|
|
16
|
+
const WINDOW_MS = 20;
|
|
17
|
+
/** 假 provider 默认调参:阈值偏低(假数据通常安静),便于测试造简单波形。 */
|
|
18
|
+
export const FAKE_REALTIME_DEFAULTS = {
|
|
19
|
+
rms: 0.02,
|
|
20
|
+
silenceMs: 600,
|
|
21
|
+
minSpeechMs: 200,
|
|
22
|
+
maxSegmentMs: 8_000,
|
|
23
|
+
partialMs: 600,
|
|
24
|
+
};
|
|
25
|
+
/** int16 小端字节块 → RMS(0~1)。 */
|
|
26
|
+
function rmsInt16(data) {
|
|
27
|
+
const n = data.byteLength >> 1;
|
|
28
|
+
if (n === 0)
|
|
29
|
+
return 0;
|
|
30
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
31
|
+
let sum = 0;
|
|
32
|
+
for (let i = 0; i < n; i++) {
|
|
33
|
+
const s = view.getInt16(i * 2, true) / 0x8000;
|
|
34
|
+
sum += s * s;
|
|
35
|
+
}
|
|
36
|
+
return Math.sqrt(sum / n);
|
|
37
|
+
}
|
|
38
|
+
/** 假 provider 的连接实现:能量 VAD 把 PCM 切成句,按句吐 partial → final。 */
|
|
39
|
+
class FakeRealtimeConnection {
|
|
40
|
+
tuning;
|
|
41
|
+
onEvent = null;
|
|
42
|
+
silenceWindows;
|
|
43
|
+
minSpeechWindows;
|
|
44
|
+
maxSegmentWindows;
|
|
45
|
+
partialWindows;
|
|
46
|
+
/** 攒窗缓冲(一个分析窗的 int16 字节)。 */
|
|
47
|
+
win = new Uint8Array((SAMPLE_RATE * WINDOW_MS) / 1000 * 2);
|
|
48
|
+
winLen = 0;
|
|
49
|
+
speaking = false;
|
|
50
|
+
silenceRun = 0;
|
|
51
|
+
speechWindows = 0;
|
|
52
|
+
sincePartial = 0;
|
|
53
|
+
/** 已交出的句数(final 序号)。 */
|
|
54
|
+
segNo = 0;
|
|
55
|
+
closed = false;
|
|
56
|
+
constructor(tuning) {
|
|
57
|
+
this.tuning = tuning;
|
|
58
|
+
this.silenceWindows = Math.max(1, Math.round(tuning.silenceMs / WINDOW_MS));
|
|
59
|
+
this.minSpeechWindows = Math.max(1, Math.round(tuning.minSpeechMs / WINDOW_MS));
|
|
60
|
+
this.maxSegmentWindows = Math.max(this.minSpeechWindows + 1, Math.round(tuning.maxSegmentMs / WINDOW_MS));
|
|
61
|
+
this.partialWindows = Math.max(1, Math.round(tuning.partialMs / WINDOW_MS));
|
|
62
|
+
}
|
|
63
|
+
emit(ev) {
|
|
64
|
+
if (!this.closed)
|
|
65
|
+
this.onEvent?.(ev);
|
|
66
|
+
}
|
|
67
|
+
/** 处理一个完整分析窗(int16 字节,长度 = 窗采样数 × 2)。 */
|
|
68
|
+
handleWindow(bytes) {
|
|
69
|
+
const voiced = rmsInt16(bytes) > this.tuning.rms;
|
|
70
|
+
if (!this.speaking) {
|
|
71
|
+
if (!voiced)
|
|
72
|
+
return;
|
|
73
|
+
this.speaking = true;
|
|
74
|
+
this.silenceRun = 0;
|
|
75
|
+
this.speechWindows = 1;
|
|
76
|
+
this.sincePartial = this.partialWindows; // 开句立即吐一次 partial
|
|
77
|
+
this.emit({ type: 'speech-started' });
|
|
78
|
+
this.emit({ type: 'partial', text: `模拟转写·第${this.segNo + 1}段` });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (voiced) {
|
|
82
|
+
this.speechWindows += 1; // minSpeech/maxSegment 只数「有声」窗,静音窗不拉长语音时长
|
|
83
|
+
this.silenceRun = 0;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
this.silenceRun += 1;
|
|
87
|
+
}
|
|
88
|
+
this.sincePartial += 1;
|
|
89
|
+
if (this.sincePartial >= this.partialWindows) {
|
|
90
|
+
this.sincePartial = 0;
|
|
91
|
+
this.emit({ type: 'partial', text: `模拟转写·第${this.segNo + 1}段…` });
|
|
92
|
+
}
|
|
93
|
+
// 静音闭合一段,或说到段上限强制轮换:都算「这一句说完了」。
|
|
94
|
+
if (this.silenceRun >= this.silenceWindows || this.speechWindows >= this.maxSegmentWindows) {
|
|
95
|
+
this.closeSegment();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** 收口当前段:段长达标交 final(杂音/咳嗽不占回合),太短只发 VAD 边界。 */
|
|
99
|
+
closeSegment() {
|
|
100
|
+
this.speaking = false;
|
|
101
|
+
if (this.speechWindows >= this.minSpeechWindows) {
|
|
102
|
+
this.segNo += 1;
|
|
103
|
+
this.emit({ type: 'speech-stopped' });
|
|
104
|
+
this.emit({ type: 'final', text: `模拟转写·第${this.segNo}段` });
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.emit({ type: 'speech-stopped' });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
send(pcm) {
|
|
111
|
+
if (this.closed || pcm.byteLength === 0)
|
|
112
|
+
return;
|
|
113
|
+
const bytes = pcm instanceof Uint8Array ? pcm : new Uint8Array(pcm);
|
|
114
|
+
let i = 0;
|
|
115
|
+
while (i < bytes.byteLength) {
|
|
116
|
+
const take = Math.min(bytes.byteLength - i, this.win.byteLength - this.winLen);
|
|
117
|
+
this.win.set(bytes.subarray(i, i + take), this.winLen);
|
|
118
|
+
this.winLen += take;
|
|
119
|
+
i += take;
|
|
120
|
+
if (this.winLen >= this.win.byteLength) {
|
|
121
|
+
const full = this.win.slice();
|
|
122
|
+
this.winLen = 0;
|
|
123
|
+
this.handleWindow(full);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
close() {
|
|
128
|
+
if (this.closed)
|
|
129
|
+
return;
|
|
130
|
+
// 收尾:正在说的一段也交掉,别让最后一句凭空消失(对齐真实通道的 session.finish)。
|
|
131
|
+
// 必须在置 closed=true 之前 emit——emit() 会拒绝已关闭连接上的事件。
|
|
132
|
+
if (this.speaking)
|
|
133
|
+
this.closeSegment();
|
|
134
|
+
this.closed = true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** 创建假 provider(I3 阶段 host 用它驱动整条通道;I5 换成真 provider 实现)。 */
|
|
138
|
+
export function createFakeRealtimeProvider(tuning = FAKE_REALTIME_DEFAULTS) {
|
|
139
|
+
return {
|
|
140
|
+
connect: async () => new FakeRealtimeConnection(tuning),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=realtime-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-provider.js","sourceRoot":"","sources":["../src/realtime-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { guardRoute, readJsonBody, sendJson } from "./http.js";
|
|
2
|
+
import { resolveApiKey } from "./transcribe.js";
|
|
3
|
+
/** 文本长度上限(字符):client 分句泵已切 ≤200 的块,这里防御性设上限。 */
|
|
4
|
+
const MAX_TEXT_CHARS = 500;
|
|
5
|
+
/** 合成等待上限(毫秒):一句语音正常远低于此。 */
|
|
6
|
+
const TTS_TIMEOUT_MS = 20_000;
|
|
7
|
+
/** 建一条 DashScope TTS 连接并合成一整句。 */
|
|
8
|
+
export async function synthesize(apiKey, text, voice = 'Cherry', wssUrl = 'wss://dashscope.aliyuncs.com/api-ws/v1/realtime') {
|
|
9
|
+
if (!apiKey)
|
|
10
|
+
throw new Error('cloud tts: no API key');
|
|
11
|
+
if (text.trim() === '')
|
|
12
|
+
throw new Error('cloud tts: empty text');
|
|
13
|
+
if (text.length > MAX_TEXT_CHARS)
|
|
14
|
+
throw new Error(`cloud tts: text too long (${text.length} > ${MAX_TEXT_CHARS})`);
|
|
15
|
+
const url = `${wssUrl.replace(/\/+$/, '')}?model=${encodeURIComponent('qwen3-tts-flash-realtime')}`;
|
|
16
|
+
const ws = new WebSocket(url, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
17
|
+
return await new Promise((resolve, reject) => {
|
|
18
|
+
const chunks = [];
|
|
19
|
+
let settled = false;
|
|
20
|
+
let sessionReady = false;
|
|
21
|
+
let textSent = false;
|
|
22
|
+
let audioDone = false;
|
|
23
|
+
const timer = setTimeout(() => {
|
|
24
|
+
if (!settled) {
|
|
25
|
+
settled = true;
|
|
26
|
+
try {
|
|
27
|
+
ws.close();
|
|
28
|
+
}
|
|
29
|
+
catch { /* noop */ }
|
|
30
|
+
reject(new Error('cloud tts: timeout'));
|
|
31
|
+
}
|
|
32
|
+
}, TTS_TIMEOUT_MS);
|
|
33
|
+
const finish = (pcm) => {
|
|
34
|
+
if (settled)
|
|
35
|
+
return;
|
|
36
|
+
settled = true;
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
// 收完先优雅关:session.finish 通知服务端清理(socket 保持打开到 finally 才 close,
|
|
39
|
+
// 否则这条帧会被 close 截断)。
|
|
40
|
+
try {
|
|
41
|
+
ws.send(JSON.stringify({ type: 'session.finish', event_id: ev() }));
|
|
42
|
+
}
|
|
43
|
+
catch { /* noop */ }
|
|
44
|
+
resolve({ pcm, sampleRate: 16000 });
|
|
45
|
+
};
|
|
46
|
+
const fail = (code) => {
|
|
47
|
+
if (settled)
|
|
48
|
+
return;
|
|
49
|
+
settled = true;
|
|
50
|
+
clearTimeout(timer);
|
|
51
|
+
try {
|
|
52
|
+
ws.close();
|
|
53
|
+
}
|
|
54
|
+
catch { /* noop */ }
|
|
55
|
+
reject(new Error(`cloud tts: ${code}`));
|
|
56
|
+
};
|
|
57
|
+
ws.onopen = () => {
|
|
58
|
+
// 连接建立后先配会话(音色/格式/采样率),再送文本触发合成。
|
|
59
|
+
try {
|
|
60
|
+
ws.send(JSON.stringify({
|
|
61
|
+
type: 'session.update',
|
|
62
|
+
event_id: ev(),
|
|
63
|
+
session: { voice, response_format: 'pcm', sample_rate: 16000 },
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
fail('socket-closed');
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
ws.onmessage = (msg) => {
|
|
71
|
+
if (settled)
|
|
72
|
+
return;
|
|
73
|
+
let evt;
|
|
74
|
+
try {
|
|
75
|
+
evt = JSON.parse(String(msg.data));
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
switch (evt.type) {
|
|
81
|
+
case 'session.updated':
|
|
82
|
+
sessionReady = true;
|
|
83
|
+
break;
|
|
84
|
+
case 'response.audio.delta':
|
|
85
|
+
if (evt.delta !== undefined && evt.delta !== '')
|
|
86
|
+
chunks.push(Buffer.from(evt.delta, 'base64'));
|
|
87
|
+
break;
|
|
88
|
+
case 'response.audio.done':
|
|
89
|
+
audioDone = true;
|
|
90
|
+
// 音频数据收齐:合成完成,直接收口(不再等 response.done——部分模型不保证送达)。
|
|
91
|
+
if (chunks.length > 0)
|
|
92
|
+
finish(Buffer.concat(chunks));
|
|
93
|
+
break;
|
|
94
|
+
case 'response.done':
|
|
95
|
+
// 兜底:某些实现只发 response.done 不发 audio.done。
|
|
96
|
+
if (!audioDone && chunks.length > 0)
|
|
97
|
+
finish(Buffer.concat(chunks));
|
|
98
|
+
break;
|
|
99
|
+
case 'error':
|
|
100
|
+
fail(evt.error?.code ?? 'provider-error');
|
|
101
|
+
break;
|
|
102
|
+
default:
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
// 会话就绪且还没送文本:append + commit 触发合成(只送一次)。
|
|
106
|
+
if (sessionReady && !textSent) {
|
|
107
|
+
textSent = true;
|
|
108
|
+
try {
|
|
109
|
+
ws.send(JSON.stringify({ type: 'input_text_buffer.append', event_id: ev(), text }));
|
|
110
|
+
ws.send(JSON.stringify({ type: 'input_text_buffer.commit', event_id: ev() }));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
fail('socket-closed');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
ws.onerror = () => fail('provider-unreachable');
|
|
118
|
+
ws.onclose = () => {
|
|
119
|
+
// 对端先断:已收到音频就按结果收口,否则是异常断连。
|
|
120
|
+
clearTimeout(timer);
|
|
121
|
+
if (settled)
|
|
122
|
+
return;
|
|
123
|
+
if (chunks.length > 0) {
|
|
124
|
+
finish(Buffer.concat(chunks));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
fail('provider-closed');
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}).finally(() => {
|
|
131
|
+
// session.finish 是异步入队的:立刻 close 会把这条帧截断,让出几毫秒再关。
|
|
132
|
+
setTimeout(() => { try {
|
|
133
|
+
ws.close();
|
|
134
|
+
}
|
|
135
|
+
catch { /* noop */ } }, 50);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/** 简单的 event_id(协议要求会话内唯一;这里一次请求一个连接,随机即可)。 */
|
|
139
|
+
function ev() {
|
|
140
|
+
return `ev_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
141
|
+
}
|
|
142
|
+
/** 注册 TTS 路由:POST /api/asr-voice/tts。签名与兄弟路由(transcribe/optimize)同构。 */
|
|
143
|
+
export function registerTtsRoute(register, getTtsConfig, ctx) {
|
|
144
|
+
return register({
|
|
145
|
+
kind: 'exact',
|
|
146
|
+
path: '/api/asr-voice/tts',
|
|
147
|
+
handler: async (req, res) => {
|
|
148
|
+
const denied = guardRoute(req);
|
|
149
|
+
if (denied !== null)
|
|
150
|
+
return sendJson(res, denied.status, denied.payload);
|
|
151
|
+
let body;
|
|
152
|
+
try {
|
|
153
|
+
body = (await readJsonBody(req));
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return sendJson(res, 400, { ok: false, reason: 'invalid JSON body' });
|
|
157
|
+
}
|
|
158
|
+
const text = (body.text ?? '').trim();
|
|
159
|
+
if (text === '')
|
|
160
|
+
return sendJson(res, 400, { ok: false, reason: 'empty text' });
|
|
161
|
+
if (text.length > MAX_TEXT_CHARS)
|
|
162
|
+
return sendJson(res, 400, { ok: false, reason: `text too long (${text.length} > ${MAX_TEXT_CHARS})` });
|
|
163
|
+
const cfg = getTtsConfig() ?? { id: 'tts', preset: 'dashscope', name: '', baseUrl: '', apiKey: '', model: '', mode: 'chat' };
|
|
164
|
+
const apiKey = await resolveApiKey(ctx, cfg);
|
|
165
|
+
if (!apiKey) {
|
|
166
|
+
return sendJson(res, 400, { ok: false, reason: 'no API key: set the credential DASHSCOPE_API_KEY in DSH (a same-named LLM key is reused automatically)' });
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
const { pcm } = await synthesize(apiKey, text, body.voice);
|
|
170
|
+
return sendJson(res, 200, { ok: true, audio: Buffer.from(pcm).toString('base64'), sampleRate: 16000 });
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
174
|
+
return sendJson(res, 502, { ok: false, reason });
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=realtime-tts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-tts.js","sourceRoot":"","sources":["../src/realtime-tts.ts"],"names":[],"mappings":"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"}
|
package/lib/settings.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/** dsh-asr-voice — host 半区:settings namespace + schema(设置页配置的权威源)。
|
|
2
|
+
* **API key 不在这里**:云端 ASR 的 key 统一存 DSH credentials 服务,引用名由
|
|
3
|
+
* `src/key-ref.ts` 派生(预置供应商与官方 LLM provider 同名,配过 LLM 就直接复用,
|
|
4
|
+
* 用户一次都不用填);LLM 提示词优化不存 key,它走 DSH 官方通道 ctx.llm。settings
|
|
5
|
+
* 只存有 baseUrl / model / mode 等**无密钥**的供应商元数据,因此浏览器拿到整份
|
|
6
|
+
* 文档也拿不到 key,客户端整段回写也不可能顺手删掉谁的密钥。
|
|
7
|
+
* 两个 `apiKey` 字段是 v0.1/v0.2 的遗留位置,本版本保留只为让 `src/index.ts` 的
|
|
8
|
+
* 一次性迁移读到旧值并搬进 credentials:字段一旦从 schema 消失,schemastery 会把
|
|
9
|
+
* 旧文档里的值直接剥掉,迁移就再也看不见它。它们声明为 `role('secret')`,从此不经
|
|
10
|
+
* `settings.describe` 渡到浏览器(此前是明文过境的,迁移后请自行清理
|
|
11
|
+
* `~/.dsh/settings.yaml` 中的历史残留)。下一版本再删除字段本身。
|
|
12
|
+
* 云端 ASR 支持**多供应商**(v0.2):`asr.cloud.providers` 为供应商列表(每个含
|
|
13
|
+
* 自己的 name/baseUrl/model/mode),`asr.cloud.active` 指定当前使用的供应商 id。
|
|
14
|
+
* 兼容旧单配置:仍保留 preset/baseUrl/model/mode 顶层字段,读取时若无 providers
|
|
15
|
+
* 则回退到旧单配置(向后兼容,写回优先新 shape)。
|
|
16
|
+
*/
|
|
17
|
+
import z from '@deepseek-ai/schemastery';
|
|
18
|
+
/** 插件配置页的 settings namespace:注册后出现在「设置 → 插件 → 配置」分派列表。 */
|
|
19
|
+
export const ASR_VOICE_SETTINGS_NAMESPACE = 'asr-voice';
|
|
20
|
+
/** 单个云端 ASR 供应商配置(密钥不在此处,见文件头)。 */
|
|
21
|
+
export const CloudProviderSchema = z.object({
|
|
22
|
+
/** 供应商唯一 id(新增时由前端生成,如 crypto.randomUUID)。 */
|
|
23
|
+
id: z.string().default(''),
|
|
24
|
+
/** 预置 id(openai | groq | siliconflow | mimo | dashscope | custom)。 */
|
|
25
|
+
preset: z.string().default('openai'),
|
|
26
|
+
/** 显示名;自定义供应商同时是凭据引用名的派生依据(见 src/key-ref.ts)。 */
|
|
27
|
+
name: z.string().default(''),
|
|
28
|
+
/** OpenAI-compatible base URL(预置自动填充,可改)。 */
|
|
29
|
+
baseUrl: z.string().default(''),
|
|
30
|
+
/** 遗留密钥位置:只由 src/index.ts 的一次性迁移读取并搬进 credentials,之后恒为空。 */
|
|
31
|
+
apiKey: z.string().default('').role('secret'),
|
|
32
|
+
/** ASR 模型(预置自动填充,可改;可经「获取模型」动态拉取)。 */
|
|
33
|
+
model: z.string().default(''),
|
|
34
|
+
/** 调用通道:auto(按模型名判定)/ transcriptions(whisper 式)/ chat(MiMo/Qwen-ASR)。 */
|
|
35
|
+
mode: z.string().default('auto'),
|
|
36
|
+
});
|
|
37
|
+
/** 云端 ASR 配置:多供应商列表 + active(含旧单配置兼容字段)。 */
|
|
38
|
+
// 显式注解为 any(有注释的移植性妥协,**刻意保留**):providers 数组的 default 会让
|
|
39
|
+
// 推断类型引用 cosmokit 的 Dict,声明发射时报 TS2883(不可移植到其他 tsconfig);
|
|
40
|
+
// 业务侧用下方手写 AsrVoiceSettings 接口兜底,不受影响。留待 schemastery 依赖升级
|
|
41
|
+
// 后改回精确类型,届时需重跑双半区 tsc + build 确认声明可移植。
|
|
42
|
+
export const CloudSchema = z.object({
|
|
43
|
+
/** 多供应商列表(新 shape)。 */
|
|
44
|
+
providers: z.array(CloudProviderSchema).default([]),
|
|
45
|
+
/** 当前使用的供应商 id(空 = 取第一个)。 */
|
|
46
|
+
active: z.string().default(''),
|
|
47
|
+
/** ── 兼容旧单配置(v0.1 遗留;读取时回退,写回优先新 shape) ── */
|
|
48
|
+
preset: z.string().default('openai'),
|
|
49
|
+
baseUrl: z.string().default(''),
|
|
50
|
+
/** 遗留密钥位置,同 CloudProviderSchema.apiKey。 */
|
|
51
|
+
apiKey: z.string().default('').role('secret'),
|
|
52
|
+
model: z.string().default(''),
|
|
53
|
+
mode: z.string().default('auto'),
|
|
54
|
+
});
|
|
55
|
+
/** LLM 提示词优化目标(DSH 已配置模型的 provider/model;空 = 用当前所选 LLM)。 */
|
|
56
|
+
export const LlmSchema = z.object({
|
|
57
|
+
provider: z.string().default(''),
|
|
58
|
+
model: z.string().default(''),
|
|
59
|
+
});
|
|
60
|
+
/** 插件设置 schema(与 client 的 AsrVoiceConfig 结构一致)。 */
|
|
61
|
+
// 同上 CloudSchema:TS2883 移植性妥协(有注释,刻意保留),业务类型见下方手写接口。
|
|
62
|
+
export const AsrVoiceSettingsSchema = z.object({
|
|
63
|
+
/** ASR 引擎:auto(默认,浏览器 Web Speech 优先、失败自动切云端)/ browser / cloud。 */
|
|
64
|
+
asr: z.object({
|
|
65
|
+
provider: z.string().default('auto'),
|
|
66
|
+
cloud: CloudSchema,
|
|
67
|
+
}),
|
|
68
|
+
/** 提示词优化:llm(默认,用当前所选 LLM 重写)/ heuristic(本地启发式,可选)。 */
|
|
69
|
+
optimize: z.object({
|
|
70
|
+
mode: z.string().default('llm'),
|
|
71
|
+
/** LLM 模式下的入框方式:false(默认)= 停止录音立即填入清洗版文本,优化后台完成后自动替换(不覆盖用户编辑);true = 等优化完成弹预览卡确认后填入。 */
|
|
72
|
+
preview: z.boolean().default(false),
|
|
73
|
+
llm: LlmSchema,
|
|
74
|
+
}),
|
|
75
|
+
/** 识别语言:auto(跟随浏览器/系统)/ zh-CN / en-US / …。 */
|
|
76
|
+
language: z.string().default('auto'),
|
|
77
|
+
/** 交互行为。 */
|
|
78
|
+
behavior: z.object({
|
|
79
|
+
/** 识别优化完成后是否自动发送(默认关,防误发)。 */
|
|
80
|
+
autoSend: z.boolean().default(false),
|
|
81
|
+
/** 静音自动停止(默认关 = 只有手动点击/快捷键结束录音)。 */
|
|
82
|
+
silenceStop: z.boolean().default(false),
|
|
83
|
+
/** 按住说话模式(可选)。 */
|
|
84
|
+
holdToTalk: z.boolean().default(false),
|
|
85
|
+
/** 快捷键(默认 Ctrl+Shift+Space,可改;'' 表示关闭)。 */
|
|
86
|
+
hotkey: z.string().default('Ctrl+Shift+Space'),
|
|
87
|
+
/** 文本输入模式:replace(完整替换草稿,默认)/ append(在已有文字后插入)。 */
|
|
88
|
+
textMode: z.string().default('replace'),
|
|
89
|
+
/** 生成内容自动加入剪贴板(默认开)。 */
|
|
90
|
+
copyToClipboard: z.boolean().default(true),
|
|
91
|
+
/** 单次录音最长时长(毫秒),到点自动停止并送去识别。 */
|
|
92
|
+
maxRecordMs: z.natural().min(5_000).max(600_000).default(120_000),
|
|
93
|
+
/** 静音判定阈值(RMS,0~1):低于它算无声,供静音自动停止与静音守卫使用。 */
|
|
94
|
+
silenceRms: z.percent().default(0.02),
|
|
95
|
+
/** 静音持续多久即自动停止(毫秒,仅在 silenceStop 开启时生效)。 */
|
|
96
|
+
silenceMs: z.natural().min(200).max(60_000).default(2_500),
|
|
97
|
+
}),
|
|
98
|
+
/** 实时语音对话:边说边出字 → 停顿即发起 agent 回合 → 把回复读出来。 与整段模式共用同一条 setDraft/submit 上通路,只是不再需要手动关麦。 */
|
|
99
|
+
realtime: z.object({
|
|
100
|
+
/** 总开关(默认开):关掉时实时按钮不注册,一切行为回到整段模式。 */
|
|
101
|
+
enabled: z.boolean().default(true),
|
|
102
|
+
/** 实时引擎:browser(Web Speech 连续会话,逐字出字、零配额)/ segmented
|
|
103
|
+
* (本地能量 VAD 按句切段,走已配置的整段转写通道;每句一次上游调用)/
|
|
104
|
+
* cloud(16k PCM 上行 host 实时通道,服务端 VAD 判回合——I3 假 provider /
|
|
105
|
+
* I5 真云端 provider)。
|
|
106
|
+
*/
|
|
107
|
+
engine: z.string().default('browser'),
|
|
108
|
+
/** 云端实时 provider(仅 engine=cloud 生效):'builtin' = 内置模拟(I3/I4 开发态, host 用假 provider)/ 预置 id(见 REALTIME_PRESETS,I5 真云端)。 */
|
|
109
|
+
provider: z.string().default('builtin'),
|
|
110
|
+
/** 回复播报:browser(speechSynthesis,零配置)/ cloud(云端 TTS)/ off(只出字不读)。 */
|
|
111
|
+
tts: z.string().default('browser'),
|
|
112
|
+
/** 云端 TTS 音色(仅 tts=cloud 生效;qwen3-tts-flash-realtime 系统音色名)。 */
|
|
113
|
+
ttsVoice: z.string().default('Cherry'),
|
|
114
|
+
/** 进出实时模式的快捷键(与录音键 Ctrl+Shift+Space 错开,避免撞车)。 */
|
|
115
|
+
hotkey: z.string().default('Ctrl+Shift+Alt+Space'),
|
|
116
|
+
/** 语音插话(默认关):播报期间恢复收音,人声持续超出回声门才打断。 */
|
|
117
|
+
bargeIn: z.boolean().default(false),
|
|
118
|
+
/** 回合边界判定(本地兜底:实时引擎不给回合终点时由文字稳定性决定)。 */
|
|
119
|
+
turn: z.object({
|
|
120
|
+
/** 转写文字静默多久算「说完了」(毫秒)。 */
|
|
121
|
+
settleMs: z.natural().min(200).max(10_000).default(900),
|
|
122
|
+
/** 静音窗口之后再宽限这么久才提交(毫秒):接住最后一个词的迟到结果;0 = 不等。 */
|
|
123
|
+
tailMs: z.natural().min(0).max(5_000).default(300),
|
|
124
|
+
}),
|
|
125
|
+
/** 声学切段(仅 engine=segmented 生效):只看 RMS,阈值是设备噪声底的函数。 */
|
|
126
|
+
vad: z.object({
|
|
127
|
+
/** 采集帧长(毫秒):越小越省延迟,越大越省调度开销。 */
|
|
128
|
+
frameMs: z.natural().min(10).max(500).default(40),
|
|
129
|
+
/** RMS 高于此值算有声。偏低→杂音成句;偏高→轻声句尾被切掉。 */
|
|
130
|
+
rms: z.percent().default(0.02),
|
|
131
|
+
/** 自动校准:实际判据 = max(rms, 静音期噪声底×3),换设备免重校。 */
|
|
132
|
+
rmsAuto: z.boolean().default(true),
|
|
133
|
+
/** 连续静音多久切一段(毫秒):也是每句上屏的固定延迟。 */
|
|
134
|
+
silenceMs: z.natural().min(200).max(5_000).default(700),
|
|
135
|
+
/** 段前保留(毫秒):不留就会切掉第一个音节。 */
|
|
136
|
+
prerollMs: z.natural().min(0).max(1_000).default(200),
|
|
137
|
+
/** 实际语音短于此不成为一段:咳嗽、键盘、门响不该花一次上游配额。 */
|
|
138
|
+
minSpeechMs: z.natural().min(100).max(3_000).default(250),
|
|
139
|
+
/** 单段语音长度上限(毫秒):说个不停也要定期出字,同时封顶上传体大小。 */
|
|
140
|
+
maxSegmentMs: z.natural().min(1_000).max(30_000).default(8_000),
|
|
141
|
+
/** 待转写队列上限(不含在途那段):转写慢过说话时丢最旧。 */
|
|
142
|
+
maxPending: z.natural().min(1).max(20).default(3),
|
|
143
|
+
}),
|
|
144
|
+
/** 单次对话上限(毫秒):麦克风不能无人值守常开,到点自动结束会话。 */
|
|
145
|
+
maxSessionMs: z.natural().min(30_000).max(3_600_000).default(600_000),
|
|
146
|
+
/** 回复朗读。 */
|
|
147
|
+
speech: z.object({
|
|
148
|
+
/** 首句最少字数:短句先合并再读,避免逐词起句。 */
|
|
149
|
+
firstSentenceMinChars: z.natural().min(1).max(200).default(12),
|
|
150
|
+
/** 朗读看门狗(毫秒):speechSynthesis 的 onend 不可信,超时按播完处理。 */
|
|
151
|
+
utteranceWatchdogMs: z.natural().min(1_000).max(300_000).default(60_000),
|
|
152
|
+
}),
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|
package/lib/stats.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { guardRoute, sendJson } from "./http.js";
|
|
2
|
+
/** 创建用量计数器(进程内)。 */
|
|
3
|
+
export function createAsrStats() {
|
|
4
|
+
const s = { count: 0, chars: 0, lastAt: null, lastProvider: '' };
|
|
5
|
+
return {
|
|
6
|
+
record(text, providerId) {
|
|
7
|
+
s.count += 1;
|
|
8
|
+
s.chars += text.length;
|
|
9
|
+
s.lastAt = Date.now();
|
|
10
|
+
s.lastProvider = providerId;
|
|
11
|
+
},
|
|
12
|
+
snapshot() {
|
|
13
|
+
return { ...s };
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** 注册 /api/asr-voice/stats 路由(GET):返回用量快照。 */
|
|
18
|
+
export function registerStatsRoute(register, getStats) {
|
|
19
|
+
return register({
|
|
20
|
+
kind: 'exact',
|
|
21
|
+
path: '/api/asr-voice/stats',
|
|
22
|
+
handler: async (req, res) => {
|
|
23
|
+
const denied = guardRoute(req, ['GET']);
|
|
24
|
+
if (denied !== null)
|
|
25
|
+
return sendJson(res, denied.status, denied.payload);
|
|
26
|
+
return sendJson(res, 200, { ok: true, stats: getStats() });
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=stats.js.map
|
package/lib/stats.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAcjD,oBAAoB;AACpB,MAAM,UAAU,cAAc;IAC5B,MAAM,CAAC,GAAa,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAA;IAC1E,OAAO;QACL,MAAM,CAAC,IAAY,EAAE,UAAkB;YACrC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;YACZ,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAA;YACtB,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACrB,CAAC,CAAC,YAAY,GAAG,UAAU,CAAA;QAC7B,CAAC;QACD,QAAQ;YACN,OAAO,EAAE,GAAG,CAAC,EAAE,CAAA;QACjB,CAAC;KACF,CAAA;AACH,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,kBAAkB,CAChC,QAA4I,EAC5I,QAAwB;IAExB,OAAO,QAAQ,CAAC;QACd,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAE,EAAE;YAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACxC,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YACzE,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|