@lee-zg/melange 1.2.3 → 1.2.5
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 +257 -256
- package/dist/{chunk-YZVCK6VZ.cjs → chunk-AAWWAPSG.cjs} +1425 -2
- package/dist/{chunk-3RM45M64.js → chunk-R3BPDZ3R.js} +1388 -3
- package/dist/container-B8n-ok8M.d.cts +201 -0
- package/dist/container-n8Q2Xa_y.d.ts +201 -0
- package/dist/core/index.d.cts +3 -200
- package/dist/core/index.d.ts +3 -200
- package/dist/generator-CEj5qxFh.d.cts +1752 -0
- package/dist/generator-D7ofMxfc.d.ts +1752 -0
- package/dist/index.cjs +138 -34
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -2
- package/dist/plugins/index.cjs +162 -9
- package/dist/plugins/index.d.cts +108 -755
- package/dist/plugins/index.d.ts +108 -755
- package/dist/plugins/index.js +2 -1
- package/package.json +143 -138
|
@@ -0,0 +1,1752 @@
|
|
|
1
|
+
import { C as Container } from './container-B8n-ok8M.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview 语音模块类型定义
|
|
5
|
+
* @module melange/plugins/speech/types
|
|
6
|
+
* @description 语音合成和语音识别的类型定义
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* 语音服务提供商类型
|
|
10
|
+
*/
|
|
11
|
+
type SpeechProviderType = 'browser' | 'azure' | 'google' | 'aws' | 'custom';
|
|
12
|
+
/**
|
|
13
|
+
* 语音服务状态
|
|
14
|
+
*/
|
|
15
|
+
type SpeechServiceStatus = 'idle' | 'loading' | 'ready' | 'error';
|
|
16
|
+
/**
|
|
17
|
+
* 语音服务错误
|
|
18
|
+
*/
|
|
19
|
+
interface SpeechError {
|
|
20
|
+
/** 错误代码 */
|
|
21
|
+
code: string;
|
|
22
|
+
/** 错误信息 */
|
|
23
|
+
message: string;
|
|
24
|
+
/** 原始错误对象 */
|
|
25
|
+
originalError?: Error;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 语音服务基础配置
|
|
29
|
+
*/
|
|
30
|
+
interface BaseSpeechConfig {
|
|
31
|
+
/** 语言代码 (如 'zh-CN', 'en-US') */
|
|
32
|
+
lang?: string;
|
|
33
|
+
/** 首选提供商 */
|
|
34
|
+
preferredProvider?: SpeechProviderType;
|
|
35
|
+
/** 是否自动降级 */
|
|
36
|
+
autoFallback?: boolean;
|
|
37
|
+
/** 降级提供商列表 */
|
|
38
|
+
fallbackProviders?: SpeechProviderType[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 语音信息
|
|
42
|
+
*/
|
|
43
|
+
interface VoiceInfo {
|
|
44
|
+
/** 语音唯一标识 */
|
|
45
|
+
id: string;
|
|
46
|
+
/** 语音名称 */
|
|
47
|
+
name: string;
|
|
48
|
+
/** 语言代码 */
|
|
49
|
+
lang: string;
|
|
50
|
+
/** 是否为本地语音 */
|
|
51
|
+
localService: boolean;
|
|
52
|
+
/** 是否为默认语音 */
|
|
53
|
+
default: boolean;
|
|
54
|
+
/** 提供商类型 */
|
|
55
|
+
provider: SpeechProviderType;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 语音合成配置
|
|
59
|
+
*/
|
|
60
|
+
interface SynthesisConfig extends BaseSpeechConfig {
|
|
61
|
+
/** 语音对象或语音名称 */
|
|
62
|
+
voice?: VoiceInfo | string;
|
|
63
|
+
/** 音量 (0-1) */
|
|
64
|
+
volume?: number;
|
|
65
|
+
/** 语速 (0.1-10) */
|
|
66
|
+
rate?: number;
|
|
67
|
+
/** 音调 (0-2) */
|
|
68
|
+
pitch?: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 语音合成事件类型
|
|
72
|
+
*/
|
|
73
|
+
type SynthesisEventType = 'start' | 'end' | 'pause' | 'resume' | 'boundary' | 'mark' | 'error';
|
|
74
|
+
/**
|
|
75
|
+
* 语音合成事件数据
|
|
76
|
+
*/
|
|
77
|
+
interface SynthesisEvent {
|
|
78
|
+
/** 事件类型 */
|
|
79
|
+
type: SynthesisEventType;
|
|
80
|
+
/** 当前字符索引 */
|
|
81
|
+
charIndex?: number;
|
|
82
|
+
/** 当前字符长度 */
|
|
83
|
+
charLength?: number;
|
|
84
|
+
/** 经过的时间(毫秒) */
|
|
85
|
+
elapsedTime?: number;
|
|
86
|
+
/** 边界名称 */
|
|
87
|
+
name?: string;
|
|
88
|
+
/** 错误信息 */
|
|
89
|
+
error?: SpeechError;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 语音合成事件处理器
|
|
93
|
+
*/
|
|
94
|
+
type SynthesisEventHandler = (event: SynthesisEvent) => void;
|
|
95
|
+
/**
|
|
96
|
+
* 语音合成提供商接口
|
|
97
|
+
*/
|
|
98
|
+
interface SynthesisProvider {
|
|
99
|
+
/** 提供商类型 */
|
|
100
|
+
readonly type: SpeechProviderType;
|
|
101
|
+
/** 检查是否可用 */
|
|
102
|
+
isAvailable(): boolean;
|
|
103
|
+
/** 获取可用语音列表 */
|
|
104
|
+
getVoices(): Promise<VoiceInfo[]>;
|
|
105
|
+
/** 朗读文本 */
|
|
106
|
+
speak(text: string, config?: SynthesisConfig): Promise<void>;
|
|
107
|
+
/** 暂停 */
|
|
108
|
+
pause(): void;
|
|
109
|
+
/** 继续 */
|
|
110
|
+
resume(): void;
|
|
111
|
+
/** 取消 */
|
|
112
|
+
cancel(): void;
|
|
113
|
+
/** 是否正在朗读 */
|
|
114
|
+
isSpeaking(): boolean;
|
|
115
|
+
/** 是否已暂停 */
|
|
116
|
+
isPaused(): boolean;
|
|
117
|
+
/** 添加事件监听 */
|
|
118
|
+
on(event: SynthesisEventType, handler: SynthesisEventHandler): void;
|
|
119
|
+
/** 移除事件监听 */
|
|
120
|
+
off(event: SynthesisEventType, handler: SynthesisEventHandler): void;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 语音合成器接口
|
|
124
|
+
*/
|
|
125
|
+
interface SpeechSynthesizer {
|
|
126
|
+
/** 当前使用的提供商 */
|
|
127
|
+
readonly currentProvider: SpeechProviderType;
|
|
128
|
+
/** 服务状态 */
|
|
129
|
+
readonly status: SpeechServiceStatus;
|
|
130
|
+
/** 初始化 */
|
|
131
|
+
initialize(config?: SynthesisConfig): Promise<void>;
|
|
132
|
+
/** 获取可用语音列表 */
|
|
133
|
+
getVoices(): Promise<VoiceInfo[]>;
|
|
134
|
+
/** 朗读文本 */
|
|
135
|
+
speak(text: string, config?: SynthesisConfig): Promise<void>;
|
|
136
|
+
/** 暂停 */
|
|
137
|
+
pause(): void;
|
|
138
|
+
/** 继续 */
|
|
139
|
+
resume(): void;
|
|
140
|
+
/** 取消 */
|
|
141
|
+
cancel(): void;
|
|
142
|
+
/** 是否正在朗读 */
|
|
143
|
+
isSpeaking(): boolean;
|
|
144
|
+
/** 是否已暂停 */
|
|
145
|
+
isPaused(): boolean;
|
|
146
|
+
/** 添加事件监听 */
|
|
147
|
+
on(event: SynthesisEventType, handler: SynthesisEventHandler): void;
|
|
148
|
+
/** 移除事件监听 */
|
|
149
|
+
off(event: SynthesisEventType, handler: SynthesisEventHandler): void;
|
|
150
|
+
/** 销毁实例 */
|
|
151
|
+
dispose(): void;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 识别结果项
|
|
155
|
+
*/
|
|
156
|
+
interface RecognitionResultItem {
|
|
157
|
+
/** 识别的文本 */
|
|
158
|
+
transcript: string;
|
|
159
|
+
/** 置信度 (0-1) */
|
|
160
|
+
confidence: number;
|
|
161
|
+
/** 是否为最终结果 */
|
|
162
|
+
isFinal: boolean;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 识别结果
|
|
166
|
+
*/
|
|
167
|
+
interface RecognitionResult {
|
|
168
|
+
/** 结果列表 */
|
|
169
|
+
results: RecognitionResultItem[];
|
|
170
|
+
/** 最佳结果 */
|
|
171
|
+
bestTranscript: string;
|
|
172
|
+
/** 最佳置信度 */
|
|
173
|
+
bestConfidence: number;
|
|
174
|
+
/** 是否为最终结果 */
|
|
175
|
+
isFinal: boolean;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* 语音识别配置
|
|
179
|
+
*/
|
|
180
|
+
interface RecognitionConfig extends BaseSpeechConfig {
|
|
181
|
+
/** 是否连续识别 */
|
|
182
|
+
continuous?: boolean;
|
|
183
|
+
/** 是否返回中间结果 */
|
|
184
|
+
interimResults?: boolean;
|
|
185
|
+
/** 最大备选结果数 */
|
|
186
|
+
maxAlternatives?: number;
|
|
187
|
+
/** 语法列表 (仅部分浏览器支持) */
|
|
188
|
+
grammars?: string[];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* 语音识别事件类型
|
|
192
|
+
*/
|
|
193
|
+
type RecognitionEventType = 'start' | 'end' | 'result' | 'error' | 'soundstart' | 'soundend' | 'speechstart' | 'speechend' | 'audiostart' | 'audioend' | 'nomatch';
|
|
194
|
+
/**
|
|
195
|
+
* 语音识别事件数据
|
|
196
|
+
*/
|
|
197
|
+
interface RecognitionEvent {
|
|
198
|
+
/** 事件类型 */
|
|
199
|
+
type: RecognitionEventType;
|
|
200
|
+
/** 识别结果 (仅 result 事件) */
|
|
201
|
+
result?: RecognitionResult;
|
|
202
|
+
/** 错误信息 (仅 error 事件) */
|
|
203
|
+
error?: SpeechError;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* 语音识别事件处理器
|
|
207
|
+
*/
|
|
208
|
+
type RecognitionEventHandler = (event: RecognitionEvent) => void;
|
|
209
|
+
/**
|
|
210
|
+
* 语音识别提供商接口
|
|
211
|
+
*/
|
|
212
|
+
interface RecognitionProvider {
|
|
213
|
+
/** 提供商类型 */
|
|
214
|
+
readonly type: SpeechProviderType;
|
|
215
|
+
/** 检查是否可用 */
|
|
216
|
+
isAvailable(): boolean;
|
|
217
|
+
/** 开始识别 */
|
|
218
|
+
start(config?: RecognitionConfig): Promise<void>;
|
|
219
|
+
/** 停止识别 */
|
|
220
|
+
stop(): void;
|
|
221
|
+
/** 中止识别 */
|
|
222
|
+
abort(): void;
|
|
223
|
+
/** 是否正在识别 */
|
|
224
|
+
isListening(): boolean;
|
|
225
|
+
/** 添加事件监听 */
|
|
226
|
+
on(event: RecognitionEventType, handler: RecognitionEventHandler): void;
|
|
227
|
+
/** 移除事件监听 */
|
|
228
|
+
off(event: RecognitionEventType, handler: RecognitionEventHandler): void;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 语音识别器接口
|
|
232
|
+
*/
|
|
233
|
+
interface SpeechRecognizer {
|
|
234
|
+
/** 当前使用的提供商 */
|
|
235
|
+
readonly currentProvider: SpeechProviderType;
|
|
236
|
+
/** 服务状态 */
|
|
237
|
+
readonly status: SpeechServiceStatus;
|
|
238
|
+
/** 初始化 */
|
|
239
|
+
initialize(config?: RecognitionConfig): Promise<void>;
|
|
240
|
+
/** 开始识别 */
|
|
241
|
+
start(config?: RecognitionConfig): Promise<void>;
|
|
242
|
+
/** 停止识别 */
|
|
243
|
+
stop(): void;
|
|
244
|
+
/** 中止识别 */
|
|
245
|
+
abort(): void;
|
|
246
|
+
/** 是否正在识别 */
|
|
247
|
+
isListening(): boolean;
|
|
248
|
+
/** 添加事件监听 */
|
|
249
|
+
on(event: RecognitionEventType, handler: RecognitionEventHandler): void;
|
|
250
|
+
/** 移除事件监听 */
|
|
251
|
+
off(event: RecognitionEventType, handler: RecognitionEventHandler): void;
|
|
252
|
+
/** 销毁实例 */
|
|
253
|
+
dispose(): void;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Azure 语音服务配置
|
|
257
|
+
*/
|
|
258
|
+
interface AzureSpeechConfig {
|
|
259
|
+
/** 订阅密钥 */
|
|
260
|
+
subscriptionKey: string;
|
|
261
|
+
/** 服务区域 */
|
|
262
|
+
region: string;
|
|
263
|
+
/** 自定义端点 */
|
|
264
|
+
endpoint?: string;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Google Cloud Speech 配置
|
|
268
|
+
*/
|
|
269
|
+
interface GoogleSpeechConfig {
|
|
270
|
+
/** API 密钥 */
|
|
271
|
+
apiKey: string;
|
|
272
|
+
/** 项目 ID */
|
|
273
|
+
projectId?: string;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* AWS Polly/Transcribe 配置
|
|
277
|
+
*/
|
|
278
|
+
interface AWSSpeechConfig {
|
|
279
|
+
/** 访问密钥 ID */
|
|
280
|
+
accessKeyId: string;
|
|
281
|
+
/** 秘密访问密钥 */
|
|
282
|
+
secretAccessKey: string;
|
|
283
|
+
/** 区域 */
|
|
284
|
+
region: string;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* 自定义提供商配置
|
|
288
|
+
*/
|
|
289
|
+
interface CustomProviderConfig {
|
|
290
|
+
/** 合成 API 端点 */
|
|
291
|
+
synthesisEndpoint?: string;
|
|
292
|
+
/** 识别 API 端点 */
|
|
293
|
+
recognitionEndpoint?: string;
|
|
294
|
+
/** 自定义请求头 */
|
|
295
|
+
headers?: Record<string, string>;
|
|
296
|
+
/** 认证令牌 */
|
|
297
|
+
authToken?: string;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* 提供商配置联合类型
|
|
301
|
+
*/
|
|
302
|
+
type ProviderConfig = AzureSpeechConfig | GoogleSpeechConfig | AWSSpeechConfig | CustomProviderConfig;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* @fileoverview 语音合成 (TTS) 实现 - 商业级版本 v2.0
|
|
306
|
+
* @module melange/plugins/speech/synthesis
|
|
307
|
+
* @description 生产级 Web 语音合成插件
|
|
308
|
+
*
|
|
309
|
+
* 架构:
|
|
310
|
+
* [UI层] -> [SpeechSynthesizerImpl] -> [NativeStrategy / CloudStrategy]
|
|
311
|
+
* |
|
|
312
|
+
* +-> [音频核心]: AudioContext, 流式播放
|
|
313
|
+
* +-> [适配器]: AzureAdapter, GoogleAdapter, TencentAdapter...
|
|
314
|
+
*
|
|
315
|
+
* 功能特性:
|
|
316
|
+
* 1. 多模式: 支持原生 Web Speech API & 云端 TTS 服务
|
|
317
|
+
* 2. 状态机: IDLE -> LOADING -> SPEAKING -> PAUSED
|
|
318
|
+
* 3. 插件化: 内置 Azure/Google/AWS/讯飞/腾讯/百度/阿里 适配器
|
|
319
|
+
* 4. 核心: AudioContext 流式播放 + 音频队列管理
|
|
320
|
+
* 5. 兼容性: 多浏览器支持 + 自动降级处理
|
|
321
|
+
*/
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* 合成器状态枚举
|
|
325
|
+
*/
|
|
326
|
+
declare enum SynthesisStatus {
|
|
327
|
+
/** 空闲状态 */
|
|
328
|
+
IDLE = "IDLE",
|
|
329
|
+
/** 加载中(获取语音/准备中) */
|
|
330
|
+
LOADING = "LOADING",
|
|
331
|
+
/** 正在播放 */
|
|
332
|
+
SPEAKING = "SPEAKING",
|
|
333
|
+
/** 已暂停 */
|
|
334
|
+
PAUSED = "PAUSED"
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* 合成引擎模式
|
|
338
|
+
*/
|
|
339
|
+
type SynthesisEngineMode = 'native' | 'cloud' | 'auto';
|
|
340
|
+
/**
|
|
341
|
+
* 云端 TTS 音频格式
|
|
342
|
+
*/
|
|
343
|
+
type CloudAudioFormat = 'mp3' | 'wav' | 'ogg' | 'pcm';
|
|
344
|
+
/**
|
|
345
|
+
* 云端合成结果接口
|
|
346
|
+
*/
|
|
347
|
+
interface ISynthesisResult {
|
|
348
|
+
/** 音频数据 */
|
|
349
|
+
audioData: ArrayBuffer;
|
|
350
|
+
/** 音频格式 */
|
|
351
|
+
format: CloudAudioFormat;
|
|
352
|
+
/** 音频时长 (ms) */
|
|
353
|
+
duration?: number;
|
|
354
|
+
/** 原始响应数据 */
|
|
355
|
+
original?: unknown;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* 合成错误接口
|
|
359
|
+
*/
|
|
360
|
+
interface ISynthesisError {
|
|
361
|
+
/** 错误代码 */
|
|
362
|
+
code: 'NETWORK' | 'NOT_SUPPORTED' | 'INVALID_TEXT' | 'ADAPTER_ERROR' | 'PLAYBACK_ERROR' | 'UNKNOWN';
|
|
363
|
+
/** 错误信息 */
|
|
364
|
+
message: string;
|
|
365
|
+
/** 原始错误 */
|
|
366
|
+
originalError?: unknown;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* 云端语音信息
|
|
370
|
+
*/
|
|
371
|
+
interface ICloudVoice {
|
|
372
|
+
/** 语音 ID */
|
|
373
|
+
id: string;
|
|
374
|
+
/** 语音名称 */
|
|
375
|
+
name: string;
|
|
376
|
+
/** 语言代码 */
|
|
377
|
+
lang: string;
|
|
378
|
+
/** 性别 */
|
|
379
|
+
gender?: 'male' | 'female' | 'neutral';
|
|
380
|
+
/** 提供商名称 */
|
|
381
|
+
provider: string;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* 高级合成配置
|
|
385
|
+
*/
|
|
386
|
+
interface IAdvancedSynthesisConfig extends SynthesisConfig {
|
|
387
|
+
/** 合成引擎模式 */
|
|
388
|
+
mode?: SynthesisEngineMode;
|
|
389
|
+
/** 云端适配器 */
|
|
390
|
+
cloudAdapter?: ICloudSynthesisAdapter;
|
|
391
|
+
/** 音频格式偏好 */
|
|
392
|
+
audioFormat?: CloudAudioFormat;
|
|
393
|
+
/** 是否启用 SSML */
|
|
394
|
+
enableSSML?: boolean;
|
|
395
|
+
/** 是否预加载音频 */
|
|
396
|
+
preload?: boolean;
|
|
397
|
+
/** 音频缓存大小 */
|
|
398
|
+
cacheSize?: number;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* 云端合成适配器接口
|
|
402
|
+
* 提供统一的第三方语音合成服务集成接口
|
|
403
|
+
*/
|
|
404
|
+
interface ICloudSynthesisAdapter {
|
|
405
|
+
/** 适配器名称 */
|
|
406
|
+
readonly name: string;
|
|
407
|
+
/**
|
|
408
|
+
* 合成语音
|
|
409
|
+
* @param text 要合成的文本
|
|
410
|
+
* @param config 合成配置
|
|
411
|
+
* @returns 合成结果(音频数据)
|
|
412
|
+
*/
|
|
413
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
414
|
+
/**
|
|
415
|
+
* 获取可用语音列表
|
|
416
|
+
* @returns 语音列表
|
|
417
|
+
*/
|
|
418
|
+
getVoices?(): Promise<ICloudVoice[]>;
|
|
419
|
+
/**
|
|
420
|
+
* 检查适配器是否可用
|
|
421
|
+
* @returns 是否可用
|
|
422
|
+
*/
|
|
423
|
+
isAvailable?(): boolean;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* 音频播放工具集
|
|
427
|
+
*/
|
|
428
|
+
declare const SynthesisAudioUtils: {
|
|
429
|
+
/**
|
|
430
|
+
* 创建 AudioContext
|
|
431
|
+
*/
|
|
432
|
+
createAudioContext(): AudioContext;
|
|
433
|
+
/**
|
|
434
|
+
* ArrayBuffer 转 Base64
|
|
435
|
+
*/
|
|
436
|
+
arrayBufferToBase64(buffer: ArrayBuffer): string;
|
|
437
|
+
/**
|
|
438
|
+
* Base64 转 ArrayBuffer
|
|
439
|
+
*/
|
|
440
|
+
base64ToArrayBuffer(base64: string): ArrayBuffer;
|
|
441
|
+
/**
|
|
442
|
+
* 计算音频时长(粗略估算)
|
|
443
|
+
*/
|
|
444
|
+
estimateDuration(byteLength: number, format: CloudAudioFormat): number;
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* 通用语音合成适配器。
|
|
448
|
+
*
|
|
449
|
+
* @description
|
|
450
|
+
* 这是生产推荐的 BFF 模式适配器。浏览器只向自有后端提交文本、语言、
|
|
451
|
+
* 语速、音色和输出格式,云厂商密钥、签名、限流、审计和错误映射必须由
|
|
452
|
+
* 后端完成。
|
|
453
|
+
*
|
|
454
|
+
* @remarks
|
|
455
|
+
* 默认协议:
|
|
456
|
+
* - `POST {baseUrl}/synthesize` 返回音频二进制;
|
|
457
|
+
* - `GET {baseUrl}/voices` 返回 `{ voices: ICloudVoice[] }`;
|
|
458
|
+
* - 错误响应建议映射为 `{ code, message, retryable, requestId? }`。
|
|
459
|
+
*/
|
|
460
|
+
declare class GenericSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
461
|
+
private baseUrl;
|
|
462
|
+
readonly name = "Generic/BFF";
|
|
463
|
+
constructor(baseUrl: string);
|
|
464
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
465
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Azure 语音服务直连适配器。
|
|
469
|
+
*
|
|
470
|
+
* @deprecated demo-only。该适配器会在浏览器请求中使用 subscription key,
|
|
471
|
+
* 仅适合本地验证 API 形态。生产环境请使用 `GenericSynthesisAdapter`
|
|
472
|
+
* 连接自有 BFF,由后端持有和使用 Azure 凭证。
|
|
473
|
+
*/
|
|
474
|
+
declare class AzureSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
475
|
+
private subscriptionKey;
|
|
476
|
+
private region;
|
|
477
|
+
private defaultVoice;
|
|
478
|
+
readonly name = "Azure";
|
|
479
|
+
constructor(subscriptionKey: string, region: string, defaultVoice?: string);
|
|
480
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
481
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
482
|
+
private escapeXml;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Google Cloud TTS 直连适配器。
|
|
486
|
+
*
|
|
487
|
+
* @deprecated demo-only。该适配器会将 API key 放入浏览器请求 URL,
|
|
488
|
+
* 仅适合本地验证。生产环境请通过 BFF 代理调用 Google Cloud TTS。
|
|
489
|
+
*/
|
|
490
|
+
declare class GoogleSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
491
|
+
private apiKey;
|
|
492
|
+
private defaultVoice;
|
|
493
|
+
readonly name = "Google";
|
|
494
|
+
constructor(apiKey: string, defaultVoice?: string);
|
|
495
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
496
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* AWS Polly 示例适配器。
|
|
500
|
+
*
|
|
501
|
+
* @deprecated demo-only。构造函数保留 AWS 长期凭证参数以兼容旧 API,
|
|
502
|
+
* 但生产环境不得在前端创建或保存这些凭证,应由 BFF 完成签名和调用。
|
|
503
|
+
*/
|
|
504
|
+
declare class AWSSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
505
|
+
private accessKeyId;
|
|
506
|
+
private secretAccessKey;
|
|
507
|
+
private region;
|
|
508
|
+
private defaultVoice;
|
|
509
|
+
readonly name = "AWS";
|
|
510
|
+
constructor(accessKeyId: string, secretAccessKey: string, region: string, defaultVoice?: string);
|
|
511
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
512
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* 讯飞云示例适配器。
|
|
516
|
+
*
|
|
517
|
+
* @deprecated demo-only。仅用于展示参数映射和 BFF 请求形态。生产环境应在
|
|
518
|
+
* 后端完成讯飞 WebAPI 鉴权签名,不应在浏览器保存 apiKey/apiSecret。
|
|
519
|
+
*/
|
|
520
|
+
declare class XunfeiSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
521
|
+
private appId;
|
|
522
|
+
private defaultVoice;
|
|
523
|
+
readonly name = "Xunfei";
|
|
524
|
+
constructor(appId: string, _apiKey?: string, _apiSecret?: string, defaultVoice?: string);
|
|
525
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
526
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* 腾讯云示例适配器。
|
|
530
|
+
*
|
|
531
|
+
* @deprecated demo-only。构造函数保留 secretId/secretKey 以兼容旧 API,
|
|
532
|
+
* 但生产环境必须在 BFF 完成 TC3-HMAC-SHA256 签名。
|
|
533
|
+
*/
|
|
534
|
+
declare class TencentSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
535
|
+
private secretId;
|
|
536
|
+
private secretKey;
|
|
537
|
+
private defaultVoice;
|
|
538
|
+
readonly name = "Tencent";
|
|
539
|
+
constructor(secretId: string, secretKey: string, defaultVoice?: string);
|
|
540
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
541
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* 百度云示例适配器。
|
|
545
|
+
*
|
|
546
|
+
* @deprecated experimental。access token 不应由浏览器长期持有。生产环境请由
|
|
547
|
+
* BFF 管理 token 生命周期、限流和错误映射。
|
|
548
|
+
*/
|
|
549
|
+
declare class BaiduSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
550
|
+
private accessToken;
|
|
551
|
+
private defaultVoice;
|
|
552
|
+
readonly name = "Baidu";
|
|
553
|
+
constructor(accessToken: string, defaultVoice?: string);
|
|
554
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
555
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* 阿里云示例适配器。
|
|
559
|
+
*
|
|
560
|
+
* @deprecated demo-only。构造函数保留 accessKeySecret 以兼容旧 API,
|
|
561
|
+
* 生产环境请通过 BFF 获取临时凭证或由后端直接调用阿里云服务。
|
|
562
|
+
*/
|
|
563
|
+
declare class AlibabaSynthesisAdapter implements ICloudSynthesisAdapter {
|
|
564
|
+
private accessKeyId;
|
|
565
|
+
private appKey;
|
|
566
|
+
private defaultVoice;
|
|
567
|
+
readonly name = "Alibaba";
|
|
568
|
+
constructor(accessKeyId: string, _accessKeySecret: string, appKey: string, defaultVoice?: string);
|
|
569
|
+
synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;
|
|
570
|
+
getVoices(): Promise<ICloudVoice[]>;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* 语音合成器实现
|
|
574
|
+
* 统一封装原生合成和云端合成
|
|
575
|
+
*/
|
|
576
|
+
declare class SpeechSynthesizerImpl implements SpeechSynthesizer {
|
|
577
|
+
private strategy;
|
|
578
|
+
private config;
|
|
579
|
+
private _currentProvider;
|
|
580
|
+
private _status;
|
|
581
|
+
private eventHandlers;
|
|
582
|
+
private customProviders;
|
|
583
|
+
get currentProvider(): SpeechProviderType;
|
|
584
|
+
get status(): SpeechServiceStatus;
|
|
585
|
+
/**
|
|
586
|
+
* 获取当前合成状态
|
|
587
|
+
*/
|
|
588
|
+
get synthesisStatus(): SynthesisStatus;
|
|
589
|
+
/**
|
|
590
|
+
* 初始化语音合成器
|
|
591
|
+
*/
|
|
592
|
+
initialize(config?: SynthesisConfig): Promise<void>;
|
|
593
|
+
/**
|
|
594
|
+
* 初始化合成策略
|
|
595
|
+
*/
|
|
596
|
+
private initializeStrategy;
|
|
597
|
+
/**
|
|
598
|
+
* 转发策略事件
|
|
599
|
+
*/
|
|
600
|
+
private forwardStrategyEvents;
|
|
601
|
+
/**
|
|
602
|
+
* 获取可用语音列表
|
|
603
|
+
*/
|
|
604
|
+
getVoices(): Promise<VoiceInfo[]>;
|
|
605
|
+
/**
|
|
606
|
+
* 朗读文本
|
|
607
|
+
*/
|
|
608
|
+
speak(text: string, config?: SynthesisConfig): Promise<void>;
|
|
609
|
+
/**
|
|
610
|
+
* 暂停朗读
|
|
611
|
+
*/
|
|
612
|
+
pause(): void;
|
|
613
|
+
/**
|
|
614
|
+
* 继续朗读
|
|
615
|
+
*/
|
|
616
|
+
resume(): void;
|
|
617
|
+
/**
|
|
618
|
+
* 取消朗读
|
|
619
|
+
*/
|
|
620
|
+
cancel(): void;
|
|
621
|
+
/**
|
|
622
|
+
* 是否正在朗读
|
|
623
|
+
*/
|
|
624
|
+
isSpeaking(): boolean;
|
|
625
|
+
/**
|
|
626
|
+
* 是否已暂停
|
|
627
|
+
*/
|
|
628
|
+
isPaused(): boolean;
|
|
629
|
+
/**
|
|
630
|
+
* 添加事件监听
|
|
631
|
+
*/
|
|
632
|
+
on(event: SynthesisEventType, handler: SynthesisEventHandler): void;
|
|
633
|
+
/**
|
|
634
|
+
* 移除事件监听
|
|
635
|
+
*/
|
|
636
|
+
off(event: SynthesisEventType, handler: SynthesisEventHandler): void;
|
|
637
|
+
/**
|
|
638
|
+
* 触发事件
|
|
639
|
+
*/
|
|
640
|
+
private emit;
|
|
641
|
+
/**
|
|
642
|
+
* 销毁实例
|
|
643
|
+
*/
|
|
644
|
+
dispose(): void;
|
|
645
|
+
/**
|
|
646
|
+
* 注册自定义提供商
|
|
647
|
+
*/
|
|
648
|
+
registerProvider(type: SpeechProviderType, provider: SynthesisProvider): void;
|
|
649
|
+
/**
|
|
650
|
+
* 使用云端适配器
|
|
651
|
+
*/
|
|
652
|
+
useCloudAdapter(adapter: ICloudSynthesisAdapter): void;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* 创建语音合成器实例
|
|
656
|
+
* @param config - 可选的合成配置
|
|
657
|
+
* @returns 语音合成器实例
|
|
658
|
+
*
|
|
659
|
+
* @example
|
|
660
|
+
* ```typescript
|
|
661
|
+
* // 使用原生合成
|
|
662
|
+
* const synthesizer = await createSpeechSynthesizer({
|
|
663
|
+
* lang: 'zh-CN',
|
|
664
|
+
* rate: 1.0,
|
|
665
|
+
* });
|
|
666
|
+
*
|
|
667
|
+
* // 使用云端合成 (Azure)
|
|
668
|
+
* const azureAdapter = new AzureSynthesisAdapter('key', 'eastasia');
|
|
669
|
+
* const cloudSynthesizer = await createSpeechSynthesizer({
|
|
670
|
+
* mode: 'cloud',
|
|
671
|
+
* cloudAdapter: azureAdapter,
|
|
672
|
+
* });
|
|
673
|
+
*
|
|
674
|
+
* await synthesizer.speak('你好,世界!');
|
|
675
|
+
* ```
|
|
676
|
+
*/
|
|
677
|
+
declare function createSpeechSynthesizer(config?: SynthesisConfig | IAdvancedSynthesisConfig): Promise<SpeechSynthesizer>;
|
|
678
|
+
/**
|
|
679
|
+
* 检查当前环境是否支持语音合成
|
|
680
|
+
* @returns 是否支持语音合成
|
|
681
|
+
*/
|
|
682
|
+
declare function isSpeechSynthesisSupported(): boolean;
|
|
683
|
+
/**
|
|
684
|
+
* 快速朗读文本(一次性使用)
|
|
685
|
+
* @param text - 要朗读的文本
|
|
686
|
+
* @param config - 可选的合成配置
|
|
687
|
+
*
|
|
688
|
+
* @example
|
|
689
|
+
* ```typescript
|
|
690
|
+
* // 快速朗读
|
|
691
|
+
* await speak('你好,世界!');
|
|
692
|
+
*
|
|
693
|
+
* // 带配置的朗读
|
|
694
|
+
* await speak('Hello World', { lang: 'en-US', rate: 0.8 });
|
|
695
|
+
* ```
|
|
696
|
+
*/
|
|
697
|
+
declare function speak(text: string, config?: SynthesisConfig | IAdvancedSynthesisConfig): Promise<void>;
|
|
698
|
+
/**
|
|
699
|
+
* 快速朗读文本(云端模式)
|
|
700
|
+
* @param text - 要朗读的文本
|
|
701
|
+
* @param adapter - 云端适配器
|
|
702
|
+
* @param config - 可选配置
|
|
703
|
+
*/
|
|
704
|
+
declare function speakWithCloud(text: string, adapter: ICloudSynthesisAdapter, config?: SynthesisConfig): Promise<void>;
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* @fileoverview 语音识别 (STT) 实现 - 商业级版本 v2.0
|
|
708
|
+
* @module melange/plugins/speech/recognition
|
|
709
|
+
* @description 生产级 Web 语音识别插件
|
|
710
|
+
*
|
|
711
|
+
* 架构:
|
|
712
|
+
* [UI层] -> [SpeechRecognizerImpl] -> [NativeStrategy / CloudStrategy]
|
|
713
|
+
* |
|
|
714
|
+
* +-> [音频核心]: Worklet, VAD, Resample
|
|
715
|
+
* +-> [适配器]: BaiduAdapter, XunfeiAdapter, TencentAdapter...
|
|
716
|
+
*
|
|
717
|
+
* 功能特性:
|
|
718
|
+
* 1. 多模式: 支持 WebSocket 流式识别 & HTTP 短语音识别
|
|
719
|
+
* 2. 状态机: IDLE -> CONNECTING -> RECORDING -> PROCESSING
|
|
720
|
+
* 3. 插件化: 内置 讯飞/腾讯/百度/阿里/Google/Azure 适配器
|
|
721
|
+
* 4. 核心: AudioWorklet + VAD + 自动重采样 + WAV编码
|
|
722
|
+
* 5. 兼容性: 自动降级处理 (ScriptProcessor) + 断网缓冲队列
|
|
723
|
+
*/
|
|
724
|
+
|
|
725
|
+
declare global {
|
|
726
|
+
interface Window {
|
|
727
|
+
SpeechRecognition?: unknown;
|
|
728
|
+
webkitSpeechRecognition?: unknown;
|
|
729
|
+
webkitAudioContext?: typeof AudioContext;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* 识别器状态枚举
|
|
734
|
+
*/
|
|
735
|
+
declare enum RecognitionStatus {
|
|
736
|
+
/** 空闲状态 */
|
|
737
|
+
IDLE = "IDLE",
|
|
738
|
+
/** 连接中 */
|
|
739
|
+
CONNECTING = "CONNECTING",
|
|
740
|
+
/** 录音中 */
|
|
741
|
+
RECORDING = "RECORDING",
|
|
742
|
+
/** 处理中/上传中 */
|
|
743
|
+
PROCESSING = "PROCESSING"
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* 识别引擎模式
|
|
747
|
+
*/
|
|
748
|
+
type RecognitionEngineMode = 'native' | 'cloud' | 'auto';
|
|
749
|
+
/**
|
|
750
|
+
* 云端传输协议类型
|
|
751
|
+
*/
|
|
752
|
+
type CloudTransportType = 'websocket' | 'http';
|
|
753
|
+
/**
|
|
754
|
+
* 识别结果接口
|
|
755
|
+
*/
|
|
756
|
+
interface IRecognitionResult {
|
|
757
|
+
/** 识别文本 */
|
|
758
|
+
transcript: string;
|
|
759
|
+
/** 是否为最终结果 */
|
|
760
|
+
isFinal: boolean;
|
|
761
|
+
/** 置信度 (0-1) */
|
|
762
|
+
confidence: number;
|
|
763
|
+
/** 原始响应数据 */
|
|
764
|
+
original?: unknown;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* 识别错误接口
|
|
768
|
+
*/
|
|
769
|
+
interface IRecognitionError {
|
|
770
|
+
/** 错误代码 */
|
|
771
|
+
code: 'NETWORK' | 'NOT_ALLOWED' | 'NO_SPEECH' | 'NOT_SUPPORTED' | 'VAD_TIMEOUT' | 'ADAPTER_ERROR' | 'UNKNOWN';
|
|
772
|
+
/** 错误信息 */
|
|
773
|
+
message: string;
|
|
774
|
+
/** 原始错误 */
|
|
775
|
+
originalError?: unknown;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* 音频配置接口
|
|
779
|
+
*/
|
|
780
|
+
interface IAudioConfig {
|
|
781
|
+
/** 目标采样率 (默认 16000) */
|
|
782
|
+
sampleRate?: number;
|
|
783
|
+
/** VAD 阈值 (0.01 ~ 0.5) */
|
|
784
|
+
vadThreshold?: number;
|
|
785
|
+
/** VAD 静音超时 (ms) */
|
|
786
|
+
vadDuration?: number;
|
|
787
|
+
/** 是否启用回声消除 */
|
|
788
|
+
echoCancellation?: boolean;
|
|
789
|
+
/** 是否启用噪声抑制 */
|
|
790
|
+
noiseSuppression?: boolean;
|
|
791
|
+
/** 是否启用自动增益控制 */
|
|
792
|
+
autoGainControl?: boolean;
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* 高级识别配置
|
|
796
|
+
*/
|
|
797
|
+
interface IAdvancedRecognitionConfig extends RecognitionConfig {
|
|
798
|
+
/** 识别引擎模式 */
|
|
799
|
+
mode?: RecognitionEngineMode;
|
|
800
|
+
/** 云端适配器 */
|
|
801
|
+
cloudAdapter?: ICloudRecognitionAdapter;
|
|
802
|
+
/** 传输协议 */
|
|
803
|
+
transport?: CloudTransportType;
|
|
804
|
+
/** 音频配置 */
|
|
805
|
+
audioConfig?: IAudioConfig;
|
|
806
|
+
/** 是否启用自动重连 */
|
|
807
|
+
autoReconnect?: boolean;
|
|
808
|
+
/** 最大重连次数 */
|
|
809
|
+
maxReconnectAttempts?: number;
|
|
810
|
+
/** 重连间隔 (ms) */
|
|
811
|
+
reconnectInterval?: number;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* 云端识别适配器接口
|
|
815
|
+
* 提供统一的第三方语音识别服务集成接口
|
|
816
|
+
*/
|
|
817
|
+
interface ICloudRecognitionAdapter {
|
|
818
|
+
/** 适配器名称 */
|
|
819
|
+
readonly name: string;
|
|
820
|
+
/**
|
|
821
|
+
* 获取 WebSocket 连接地址
|
|
822
|
+
* @returns WebSocket URL
|
|
823
|
+
*/
|
|
824
|
+
getConnectUrl?(): Promise<string> | string;
|
|
825
|
+
/**
|
|
826
|
+
* 获取握手参数
|
|
827
|
+
* @returns 握手消息
|
|
828
|
+
*/
|
|
829
|
+
getHandshakeParams?(): unknown;
|
|
830
|
+
/**
|
|
831
|
+
* HTTP 短语音识别
|
|
832
|
+
* @param audioData WAV/PCM 二进制数据
|
|
833
|
+
* @returns 识别结果
|
|
834
|
+
*/
|
|
835
|
+
recognizeShortAudio?(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
836
|
+
/**
|
|
837
|
+
* 转换音频数据格式
|
|
838
|
+
* @param pcmData PCM 原始数据
|
|
839
|
+
* @returns 转换后的数据
|
|
840
|
+
*/
|
|
841
|
+
transformAudioData?(pcmData: ArrayBuffer): ArrayBuffer | string;
|
|
842
|
+
/**
|
|
843
|
+
* 解析识别结果
|
|
844
|
+
* @param data 原始响应数据
|
|
845
|
+
* @returns 识别结果
|
|
846
|
+
*/
|
|
847
|
+
parseResult(data: unknown): IRecognitionResult | null;
|
|
848
|
+
/**
|
|
849
|
+
* 检查适配器是否可用
|
|
850
|
+
* @returns 是否可用
|
|
851
|
+
*/
|
|
852
|
+
isAvailable?(): boolean;
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* 音频处理工具集
|
|
856
|
+
*/
|
|
857
|
+
declare const AudioUtils: {
|
|
858
|
+
/**
|
|
859
|
+
* 重采样音频数据
|
|
860
|
+
* @param data 原始音频数据
|
|
861
|
+
* @param inputRate 输入采样率
|
|
862
|
+
* @param outputRate 输出采样率
|
|
863
|
+
* @returns 重采样后的数据
|
|
864
|
+
*/
|
|
865
|
+
resample(data: Float32Array, inputRate: number, outputRate: number): Float32Array;
|
|
866
|
+
/**
|
|
867
|
+
* Float32 转 Int16 PCM
|
|
868
|
+
* @param input Float32 数据
|
|
869
|
+
* @returns Int16 PCM 数据
|
|
870
|
+
*/
|
|
871
|
+
floatTo16BitPCM(input: Float32Array): Int16Array;
|
|
872
|
+
/**
|
|
873
|
+
* 计算音量 RMS
|
|
874
|
+
* @param data 音频数据
|
|
875
|
+
* @returns RMS 值
|
|
876
|
+
*/
|
|
877
|
+
calculateRMS(data: Float32Array): number;
|
|
878
|
+
/**
|
|
879
|
+
* 合并 PCM 片段
|
|
880
|
+
* @param buffers PCM 缓冲区数组
|
|
881
|
+
* @param totalLength 总采样数
|
|
882
|
+
* @returns 合并后的 Int16 数组
|
|
883
|
+
*/
|
|
884
|
+
mergeBuffers(buffers: ArrayBuffer[], totalLength: number): Int16Array;
|
|
885
|
+
/**
|
|
886
|
+
* PCM 转 WAV 封装
|
|
887
|
+
* @param samples PCM 采样数据
|
|
888
|
+
* @param sampleRate 采样率
|
|
889
|
+
* @param channels 声道数
|
|
890
|
+
* @returns WAV 格式 ArrayBuffer
|
|
891
|
+
*/
|
|
892
|
+
encodeWAV(samples: Int16Array, sampleRate?: number, channels?: number): ArrayBuffer;
|
|
893
|
+
/**
|
|
894
|
+
* ArrayBuffer 转 Base64
|
|
895
|
+
* @param buffer ArrayBuffer
|
|
896
|
+
* @returns Base64 字符串
|
|
897
|
+
*/
|
|
898
|
+
arrayBufferToBase64(buffer: ArrayBuffer): string;
|
|
899
|
+
};
|
|
900
|
+
/**
|
|
901
|
+
* 通用语音识别适配器。
|
|
902
|
+
*
|
|
903
|
+
* @description
|
|
904
|
+
* 这是生产推荐的 BFF 模式适配器。浏览器只上传用户授权后的短音频或连接
|
|
905
|
+
* 自有 WebSocket 网关,云厂商密钥、签名、大小限制、超时、审计和错误码
|
|
906
|
+
* 必须由后端完成。
|
|
907
|
+
*
|
|
908
|
+
* @remarks
|
|
909
|
+
* 默认协议:
|
|
910
|
+
* - `GET/WS {baseUrl}` 用于流式识别;
|
|
911
|
+
* - `POST {baseUrl}/recognize` 使用 `multipart/form-data` 字段 `file` 上传 WAV;
|
|
912
|
+
* - JSON 结果支持 `{ text, score }` 或 `{ transcript, confidence }`;
|
|
913
|
+
* - 错误响应建议映射为 `{ code, message, retryable, requestId? }`。
|
|
914
|
+
*/
|
|
915
|
+
declare class GenericAdapter implements ICloudRecognitionAdapter {
|
|
916
|
+
private baseUrl;
|
|
917
|
+
readonly name = "Generic/BFF";
|
|
918
|
+
constructor(baseUrl: string);
|
|
919
|
+
getConnectUrl(): string;
|
|
920
|
+
recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
921
|
+
parseResult(data: Record<string, unknown>): IRecognitionResult | null;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* 讯飞云示例适配器。
|
|
925
|
+
*
|
|
926
|
+
* @deprecated demo-only。该适配器只展示讯飞听写协议结构。生产环境应由 BFF
|
|
927
|
+
* 生成鉴权 URL 和请求签名,前端不得保存 apiKey/apiSecret。
|
|
928
|
+
*/
|
|
929
|
+
declare class XunfeiAdapter implements ICloudRecognitionAdapter {
|
|
930
|
+
private appId;
|
|
931
|
+
readonly name = "Xunfei";
|
|
932
|
+
/** API Key - 生产环境应在后端使用 */
|
|
933
|
+
readonly apiKey: string | undefined;
|
|
934
|
+
/** API Secret - 生产环境应在后端使用 */
|
|
935
|
+
readonly apiSecret: string | undefined;
|
|
936
|
+
constructor(appId: string, apiKey?: string, apiSecret?: string);
|
|
937
|
+
getConnectUrl(): string;
|
|
938
|
+
getHandshakeParams(): Record<string, unknown>;
|
|
939
|
+
recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
940
|
+
parseResult(data: Record<string, unknown>): IRecognitionResult | null;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* 腾讯云示例适配器。
|
|
944
|
+
*
|
|
945
|
+
* @deprecated demo-only。生产环境必须在 BFF 完成 TC3-HMAC-SHA256 签名,
|
|
946
|
+
* 不应在浏览器保存 secretId/secretKey。
|
|
947
|
+
*/
|
|
948
|
+
declare class TencentAdapter implements ICloudRecognitionAdapter {
|
|
949
|
+
readonly name = "Tencent";
|
|
950
|
+
/** Secret ID - 生产环境应在后端使用 */
|
|
951
|
+
readonly secretId: string;
|
|
952
|
+
/** Secret Key - 生产环境应在后端使用 */
|
|
953
|
+
readonly secretKey: string;
|
|
954
|
+
constructor(secretId: string, secretKey: string);
|
|
955
|
+
recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
956
|
+
parseResult(data: Record<string, unknown>): IRecognitionResult | null;
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* 百度云示例适配器。
|
|
960
|
+
*
|
|
961
|
+
* @deprecated experimental。access token、appId 和 appKey 不应由浏览器长期持有。
|
|
962
|
+
* 生产环境请通过 BFF 管理 token、音频大小限制、超时和错误映射。
|
|
963
|
+
*/
|
|
964
|
+
declare class BaiduAdapter implements ICloudRecognitionAdapter {
|
|
965
|
+
private accessToken;
|
|
966
|
+
private appId?;
|
|
967
|
+
private appKey?;
|
|
968
|
+
private devPid;
|
|
969
|
+
readonly name = "Baidu";
|
|
970
|
+
constructor(accessToken: string, appId?: string | undefined, appKey?: string | undefined, devPid?: number);
|
|
971
|
+
getConnectUrl(): string;
|
|
972
|
+
getHandshakeParams(): Record<string, unknown>;
|
|
973
|
+
recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
974
|
+
parseResult(data: Record<string, unknown>): IRecognitionResult | null;
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* 阿里云示例适配器。
|
|
978
|
+
*
|
|
979
|
+
* @deprecated demo-only。构造函数保留 accessKeySecret 以兼容旧 API,
|
|
980
|
+
* 生产环境应通过 BFF 获取临时凭证或由后端直接调用阿里云服务。
|
|
981
|
+
*/
|
|
982
|
+
declare class AlibabaAdapter implements ICloudRecognitionAdapter {
|
|
983
|
+
private accessKeyId;
|
|
984
|
+
private appKey;
|
|
985
|
+
readonly name = "Alibaba";
|
|
986
|
+
/** Access Key Secret - 生产环境应在后端使用 */
|
|
987
|
+
readonly accessKeySecret: string;
|
|
988
|
+
constructor(accessKeyId: string, accessKeySecret: string, appKey: string);
|
|
989
|
+
getConnectUrl(): string;
|
|
990
|
+
getHandshakeParams(): Record<string, unknown>;
|
|
991
|
+
recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
992
|
+
parseResult(data: Record<string, unknown>): IRecognitionResult | null;
|
|
993
|
+
private generateUUID;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Google Cloud Speech 直连适配器。
|
|
997
|
+
*
|
|
998
|
+
* @deprecated demo-only。该适配器会将 API key 放入浏览器请求 URL,
|
|
999
|
+
* 生产环境请通过 BFF 代理调用 Google Cloud Speech。
|
|
1000
|
+
*/
|
|
1001
|
+
declare class GoogleAdapter implements ICloudRecognitionAdapter {
|
|
1002
|
+
private apiKey;
|
|
1003
|
+
private languageCode;
|
|
1004
|
+
readonly name = "Google";
|
|
1005
|
+
constructor(apiKey: string, languageCode?: string);
|
|
1006
|
+
recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
1007
|
+
parseResult(data: Record<string, unknown>): IRecognitionResult | null;
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Azure Speech 直连适配器。
|
|
1011
|
+
*
|
|
1012
|
+
* @deprecated demo-only。该适配器会在浏览器请求中使用 subscription key,
|
|
1013
|
+
* 生产环境请通过 BFF 代理调用 Azure Speech。
|
|
1014
|
+
*/
|
|
1015
|
+
declare class AzureAdapter implements ICloudRecognitionAdapter {
|
|
1016
|
+
private subscriptionKey;
|
|
1017
|
+
private region;
|
|
1018
|
+
private language;
|
|
1019
|
+
readonly name = "Azure";
|
|
1020
|
+
constructor(subscriptionKey: string, region: string, language?: string);
|
|
1021
|
+
getConnectUrl(): string;
|
|
1022
|
+
getHandshakeParams(): Record<string, unknown>;
|
|
1023
|
+
recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult>;
|
|
1024
|
+
parseResult(data: Record<string, unknown>): IRecognitionResult | null;
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* 语音识别器实现
|
|
1028
|
+
* 统一封装原生识别和云端识别
|
|
1029
|
+
*/
|
|
1030
|
+
declare class SpeechRecognizerImpl implements SpeechRecognizer {
|
|
1031
|
+
private strategy;
|
|
1032
|
+
private config;
|
|
1033
|
+
private _currentProvider;
|
|
1034
|
+
private _status;
|
|
1035
|
+
private eventHandlers;
|
|
1036
|
+
private customProviders;
|
|
1037
|
+
get currentProvider(): SpeechProviderType;
|
|
1038
|
+
get status(): SpeechServiceStatus;
|
|
1039
|
+
/**
|
|
1040
|
+
* 获取当前识别状态
|
|
1041
|
+
*/
|
|
1042
|
+
get recognitionStatus(): RecognitionStatus;
|
|
1043
|
+
/**
|
|
1044
|
+
* 初始化语音识别器
|
|
1045
|
+
*/
|
|
1046
|
+
initialize(config?: RecognitionConfig): Promise<void>;
|
|
1047
|
+
/**
|
|
1048
|
+
* 初始化识别策略
|
|
1049
|
+
*/
|
|
1050
|
+
private initializeStrategy;
|
|
1051
|
+
/**
|
|
1052
|
+
* 转发策略事件
|
|
1053
|
+
*/
|
|
1054
|
+
private forwardStrategyEvents;
|
|
1055
|
+
/**
|
|
1056
|
+
* 转换识别结果格式
|
|
1057
|
+
*/
|
|
1058
|
+
private convertResult;
|
|
1059
|
+
/**
|
|
1060
|
+
* 开始识别
|
|
1061
|
+
*/
|
|
1062
|
+
start(config?: RecognitionConfig): Promise<void>;
|
|
1063
|
+
/**
|
|
1064
|
+
* 停止识别
|
|
1065
|
+
*/
|
|
1066
|
+
stop(): void;
|
|
1067
|
+
/**
|
|
1068
|
+
* 中止识别
|
|
1069
|
+
*/
|
|
1070
|
+
abort(): void;
|
|
1071
|
+
/**
|
|
1072
|
+
* 是否正在识别
|
|
1073
|
+
*/
|
|
1074
|
+
isListening(): boolean;
|
|
1075
|
+
/**
|
|
1076
|
+
* 添加事件监听
|
|
1077
|
+
*/
|
|
1078
|
+
on(event: RecognitionEventType, handler: RecognitionEventHandler): void;
|
|
1079
|
+
/**
|
|
1080
|
+
* 移除事件监听
|
|
1081
|
+
*/
|
|
1082
|
+
off(event: RecognitionEventType, handler: RecognitionEventHandler): void;
|
|
1083
|
+
/**
|
|
1084
|
+
* 触发事件
|
|
1085
|
+
*/
|
|
1086
|
+
private emit;
|
|
1087
|
+
/**
|
|
1088
|
+
* 销毁实例
|
|
1089
|
+
*/
|
|
1090
|
+
dispose(): void;
|
|
1091
|
+
/**
|
|
1092
|
+
* 注册自定义提供商
|
|
1093
|
+
*/
|
|
1094
|
+
registerProvider(type: SpeechProviderType, provider: RecognitionProvider): void;
|
|
1095
|
+
/**
|
|
1096
|
+
* 使用云端适配器
|
|
1097
|
+
*/
|
|
1098
|
+
useCloudAdapter(adapter: ICloudRecognitionAdapter): void;
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* 创建语音识别器实例
|
|
1102
|
+
* @param config 识别配置
|
|
1103
|
+
* @returns 语音识别器实例
|
|
1104
|
+
*
|
|
1105
|
+
* @example
|
|
1106
|
+
* ```typescript
|
|
1107
|
+
* // 使用原生识别
|
|
1108
|
+
* const recognizer = await createSpeechRecognizer({
|
|
1109
|
+
* lang: 'zh-CN',
|
|
1110
|
+
* continuous: true,
|
|
1111
|
+
* });
|
|
1112
|
+
*
|
|
1113
|
+
* // 使用云端识别 (百度)
|
|
1114
|
+
* const baiduAdapter = new BaiduAdapter('your-access-token');
|
|
1115
|
+
* const cloudRecognizer = await createSpeechRecognizer({
|
|
1116
|
+
* mode: 'cloud',
|
|
1117
|
+
* cloudAdapter: baiduAdapter,
|
|
1118
|
+
* transport: 'http',
|
|
1119
|
+
* });
|
|
1120
|
+
*
|
|
1121
|
+
* recognizer.on('result', (event) => {
|
|
1122
|
+
* console.log('识别结果:', event.result?.bestTranscript);
|
|
1123
|
+
* });
|
|
1124
|
+
*
|
|
1125
|
+
* await recognizer.start();
|
|
1126
|
+
* ```
|
|
1127
|
+
*/
|
|
1128
|
+
declare function createSpeechRecognizer(config?: RecognitionConfig | IAdvancedRecognitionConfig): Promise<SpeechRecognizer>;
|
|
1129
|
+
/**
|
|
1130
|
+
* 检查当前环境是否支持语音识别
|
|
1131
|
+
* @returns 是否支持
|
|
1132
|
+
*/
|
|
1133
|
+
declare function isSpeechRecognitionSupported(): boolean;
|
|
1134
|
+
/**
|
|
1135
|
+
* 快速进行一次语音识别
|
|
1136
|
+
* @param config 识别配置
|
|
1137
|
+
* @returns 识别结果
|
|
1138
|
+
*
|
|
1139
|
+
* @example
|
|
1140
|
+
* ```typescript
|
|
1141
|
+
* const result = await listen({ lang: 'zh-CN' });
|
|
1142
|
+
* console.log('识别结果:', result.bestTranscript);
|
|
1143
|
+
* ```
|
|
1144
|
+
*/
|
|
1145
|
+
declare function listen(config?: RecognitionConfig | IAdvancedRecognitionConfig): Promise<RecognitionResult>;
|
|
1146
|
+
/**
|
|
1147
|
+
* 创建带超时的语音识别
|
|
1148
|
+
* @param config 识别配置
|
|
1149
|
+
* @param timeout 超时时间 (ms)
|
|
1150
|
+
* @returns 识别结果
|
|
1151
|
+
*/
|
|
1152
|
+
declare function listenWithTimeout(config?: RecognitionConfig | IAdvancedRecognitionConfig, timeout?: number): Promise<RecognitionResult>;
|
|
1153
|
+
|
|
1154
|
+
/**
|
|
1155
|
+
* @fileoverview 指纹识别模块类型定义
|
|
1156
|
+
* @module melange/plugins/fingerprint/types
|
|
1157
|
+
* @description
|
|
1158
|
+
* 定义指纹识别插件对外暴露的配置、结果、组件和采集器类型。
|
|
1159
|
+
*
|
|
1160
|
+
* 本模块的类型设计参考 FingerprintJS 的“组件集合 -> 稳定哈希”模型,
|
|
1161
|
+
* 但默认语义偏向隐私保护:组件值必须可序列化、可解释,并且鼓励调用方
|
|
1162
|
+
* 使用低敏、低熵信号,不采集音频、Canvas 像素、字体枚举、浏览历史等
|
|
1163
|
+
* 可能超出用户预期的内容。
|
|
1164
|
+
*/
|
|
1165
|
+
/**
|
|
1166
|
+
* 内置指纹组件键。
|
|
1167
|
+
*
|
|
1168
|
+
* @description
|
|
1169
|
+
* 这些键对应 `defaultFingerprintCollectors` 中提供的默认采集器。
|
|
1170
|
+
* 调用方可以在 `FingerprintOptions.include` 或 `FingerprintOptions.exclude`
|
|
1171
|
+
* 中使用这些键来精确控制组件范围。
|
|
1172
|
+
*
|
|
1173
|
+
* @remarks
|
|
1174
|
+
* 内置键只覆盖低敏浏览器环境信息和能力检测信息。若业务需要新增字段,
|
|
1175
|
+
* 应通过 `FingerprintCollector` 注册自定义采集器,并确保已获得合规授权。
|
|
1176
|
+
*/
|
|
1177
|
+
type FingerprintComponentKey =
|
|
1178
|
+
/** 浏览器 User-Agent。默认会归一化补丁版本和构建号。 */
|
|
1179
|
+
'userAgent'
|
|
1180
|
+
/** 操作系统或浏览器平台标识,例如 Win32、MacIntel。 */
|
|
1181
|
+
| 'platform'
|
|
1182
|
+
/** 浏览器首选语言,例如 zh-CN。 */
|
|
1183
|
+
| 'language'
|
|
1184
|
+
/** 浏览器语言偏好列表,strict 模式下仅保留首选语言。 */
|
|
1185
|
+
| 'languages'
|
|
1186
|
+
/** IANA 时区名称,strict 模式下仅记录是否可用。 */
|
|
1187
|
+
| 'timezone'
|
|
1188
|
+
/** 当前时区偏移量,单位为分钟。 */
|
|
1189
|
+
| 'timezoneOffset'
|
|
1190
|
+
/** 屏幕尺寸信息,balanced 模式下按桶归一化。 */
|
|
1191
|
+
| 'screen'
|
|
1192
|
+
/** 屏幕色深。 */
|
|
1193
|
+
| 'colorDepth'
|
|
1194
|
+
/** 设备像素比,默认按 0.25 桶归一化。 */
|
|
1195
|
+
| 'pixelRatio'
|
|
1196
|
+
/** 硬件线程数,默认按区间分桶。 */
|
|
1197
|
+
| 'hardwareConcurrency'
|
|
1198
|
+
/** 设备内存,默认按区间分桶。 */
|
|
1199
|
+
| 'deviceMemory'
|
|
1200
|
+
/** 最大触摸点数量。 */
|
|
1201
|
+
| 'maxTouchPoints'
|
|
1202
|
+
/** Cookie 是否可用。 */
|
|
1203
|
+
| 'cookiesEnabled'
|
|
1204
|
+
/** localStorage/sessionStorage 能力检测结果。 */
|
|
1205
|
+
| 'storage'
|
|
1206
|
+
/** IndexedDB 是否可用。 */
|
|
1207
|
+
| 'indexedDB'
|
|
1208
|
+
/** 浏览器 Do Not Track 偏好。 */
|
|
1209
|
+
| 'doNotTrack';
|
|
1210
|
+
/**
|
|
1211
|
+
* 指纹组件来源。
|
|
1212
|
+
*
|
|
1213
|
+
* @description
|
|
1214
|
+
* 来源用于解释组件的敏感度和用途,便于调用方在日志、审计或调试界面中
|
|
1215
|
+
* 判断某个组件为什么会进入指纹计算。
|
|
1216
|
+
*/
|
|
1217
|
+
type FingerprintComponentSource =
|
|
1218
|
+
/** 低熵环境信息,如语言、平台、分桶后的屏幕尺寸。 */
|
|
1219
|
+
'low-entropy'
|
|
1220
|
+
/** 能力检测信息,如存储能力、Cookie 可用性。 */
|
|
1221
|
+
| 'capability'
|
|
1222
|
+
/** 调用方通过 `collectors` 传入的业务自定义组件。 */
|
|
1223
|
+
| 'custom';
|
|
1224
|
+
/**
|
|
1225
|
+
* 指纹隐私模式。
|
|
1226
|
+
*
|
|
1227
|
+
* @description
|
|
1228
|
+
* 隐私模式会影响默认采集器如何处理可能带来唯一性的字段。
|
|
1229
|
+
* 模式越严格,组件值越粗粒度,visitorId 的稳定性和区分度也会相应下降。
|
|
1230
|
+
*/
|
|
1231
|
+
type FingerprintPrivacyMode =
|
|
1232
|
+
/** 最小化模式:尽量只保留可用性或首选项,适合隐私优先场景。 */
|
|
1233
|
+
'strict'
|
|
1234
|
+
/** 平衡模式:默认模式,保留低敏信号并对高波动字段分桶/归一化。 */
|
|
1235
|
+
| 'balanced'
|
|
1236
|
+
/** 调试模式:保留更多原始值,便于定位环境差异,不建议生产默认启用。 */
|
|
1237
|
+
| 'debug';
|
|
1238
|
+
/**
|
|
1239
|
+
* 指纹哈希算法。
|
|
1240
|
+
*
|
|
1241
|
+
* @description
|
|
1242
|
+
* `fnv1a64` 体积小、速度快,适合本地非安全标识生成。
|
|
1243
|
+
* `sha256` 会优先使用 Web Crypto API,在不可用时自动降级到 `fnv1a64`。
|
|
1244
|
+
*
|
|
1245
|
+
* @remarks
|
|
1246
|
+
* 指纹哈希不是加密身份凭证,不应作为鉴权、风控唯一依据或秘密值使用。
|
|
1247
|
+
*/
|
|
1248
|
+
type FingerprintHashAlgorithm =
|
|
1249
|
+
/** 64 位 FNV-1a 非加密哈希,默认算法。 */
|
|
1250
|
+
'fnv1a64'
|
|
1251
|
+
/** SHA-256 哈希,依赖 `globalThis.crypto.subtle`。 */
|
|
1252
|
+
| 'sha256';
|
|
1253
|
+
/**
|
|
1254
|
+
* 可序列化的指纹组件值。
|
|
1255
|
+
*
|
|
1256
|
+
* @description
|
|
1257
|
+
* 组件值必须可以稳定序列化,才能保证相同组件集合在不同执行时机生成相同
|
|
1258
|
+
* 的哈希输入。这里刻意限制为 JSON 兼容值,避免函数、DOM 节点、错误对象、
|
|
1259
|
+
* Map/Set 等不可预测结构进入指纹计算。
|
|
1260
|
+
*/
|
|
1261
|
+
type FingerprintValue =
|
|
1262
|
+
/** 字符串组件值。 */
|
|
1263
|
+
string
|
|
1264
|
+
/** 数字组件值。应优先使用分桶后的粗粒度数值。 */
|
|
1265
|
+
| number
|
|
1266
|
+
/** 布尔组件值,常用于能力检测。 */
|
|
1267
|
+
| boolean
|
|
1268
|
+
/** 明确表示采集不到或环境不支持。 */
|
|
1269
|
+
| null
|
|
1270
|
+
/** 由可序列化值组成的只读数组。 */
|
|
1271
|
+
| readonly FingerprintValue[]
|
|
1272
|
+
/** 键为字符串、值为可序列化值的只读对象。 */
|
|
1273
|
+
| {
|
|
1274
|
+
readonly [key: string]: FingerprintValue;
|
|
1275
|
+
};
|
|
1276
|
+
/**
|
|
1277
|
+
* 单个指纹组件。
|
|
1278
|
+
*
|
|
1279
|
+
* @template T - 组件值类型,必须是可稳定序列化的 `FingerprintValue`
|
|
1280
|
+
*
|
|
1281
|
+
* @description
|
|
1282
|
+
* 组件是指纹计算的最小单元。每个组件包含值、来源、采集耗时和稳定性权重。
|
|
1283
|
+
* 生成器只会将 `value` 写入哈希输入,其余字段用于调试、审计和置信度计算。
|
|
1284
|
+
*/
|
|
1285
|
+
interface FingerprintComponent<T extends FingerprintValue = FingerprintValue> {
|
|
1286
|
+
/**
|
|
1287
|
+
* 组件值。
|
|
1288
|
+
*
|
|
1289
|
+
* @remarks
|
|
1290
|
+
* 该值会参与 `visitorId` 计算。请勿放入直接身份信息、精确位置、账号 ID、
|
|
1291
|
+
* 设备序列号或其他可单独识别个人的数据。
|
|
1292
|
+
*/
|
|
1293
|
+
readonly value: T;
|
|
1294
|
+
/**
|
|
1295
|
+
* 组件来源。
|
|
1296
|
+
*
|
|
1297
|
+
* @remarks
|
|
1298
|
+
* 来源不会参与哈希计算,只用于解释该组件来自内置低熵采集、能力检测,
|
|
1299
|
+
* 还是调用方提供的自定义采集器。
|
|
1300
|
+
*/
|
|
1301
|
+
readonly source: FingerprintComponentSource;
|
|
1302
|
+
/**
|
|
1303
|
+
* 组件采集耗时,单位毫秒。
|
|
1304
|
+
*
|
|
1305
|
+
* @remarks
|
|
1306
|
+
* 该字段用于性能分析,不参与哈希计算。耗时由 `context.now()` 计算,
|
|
1307
|
+
* 在浏览器中通常来自 `performance.now()`。
|
|
1308
|
+
*/
|
|
1309
|
+
readonly duration: number;
|
|
1310
|
+
/**
|
|
1311
|
+
* 组件稳定性权重,范围 0-1。
|
|
1312
|
+
*
|
|
1313
|
+
* @remarks
|
|
1314
|
+
* 数值越高表示该组件越稳定、越适合参与“同一浏览器环境”的粗略判断。
|
|
1315
|
+
* 它只参与 `confidence.score` 计算,不会改变组件值或哈希算法。
|
|
1316
|
+
*/
|
|
1317
|
+
readonly confidence: number;
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1320
|
+
* 指纹组件集合。
|
|
1321
|
+
*
|
|
1322
|
+
* @description
|
|
1323
|
+
* 以组件键为索引的映射。生成哈希前会按键名排序,以避免对象插入顺序影响
|
|
1324
|
+
* `visitorId`。
|
|
1325
|
+
*/
|
|
1326
|
+
type FingerprintComponentMap = Record<string, FingerprintComponent>;
|
|
1327
|
+
/**
|
|
1328
|
+
* 指纹置信度说明。
|
|
1329
|
+
*
|
|
1330
|
+
* @description
|
|
1331
|
+
* 置信度是一个可解释的质量指标,用于告诉调用方本次结果包含多少组件、
|
|
1332
|
+
* 跳过了多少组件,以及组件稳定性的大致水平。
|
|
1333
|
+
*
|
|
1334
|
+
* @remarks
|
|
1335
|
+
* 置信度不是概率,不代表识别某个自然人的准确率,也不应作为风控阈值的
|
|
1336
|
+
* 唯一依据。
|
|
1337
|
+
*/
|
|
1338
|
+
interface FingerprintConfidence {
|
|
1339
|
+
/**
|
|
1340
|
+
* 置信度分数,范围 0-1。
|
|
1341
|
+
*
|
|
1342
|
+
* @remarks
|
|
1343
|
+
* 当前实现会结合组件平均权重和采集覆盖率,并将最高值限制在 0.99,
|
|
1344
|
+
* 避免表达“绝对确定”的含义。
|
|
1345
|
+
*/
|
|
1346
|
+
readonly score: number;
|
|
1347
|
+
/**
|
|
1348
|
+
* 参与哈希的组件数量。
|
|
1349
|
+
*
|
|
1350
|
+
* @remarks
|
|
1351
|
+
* 仅统计成功采集且没有超时/抛错的组件。
|
|
1352
|
+
*/
|
|
1353
|
+
readonly componentCount: number;
|
|
1354
|
+
/**
|
|
1355
|
+
* 被跳过的组件数量。
|
|
1356
|
+
*
|
|
1357
|
+
* @remarks
|
|
1358
|
+
* 组件可能因为 include/exclude 过滤、采集异常、超时或返回 `undefined`
|
|
1359
|
+
* 被跳过。
|
|
1360
|
+
*/
|
|
1361
|
+
readonly skippedCount: number;
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* 指纹生成结果。
|
|
1365
|
+
*
|
|
1366
|
+
* @description
|
|
1367
|
+
* 与 FingerprintJS 类似,结果包含稳定标识 `visitorId` 和组件详情
|
|
1368
|
+
* `components`。Melange 额外提供 `confidence`、`duration` 和版本信息,
|
|
1369
|
+
* 方便业务侧做性能监控和兼容判断。
|
|
1370
|
+
*/
|
|
1371
|
+
interface FingerprintResult {
|
|
1372
|
+
/**
|
|
1373
|
+
* 生成的访问者标识。
|
|
1374
|
+
*
|
|
1375
|
+
* @remarks
|
|
1376
|
+
* 这是组件值稳定序列化后计算出的哈希。它不是用户 ID,也不是安全令牌;
|
|
1377
|
+
* 不建议跨业务、跨站点或无限期保存。
|
|
1378
|
+
*/
|
|
1379
|
+
readonly visitorId: string;
|
|
1380
|
+
/**
|
|
1381
|
+
* 参与生成指纹的组件。
|
|
1382
|
+
*
|
|
1383
|
+
* @remarks
|
|
1384
|
+
* 只包含成功采集的组件。被 include/exclude 过滤、超时或抛错的组件不会出现。
|
|
1385
|
+
*/
|
|
1386
|
+
readonly components: FingerprintComponentMap;
|
|
1387
|
+
/**
|
|
1388
|
+
* 本次指纹结果的质量说明。
|
|
1389
|
+
*/
|
|
1390
|
+
readonly confidence: FingerprintConfidence;
|
|
1391
|
+
/**
|
|
1392
|
+
* 指纹模块版本。
|
|
1393
|
+
*
|
|
1394
|
+
* @remarks
|
|
1395
|
+
* 当默认采集器、归一化策略或哈希输入格式变化时,版本可用于帮助调用方
|
|
1396
|
+
* 做兼容处理。
|
|
1397
|
+
*/
|
|
1398
|
+
readonly version: string;
|
|
1399
|
+
/**
|
|
1400
|
+
* 本次生成总耗时,单位毫秒。
|
|
1401
|
+
*
|
|
1402
|
+
* @remarks
|
|
1403
|
+
* 包括组件采集、序列化和哈希计算耗时。
|
|
1404
|
+
*/
|
|
1405
|
+
readonly duration: number;
|
|
1406
|
+
/**
|
|
1407
|
+
* 生成时间戳,来自 `Date.now()`。
|
|
1408
|
+
*/
|
|
1409
|
+
readonly generatedAt: number;
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* 指纹组件采集上下文。
|
|
1413
|
+
*
|
|
1414
|
+
* @description
|
|
1415
|
+
* 生成器会把上下文传给每个内置或自定义采集器。上下文中包含已合并默认值
|
|
1416
|
+
* 的配置,以及统一的时间函数,方便采集器根据隐私模式调整返回值。
|
|
1417
|
+
*/
|
|
1418
|
+
interface FingerprintCollectorContext {
|
|
1419
|
+
/**
|
|
1420
|
+
* 当前已解析配置。
|
|
1421
|
+
*
|
|
1422
|
+
* @remarks
|
|
1423
|
+
* 这里的配置已合并生成器默认配置和本次调用覆盖配置,不包含 `undefined`。
|
|
1424
|
+
*/
|
|
1425
|
+
readonly options: RequiredFingerprintOptions;
|
|
1426
|
+
/**
|
|
1427
|
+
* 当前时间函数,返回毫秒级时间。
|
|
1428
|
+
*
|
|
1429
|
+
* @returns 当前高精度或普通时间戳
|
|
1430
|
+
*/
|
|
1431
|
+
now(): number;
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* 自定义指纹组件采集器。
|
|
1435
|
+
*
|
|
1436
|
+
* @template T - 采集器返回值类型,必须是 `FingerprintValue`
|
|
1437
|
+
*
|
|
1438
|
+
* @description
|
|
1439
|
+
* 业务可以通过 `FingerprintOptions.collectors` 传入自定义采集器,将自身
|
|
1440
|
+
* 已合法获得、低敏且可解释的状态纳入指纹。采集器可以同步或异步返回。
|
|
1441
|
+
*
|
|
1442
|
+
* @remarks
|
|
1443
|
+
* 采集器返回 `undefined` 会被视为跳过组件;返回 `null` 则表示“明确无值”,
|
|
1444
|
+
* 会参与哈希计算。采集器抛错或超时也会被跳过,不会中断整体指纹生成。
|
|
1445
|
+
*/
|
|
1446
|
+
interface FingerprintCollector<T extends FingerprintValue = FingerprintValue> {
|
|
1447
|
+
/**
|
|
1448
|
+
* 组件键。
|
|
1449
|
+
*
|
|
1450
|
+
* @remarks
|
|
1451
|
+
* 键名会出现在 `components` 中,并参与稳定排序。建议使用业务内唯一、
|
|
1452
|
+
* 语义清晰的 camelCase 名称,避免覆盖内置组件,除非明确需要替换。
|
|
1453
|
+
*/
|
|
1454
|
+
readonly key: string;
|
|
1455
|
+
/**
|
|
1456
|
+
* 组件来源。
|
|
1457
|
+
*
|
|
1458
|
+
* @defaultValue `'custom'`
|
|
1459
|
+
*/
|
|
1460
|
+
readonly source?: FingerprintComponentSource;
|
|
1461
|
+
/**
|
|
1462
|
+
* 组件稳定性权重,范围 0-1。
|
|
1463
|
+
*
|
|
1464
|
+
* @defaultValue `0.4`
|
|
1465
|
+
*
|
|
1466
|
+
* @remarks
|
|
1467
|
+
* 权重只影响置信度,不影响哈希。自定义低敏业务状态通常建议给较低权重。
|
|
1468
|
+
*/
|
|
1469
|
+
readonly confidence?: number;
|
|
1470
|
+
/**
|
|
1471
|
+
* 采集组件值。
|
|
1472
|
+
*
|
|
1473
|
+
* @param context - 指纹组件采集上下文,包含隐私模式、超时配置和时间函数
|
|
1474
|
+
* @returns 可序列化组件值;返回 Promise 时生成器会等待其完成或超时
|
|
1475
|
+
*/
|
|
1476
|
+
collect(context: FingerprintCollectorContext): T | Promise<T>;
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* 指纹生成配置。
|
|
1480
|
+
*
|
|
1481
|
+
* @description
|
|
1482
|
+
* 配置既可以传给 `createFingerprintGenerator` 作为实例默认值,也可以传给
|
|
1483
|
+
* `get` 或 `getFingerprint` 作为本次调用覆盖值。本次调用配置优先级更高。
|
|
1484
|
+
*/
|
|
1485
|
+
interface FingerprintOptions {
|
|
1486
|
+
/**
|
|
1487
|
+
* 命名空间盐值,用于隔离不同业务域的指纹结果。
|
|
1488
|
+
*
|
|
1489
|
+
* @defaultValue `'melange'`
|
|
1490
|
+
*
|
|
1491
|
+
* @remarks
|
|
1492
|
+
* 建议每个产品、租户或用途使用不同盐值,避免不同业务之间的 visitorId
|
|
1493
|
+
* 可以直接关联。
|
|
1494
|
+
*/
|
|
1495
|
+
readonly salt?: string;
|
|
1496
|
+
/**
|
|
1497
|
+
* 是否启用内存缓存。
|
|
1498
|
+
*
|
|
1499
|
+
* @defaultValue `true`
|
|
1500
|
+
*
|
|
1501
|
+
* @remarks
|
|
1502
|
+
* 缓存只存在于当前生成器实例内,不写入 localStorage、Cookie 或 IndexedDB。
|
|
1503
|
+
*/
|
|
1504
|
+
readonly cache?: boolean;
|
|
1505
|
+
/**
|
|
1506
|
+
* 内存缓存有效期,单位毫秒。
|
|
1507
|
+
*
|
|
1508
|
+
* @defaultValue `300000`
|
|
1509
|
+
*/
|
|
1510
|
+
readonly cacheTtl?: number;
|
|
1511
|
+
/**
|
|
1512
|
+
* 单个组件采集超时时间,单位毫秒。
|
|
1513
|
+
*
|
|
1514
|
+
* @defaultValue `80`
|
|
1515
|
+
*
|
|
1516
|
+
* @remarks
|
|
1517
|
+
* 超时的组件会被跳过,避免慢组件拖累首屏或交互流程。
|
|
1518
|
+
*/
|
|
1519
|
+
readonly componentTimeout?: number;
|
|
1520
|
+
/**
|
|
1521
|
+
* 指纹隐私模式。
|
|
1522
|
+
*
|
|
1523
|
+
* @defaultValue `'balanced'`
|
|
1524
|
+
*/
|
|
1525
|
+
readonly privacyMode?: FingerprintPrivacyMode;
|
|
1526
|
+
/**
|
|
1527
|
+
* 指纹哈希算法。
|
|
1528
|
+
*
|
|
1529
|
+
* @defaultValue `'fnv1a64'`
|
|
1530
|
+
*/
|
|
1531
|
+
readonly hashAlgorithm?: FingerprintHashAlgorithm;
|
|
1532
|
+
/**
|
|
1533
|
+
* 屏幕尺寸分桶大小。
|
|
1534
|
+
*
|
|
1535
|
+
* @defaultValue `100`
|
|
1536
|
+
*
|
|
1537
|
+
* @remarks
|
|
1538
|
+
* 仅影响非 debug 模式下的屏幕尺寸组件。值越大,隐私越强,区分度越低。
|
|
1539
|
+
*/
|
|
1540
|
+
readonly screenBucketSize?: number;
|
|
1541
|
+
/**
|
|
1542
|
+
* 是否归一化 User-Agent。
|
|
1543
|
+
*
|
|
1544
|
+
* @defaultValue
|
|
1545
|
+
* `balanced` 和 `strict` 模式为 `true`,`debug` 模式为 `false`。
|
|
1546
|
+
*/
|
|
1547
|
+
readonly normalizeUserAgent?: boolean;
|
|
1548
|
+
/**
|
|
1549
|
+
* 只采集指定组件。
|
|
1550
|
+
*
|
|
1551
|
+
* @remarks
|
|
1552
|
+
* 为空数组或未提供时表示不限制。若同时提供 `include` 和 `exclude`,
|
|
1553
|
+
* 会先判断 include,再应用 exclude。
|
|
1554
|
+
*/
|
|
1555
|
+
readonly include?: readonly string[];
|
|
1556
|
+
/**
|
|
1557
|
+
* 排除指定组件。
|
|
1558
|
+
*
|
|
1559
|
+
* @remarks
|
|
1560
|
+
* 可用于关闭业务不希望采集的内置组件,例如 `userAgent` 或 `screen`。
|
|
1561
|
+
*/
|
|
1562
|
+
readonly exclude?: readonly string[];
|
|
1563
|
+
/**
|
|
1564
|
+
* 自定义低敏组件采集器。
|
|
1565
|
+
*
|
|
1566
|
+
* @remarks
|
|
1567
|
+
* 自定义采集器会追加到内置采集器之后,并受 include/exclude 和超时配置控制。
|
|
1568
|
+
*/
|
|
1569
|
+
readonly collectors?: readonly FingerprintCollector[];
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* 内部已填充默认值的配置。
|
|
1573
|
+
*
|
|
1574
|
+
* @description
|
|
1575
|
+
* 生成器内部使用的配置形态。与 `FingerprintOptions` 不同,这里所有字段都
|
|
1576
|
+
* 已经有确定值,便于采集器和内部函数直接读取。
|
|
1577
|
+
*/
|
|
1578
|
+
interface RequiredFingerprintOptions {
|
|
1579
|
+
/** 命名空间盐值。 */
|
|
1580
|
+
readonly salt: string;
|
|
1581
|
+
/** 是否启用当前生成器实例内的内存缓存。 */
|
|
1582
|
+
readonly cache: boolean;
|
|
1583
|
+
/** 缓存有效期,单位毫秒。 */
|
|
1584
|
+
readonly cacheTtl: number;
|
|
1585
|
+
/** 单组件采集超时时间,单位毫秒。 */
|
|
1586
|
+
readonly componentTimeout: number;
|
|
1587
|
+
/** 已解析隐私模式。 */
|
|
1588
|
+
readonly privacyMode: FingerprintPrivacyMode;
|
|
1589
|
+
/** 已解析哈希算法。 */
|
|
1590
|
+
readonly hashAlgorithm: FingerprintHashAlgorithm;
|
|
1591
|
+
/** 已解析屏幕尺寸分桶大小。 */
|
|
1592
|
+
readonly screenBucketSize: number;
|
|
1593
|
+
/** 已解析 User-Agent 归一化开关。 */
|
|
1594
|
+
readonly normalizeUserAgent: boolean;
|
|
1595
|
+
/** 已解析 include 列表。 */
|
|
1596
|
+
readonly include: readonly string[];
|
|
1597
|
+
/** 已解析 exclude 列表。 */
|
|
1598
|
+
readonly exclude: readonly string[];
|
|
1599
|
+
/** 已解析自定义采集器列表。 */
|
|
1600
|
+
readonly collectors: readonly FingerprintCollector[];
|
|
1601
|
+
}
|
|
1602
|
+
/**
|
|
1603
|
+
* 指纹生成器接口。
|
|
1604
|
+
*
|
|
1605
|
+
* @description
|
|
1606
|
+
* 生成器封装默认配置和内存缓存,适合在应用启动时创建一次并通过依赖注入
|
|
1607
|
+
* 或模块单例复用。
|
|
1608
|
+
*/
|
|
1609
|
+
interface FingerprintGenerator {
|
|
1610
|
+
/**
|
|
1611
|
+
* 获取指纹结果。
|
|
1612
|
+
*
|
|
1613
|
+
* @param options - 本次调用的覆盖配置
|
|
1614
|
+
* @returns 指纹生成结果
|
|
1615
|
+
*/
|
|
1616
|
+
get(options?: FingerprintOptions): Promise<FingerprintResult>;
|
|
1617
|
+
/**
|
|
1618
|
+
* 清除当前生成器实例的内存缓存。
|
|
1619
|
+
*
|
|
1620
|
+
* @remarks
|
|
1621
|
+
* 该方法不会清除浏览器存储,因为本模块默认不会写入持久化存储。
|
|
1622
|
+
*/
|
|
1623
|
+
clearCache(): void;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
/**
|
|
1627
|
+
* @fileoverview 隐私友好的浏览器/设备指纹生成器
|
|
1628
|
+
* @module melange/plugins/fingerprint/generator
|
|
1629
|
+
* @description
|
|
1630
|
+
* 参考 FingerprintJS 的组件化指纹模型:采集组件、稳定序列化、计算哈希并
|
|
1631
|
+
* 返回 `visitorId`。与常见高熵指纹方案不同,本实现默认只采集低敏信号,
|
|
1632
|
+
* 并通过分桶、归一化、超时保护和内存缓存降低隐私与性能风险。
|
|
1633
|
+
*/
|
|
1634
|
+
|
|
1635
|
+
/**
|
|
1636
|
+
* 指纹模块版本。
|
|
1637
|
+
*
|
|
1638
|
+
* @description
|
|
1639
|
+
* 版本用于标识当前指纹生成策略。默认采集器、归一化规则或哈希输入结构
|
|
1640
|
+
* 发生不兼容变化时,应同步调整版本。
|
|
1641
|
+
*/
|
|
1642
|
+
declare const FINGERPRINT_VERSION = "1.0.0";
|
|
1643
|
+
/**
|
|
1644
|
+
* 指纹生成器 DI 令牌。
|
|
1645
|
+
*
|
|
1646
|
+
* @description
|
|
1647
|
+
* 用于在 Melange 的 `Container` 中注册和解析 `FingerprintGenerator`。
|
|
1648
|
+
*
|
|
1649
|
+
* @example
|
|
1650
|
+
* ```typescript
|
|
1651
|
+
* registerFingerprintPlugin(container);
|
|
1652
|
+
* const generator = container.resolve<FingerprintGenerator>(FINGERPRINT_GENERATOR);
|
|
1653
|
+
* ```
|
|
1654
|
+
*/
|
|
1655
|
+
declare const FINGERPRINT_GENERATOR: unique symbol;
|
|
1656
|
+
/**
|
|
1657
|
+
* 浏览器/设备指纹生成器实现。
|
|
1658
|
+
*
|
|
1659
|
+
* @description
|
|
1660
|
+
* 生成器持有默认配置和一次内存缓存。它会并发执行内置采集器和自定义采集器,
|
|
1661
|
+
* 对组件结果做稳定序列化后计算 `visitorId`。
|
|
1662
|
+
*
|
|
1663
|
+
* @example
|
|
1664
|
+
* ```typescript
|
|
1665
|
+
* const generator = new FingerprintGeneratorImpl({ salt: 'my-app' });
|
|
1666
|
+
* const result = await generator.get();
|
|
1667
|
+
* ```
|
|
1668
|
+
*/
|
|
1669
|
+
declare class FingerprintGeneratorImpl implements FingerprintGenerator {
|
|
1670
|
+
private readonly baseOptions;
|
|
1671
|
+
/**
|
|
1672
|
+
* 当前生成器实例的内存缓存。
|
|
1673
|
+
*
|
|
1674
|
+
* @remarks
|
|
1675
|
+
* 只缓存最后一次匹配配置的结果,不持久化。
|
|
1676
|
+
*/
|
|
1677
|
+
private cacheEntry;
|
|
1678
|
+
/**
|
|
1679
|
+
* 创建指纹生成器。
|
|
1680
|
+
*
|
|
1681
|
+
* @param baseOptions - 生成器默认配置;后续 `get(options)` 可覆盖这些配置
|
|
1682
|
+
*/
|
|
1683
|
+
constructor(baseOptions?: FingerprintOptions);
|
|
1684
|
+
/**
|
|
1685
|
+
* 获取指纹结果。
|
|
1686
|
+
*
|
|
1687
|
+
* @description
|
|
1688
|
+
* 生成流程:
|
|
1689
|
+
* 1. 合并默认配置和本次调用配置;
|
|
1690
|
+
* 2. 命中内存缓存时直接返回;
|
|
1691
|
+
* 3. 并发采集组件并跳过失败组件;
|
|
1692
|
+
* 4. 稳定序列化组件值并计算哈希;
|
|
1693
|
+
* 5. 返回 visitorId、组件详情、置信度和耗时。
|
|
1694
|
+
*
|
|
1695
|
+
* @param options - 本次生成配置,会覆盖构造函数中的同名默认配置
|
|
1696
|
+
* @returns 指纹生成结果
|
|
1697
|
+
*/
|
|
1698
|
+
get(options?: FingerprintOptions): Promise<FingerprintResult>;
|
|
1699
|
+
/**
|
|
1700
|
+
* 清除内存缓存。
|
|
1701
|
+
*
|
|
1702
|
+
* @description
|
|
1703
|
+
* 下次调用 `get()` 时会重新采集组件。该方法不会清理任何浏览器存储,
|
|
1704
|
+
* 因为本插件默认不会写入持久化存储。
|
|
1705
|
+
*/
|
|
1706
|
+
clearCache(): void;
|
|
1707
|
+
}
|
|
1708
|
+
/**
|
|
1709
|
+
* 创建指纹生成器实例。
|
|
1710
|
+
*
|
|
1711
|
+
* @description
|
|
1712
|
+
* 适合需要多次生成指纹、复用默认配置或通过 DI 管理生命周期的场景。
|
|
1713
|
+
*
|
|
1714
|
+
* @param options - 生成器默认配置
|
|
1715
|
+
* @returns 指纹生成器实例
|
|
1716
|
+
*/
|
|
1717
|
+
declare function createFingerprintGenerator(options?: FingerprintOptions): FingerprintGenerator;
|
|
1718
|
+
/**
|
|
1719
|
+
* 快速获取一次指纹。
|
|
1720
|
+
*
|
|
1721
|
+
* @description
|
|
1722
|
+
* 便捷函数。内部会创建临时生成器并立即调用 `get()`,适合一次性使用。
|
|
1723
|
+
* 如果需要复用缓存,请使用 `createFingerprintGenerator()`。
|
|
1724
|
+
*
|
|
1725
|
+
* @param options - 指纹生成配置
|
|
1726
|
+
* @returns 指纹生成结果
|
|
1727
|
+
*/
|
|
1728
|
+
declare function getFingerprint(options?: FingerprintOptions): Promise<FingerprintResult>;
|
|
1729
|
+
/**
|
|
1730
|
+
* 将指纹生成器注册到依赖注入容器。
|
|
1731
|
+
*
|
|
1732
|
+
* @description
|
|
1733
|
+
* 使用 Melange 的容器将 `FingerprintGenerator` 注册为单例,方便应用服务
|
|
1734
|
+
* 通过 `FINGERPRINT_GENERATOR` 令牌解析。
|
|
1735
|
+
*
|
|
1736
|
+
* @param container - 目标容器;默认使用 `globalContainer`
|
|
1737
|
+
* @param options - 注册到容器中的生成器默认配置
|
|
1738
|
+
* @returns 传入的容器实例,便于链式调用
|
|
1739
|
+
*/
|
|
1740
|
+
declare function registerFingerprintPlugin(container?: Container, options?: FingerprintOptions): Container;
|
|
1741
|
+
/**
|
|
1742
|
+
* 检查当前环境是否具备基础指纹采集能力。
|
|
1743
|
+
*
|
|
1744
|
+
* @description
|
|
1745
|
+
* 只要存在 `navigator` 或 `screen`,就认为具备基础采集能力。Node 环境通常
|
|
1746
|
+
* 返回 false,测试或 SSR 场景可据此跳过浏览器相关逻辑。
|
|
1747
|
+
*
|
|
1748
|
+
* @returns 当前环境是否支持基础指纹采集
|
|
1749
|
+
*/
|
|
1750
|
+
declare function isFingerprintSupported(): boolean;
|
|
1751
|
+
|
|
1752
|
+
export { type AzureSpeechConfig as $, AzureSynthesisAdapter as A, BaiduSynthesisAdapter as B, type SpeechProviderType as C, type SpeechServiceStatus as D, type SpeechError as E, FingerprintGeneratorImpl as F, GenericSynthesisAdapter as G, type BaseSpeechConfig as H, type SynthesisConfig as I, type SynthesisEventType as J, type SynthesisEvent as K, type SynthesisEventHandler as L, type SynthesisProvider as M, type SpeechSynthesizer as N, type RecognitionResultItem as O, type RecognitionResult as P, type RecognitionConfig as Q, RecognitionStatus as R, SynthesisStatus as S, TencentSynthesisAdapter as T, type RecognitionEventType as U, type VoiceInfo as V, type RecognitionEvent as W, XunfeiSynthesisAdapter as X, type RecognitionEventHandler as Y, type RecognitionProvider as Z, type SpeechRecognizer as _, SynthesisAudioUtils as a, type GoogleSpeechConfig as a0, type AWSSpeechConfig as a1, type CustomProviderConfig as a2, type ProviderConfig as a3, type SynthesisEngineMode as a4, type CloudAudioFormat as a5, type ISynthesisResult as a6, type ISynthesisError as a7, type ICloudVoice as a8, type IAdvancedSynthesisConfig as a9, type ICloudSynthesisAdapter as aa, type RecognitionEngineMode as ab, type CloudTransportType as ac, type IRecognitionResult as ad, type IRecognitionError as ae, type IAudioConfig as af, type IAdvancedRecognitionConfig as ag, type ICloudRecognitionAdapter as ah, type FingerprintComponentKey as ai, type FingerprintComponentSource as aj, type FingerprintPrivacyMode as ak, type FingerprintHashAlgorithm as al, type FingerprintValue as am, type FingerprintComponent as an, type FingerprintComponentMap as ao, type FingerprintConfidence as ap, type FingerprintResult as aq, type FingerprintCollectorContext as ar, type FingerprintCollector as as, type FingerprintOptions as at, type FingerprintGenerator as au, FINGERPRINT_VERSION as av, FINGERPRINT_GENERATOR as aw, GoogleSynthesisAdapter as b, AWSSynthesisAdapter as c, AlibabaSynthesisAdapter as d, SpeechSynthesizerImpl as e, createSpeechSynthesizer as f, speakWithCloud as g, SpeechRecognizerImpl as h, isSpeechSynthesisSupported as i, createSpeechRecognizer as j, isSpeechRecognitionSupported as k, listen as l, listenWithTimeout as m, AudioUtils as n, GenericAdapter as o, XunfeiAdapter as p, TencentAdapter as q, BaiduAdapter as r, speak as s, AlibabaAdapter as t, GoogleAdapter as u, AzureAdapter as v, createFingerprintGenerator as w, getFingerprint as x, registerFingerprintPlugin as y, isFingerprintSupported as z };
|