@lee-zg/melange 1.0.0 → 1.2.0

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.
Files changed (39) hide show
  1. package/dist/chunk-3RM45M64.js +1637 -0
  2. package/dist/chunk-3RM45M64.js.map +1 -0
  3. package/dist/{chunk-ALBD5XC5.js → chunk-GXFWPL5M.js} +4 -8
  4. package/dist/chunk-GXFWPL5M.js.map +1 -0
  5. package/dist/{chunk-Q73NOVWX.cjs → chunk-KUJARU3D.cjs} +7 -24
  6. package/dist/chunk-KUJARU3D.cjs.map +1 -0
  7. package/dist/{chunk-2PXWQDZC.js → chunk-MBBJMHTS.js} +3 -5
  8. package/dist/chunk-MBBJMHTS.js.map +1 -0
  9. package/dist/{chunk-ZT6HVG4G.cjs → chunk-UYJUSNDI.cjs} +4 -8
  10. package/dist/chunk-UYJUSNDI.cjs.map +1 -0
  11. package/dist/{chunk-Q7XG6YN6.cjs → chunk-V5THPEB2.cjs} +3 -5
  12. package/dist/chunk-V5THPEB2.cjs.map +1 -0
  13. package/dist/{chunk-352XNR3C.js → chunk-VGZMISJD.js} +7 -24
  14. package/dist/chunk-VGZMISJD.js.map +1 -0
  15. package/dist/chunk-YZVCK6VZ.cjs +1646 -0
  16. package/dist/chunk-YZVCK6VZ.cjs.map +1 -0
  17. package/dist/core/index.cjs +23 -23
  18. package/dist/core/index.js +1 -1
  19. package/dist/fp/index.cjs +45 -45
  20. package/dist/fp/index.js +1 -1
  21. package/dist/index.cjs +147 -147
  22. package/dist/index.js +4 -4
  23. package/dist/plugins/index.cjs +9 -9
  24. package/dist/plugins/index.d.cts +287 -133
  25. package/dist/plugins/index.d.ts +287 -133
  26. package/dist/plugins/index.js +1 -1
  27. package/dist/utils/index.cjs +73 -73
  28. package/dist/utils/index.js +1 -1
  29. package/package.json +5 -2
  30. package/dist/chunk-2PXWQDZC.js.map +0 -1
  31. package/dist/chunk-352XNR3C.js.map +0 -1
  32. package/dist/chunk-ALBD5XC5.js.map +0 -1
  33. package/dist/chunk-O7K662J5.cjs +0 -842
  34. package/dist/chunk-O7K662J5.cjs.map +0 -1
  35. package/dist/chunk-Q73NOVWX.cjs.map +0 -1
  36. package/dist/chunk-Q7XG6YN6.cjs.map +0 -1
  37. package/dist/chunk-YGMBCZJQ.js +0 -833
  38. package/dist/chunk-YGMBCZJQ.js.map +0 -1
  39. package/dist/chunk-ZT6HVG4G.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugins/speech/synthesis.ts","../src/plugins/speech/recognition.ts"],"names":["__name"],"mappings":"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","file":"chunk-YZVCK6VZ.cjs","sourcesContent":["/**\n * @fileoverview 语音合成 (TTS) 实现 - 商业级版本 v2.0\n * @module melange/plugins/speech/synthesis\n * @description 生产级 Web 语音合成插件\n *\n * 架构:\n * [UI层] -> [SpeechSynthesizerImpl] -> [NativeStrategy / CloudStrategy]\n * |\n * +-> [音频核心]: AudioContext, 流式播放\n * +-> [适配器]: AzureAdapter, GoogleAdapter, TencentAdapter...\n *\n * 功能特性:\n * 1. 多模式: 支持原生 Web Speech API & 云端 TTS 服务\n * 2. 状态机: IDLE -> LOADING -> SPEAKING -> PAUSED\n * 3. 插件化: 内置 Azure/Google/AWS/讯飞/腾讯/百度/阿里 适配器\n * 4. 核心: AudioContext 流式播放 + 音频队列管理\n * 5. 兼容性: 多浏览器支持 + 自动降级处理\n */\n\nimport type {\n SpeechProviderType,\n SpeechServiceStatus,\n VoiceInfo,\n SynthesisConfig,\n SynthesisEventType,\n SynthesisEvent,\n SynthesisEventHandler,\n SynthesisProvider,\n SpeechSynthesizer,\n} from './types';\n\n// ============================================================================\n// 1. 类型定义 & 枚举\n// ============================================================================\n\n/**\n * 合成器状态枚举\n */\nexport enum SynthesisStatus {\n /** 空闲状态 */\n IDLE = 'IDLE',\n /** 加载中(获取语音/准备中) */\n LOADING = 'LOADING',\n /** 正在播放 */\n SPEAKING = 'SPEAKING',\n /** 已暂停 */\n PAUSED = 'PAUSED',\n}\n\n/**\n * 合成引擎模式\n */\nexport type SynthesisEngineMode = 'native' | 'cloud' | 'auto';\n\n/**\n * 云端 TTS 音频格式\n */\nexport type CloudAudioFormat = 'mp3' | 'wav' | 'ogg' | 'pcm';\n\n/**\n * 云端合成结果接口\n */\nexport interface ISynthesisResult {\n /** 音频数据 */\n audioData: ArrayBuffer;\n /** 音频格式 */\n format: CloudAudioFormat;\n /** 音频时长 (ms) */\n duration?: number;\n /** 原始响应数据 */\n original?: unknown;\n}\n\n/**\n * 合成错误接口\n */\nexport interface ISynthesisError {\n /** 错误代码 */\n code:\n | 'NETWORK'\n | 'NOT_SUPPORTED'\n | 'INVALID_TEXT'\n | 'ADAPTER_ERROR'\n | 'PLAYBACK_ERROR'\n | 'UNKNOWN';\n /** 错误信息 */\n message: string;\n /** 原始错误 */\n originalError?: unknown;\n}\n\n/**\n * 云端语音信息\n */\nexport interface ICloudVoice {\n /** 语音 ID */\n id: string;\n /** 语音名称 */\n name: string;\n /** 语言代码 */\n lang: string;\n /** 性别 */\n gender?: 'male' | 'female' | 'neutral';\n /** 提供商名称 */\n provider: string;\n}\n\n/**\n * 高级合成配置\n */\nexport interface IAdvancedSynthesisConfig extends SynthesisConfig {\n /** 合成引擎模式 */\n mode?: SynthesisEngineMode;\n /** 云端适配器 */\n cloudAdapter?: ICloudSynthesisAdapter;\n /** 音频格式偏好 */\n audioFormat?: CloudAudioFormat;\n /** 是否启用 SSML */\n enableSSML?: boolean;\n /** 是否预加载音频 */\n preload?: boolean;\n /** 音频缓存大小 */\n cacheSize?: number;\n}\n\n// ============================================================================\n// 2. 云端合成适配器接口\n// ============================================================================\n\n/**\n * 云端合成适配器接口\n * 提供统一的第三方语音合成服务集成接口\n */\nexport interface ICloudSynthesisAdapter {\n /** 适配器名称 */\n readonly name: string;\n\n /**\n * 合成语音\n * @param text 要合成的文本\n * @param config 合成配置\n * @returns 合成结果(音频数据)\n */\n synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult>;\n\n /**\n * 获取可用语音列表\n * @returns 语音列表\n */\n getVoices?(): Promise<ICloudVoice[]>;\n\n /**\n * 检查适配器是否可用\n * @returns 是否可用\n */\n isAvailable?(): boolean;\n}\n\n// ============================================================================\n// 3. 音频播放工具类\n// ============================================================================\n\n/**\n * 音频播放工具集\n */\nexport const SynthesisAudioUtils = {\n /**\n * 创建 AudioContext\n */\n createAudioContext(): AudioContext {\n const AudioCtor =\n typeof window !== 'undefined'\n ? window.AudioContext ||\n (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext\n : null;\n if (!AudioCtor) {\n throw new Error('浏览器不支持 AudioContext');\n }\n return new AudioCtor();\n },\n\n /**\n * ArrayBuffer 转 Base64\n */\n arrayBufferToBase64(buffer: ArrayBuffer): string {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i] ?? 0);\n }\n return typeof btoa !== 'undefined' ? btoa(binary) : Buffer.from(binary).toString('base64');\n },\n\n /**\n * Base64 转 ArrayBuffer\n */\n base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary =\n typeof atob !== 'undefined' ? atob(base64) : Buffer.from(base64, 'base64').toString('binary');\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n },\n\n /**\n * 计算音频时长(粗略估算)\n */\n estimateDuration(byteLength: number, format: CloudAudioFormat): number {\n const bitRates: Record<CloudAudioFormat, number> = {\n mp3: 128000, // 128 kbps\n wav: 256000, // 16bit 16kHz mono\n ogg: 96000, // 96 kbps\n pcm: 256000, // 16bit 16kHz mono\n };\n return Math.ceil(((byteLength * 8) / bitRates[format]) * 1000);\n },\n};\n\n// ============================================================================\n// 4. 内置云端适配器实现\n// ============================================================================\n\n/**\n * 通用适配器 (BFF 模式 - 推荐)\n * 适用于自建后端代理场景\n */\nexport class GenericSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Generic/BFF';\n\n constructor(private baseUrl: string) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const response = await fetch(`${this.baseUrl}/synthesize`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n lang: config?.lang ?? 'zh-CN',\n voice: typeof config?.voice === 'string' ? config.voice : config?.voice?.id,\n rate: config?.rate ?? 1.0,\n pitch: config?.pitch ?? 1.0,\n volume: config?.volume ?? 1.0,\n format: config?.audioFormat ?? 'mp3',\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const audioData = await response.arrayBuffer();\n return {\n audioData,\n format: config?.audioFormat ?? 'mp3',\n duration: SynthesisAudioUtils.estimateDuration(\n audioData.byteLength,\n config?.audioFormat ?? 'mp3'\n ),\n };\n }\n\n async getVoices(): Promise<ICloudVoice[]> {\n try {\n const response = await fetch(`${this.baseUrl}/voices`);\n if (!response.ok) return [];\n const data = (await response.json()) as { voices?: ICloudVoice[] };\n return data.voices ?? [];\n } catch {\n return [];\n }\n }\n}\n\n/**\n * Azure 语音服务适配器\n */\nexport class AzureSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Azure';\n\n constructor(\n private subscriptionKey: string,\n private region: string,\n private defaultVoice: string = 'zh-CN-XiaoxiaoNeural'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n const rate = config?.rate ?? 1.0;\n const pitch = config?.pitch ?? 1.0;\n\n // 构建 SSML\n const ssml = `\n<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"${config?.lang ?? 'zh-CN'}\">\n <voice name=\"${voice}\">\n <prosody rate=\"${rate}\" pitch=\"${(pitch - 1) * 50}%\">\n ${this.escapeXml(text)}\n </prosody>\n </voice>\n</speak>`;\n\n const response = await fetch(\n `https://${this.region}.tts.speech.microsoft.com/cognitiveservices/v1`,\n {\n method: 'POST',\n headers: {\n 'Ocp-Apim-Subscription-Key': this.subscriptionKey,\n 'Content-Type': 'application/ssml+xml',\n 'X-Microsoft-OutputFormat': 'audio-16khz-128kbitrate-mono-mp3',\n },\n body: ssml,\n }\n );\n\n if (!response.ok) {\n throw new Error(`Azure TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n async getVoices(): Promise<ICloudVoice[]> {\n const response = await fetch(\n `https://${this.region}.tts.speech.microsoft.com/cognitiveservices/voices/list`,\n {\n headers: { 'Ocp-Apim-Subscription-Key': this.subscriptionKey },\n }\n );\n\n if (!response.ok) return [];\n\n const voices = (await response.json()) as Array<{\n ShortName: string;\n DisplayName: string;\n Locale: string;\n Gender: string;\n }>;\n\n return voices.map(v => ({\n id: v.ShortName,\n name: v.DisplayName,\n lang: v.Locale,\n gender: v.Gender.toLowerCase() as 'male' | 'female' | 'neutral',\n provider: 'Azure',\n }));\n }\n\n private escapeXml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n }\n}\n\n/**\n * Google Cloud TTS 适配器\n */\nexport class GoogleSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Google';\n\n constructor(\n private apiKey: string,\n private defaultVoice: string = 'zh-CN-Wavenet-A'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n const lang = config?.lang ?? 'zh-CN';\n\n const payload = {\n input: config?.enableSSML ? { ssml: text } : { text },\n voice: {\n languageCode: lang,\n name: voice,\n },\n audioConfig: {\n audioEncoding: 'MP3',\n speakingRate: config?.rate ?? 1.0,\n pitch: config?.pitch ?? 0,\n volumeGainDb: ((config?.volume ?? 1.0) - 1) * 10,\n },\n };\n\n const response = await fetch(\n `https://texttospeech.googleapis.com/v1/text:synthesize?key=${this.apiKey}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n }\n );\n\n if (!response.ok) {\n const error = (await response.json()) as { error?: { message?: string } };\n throw new Error(error.error?.message ?? 'Google TTS Error');\n }\n\n const data = (await response.json()) as { audioContent: string };\n const audioData = SynthesisAudioUtils.base64ToArrayBuffer(data.audioContent);\n return { audioData, format: 'mp3' };\n }\n\n async getVoices(): Promise<ICloudVoice[]> {\n const response = await fetch(\n `https://texttospeech.googleapis.com/v1/voices?key=${this.apiKey}`\n );\n\n if (!response.ok) return [];\n\n const data = (await response.json()) as {\n voices: Array<{\n name: string;\n languageCodes: string[];\n ssmlGender: string;\n }>;\n };\n\n return data.voices.map(v => ({\n id: v.name,\n name: v.name,\n lang: v.languageCodes[0] ?? 'en-US',\n gender: v.ssmlGender.toLowerCase() as 'male' | 'female' | 'neutral',\n provider: 'Google',\n }));\n }\n}\n\n/**\n * AWS Polly 适配器\n */\nexport class AWSSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'AWS';\n\n constructor(\n private accessKeyId: string,\n private secretAccessKey: string,\n private region: string,\n private defaultVoice: string = 'Zhiyu'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n // AWS Polly 需要签名,建议通过 BFF 代理\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // 简化示例,生产环境建议通过后端代理\n const response = await fetch('/api/aws-polly/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n voiceId: voice,\n languageCode: config?.lang ?? 'cmn-CN',\n outputFormat: 'mp3',\n accessKeyId: this.accessKeyId,\n secretAccessKey: this.secretAccessKey,\n region: this.region,\n }),\n });\n\n if (!response.ok) {\n throw new Error(`AWS Polly Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n // 返回部分常用中文语音\n return Promise.resolve([\n { id: 'Zhiyu', name: '智瑜', lang: 'cmn-CN', gender: 'female', provider: 'AWS' },\n ]);\n }\n}\n\n/**\n * 讯飞云适配器\n */\nexport class XunfeiSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Xunfei';\n\n // Note: apiKey and apiSecret are reserved for future direct API authentication\n // Currently using BFF proxy mode which handles auth server-side\n constructor(\n private appId: string,\n _apiKey?: string,\n _apiSecret?: string,\n private defaultVoice: string = 'xiaoyan'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // 讯飞 WebAPI 需要鉴权,建议通过 BFF 代理\n const response = await fetch('/api/xunfei-tts/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n appId: this.appId,\n vcn: voice,\n speed: Math.round((config?.rate ?? 1.0) * 50),\n pitch: Math.round((config?.pitch ?? 1.0) * 50),\n volume: Math.round((config?.volume ?? 1.0) * 100),\n aue: 'lame', // mp3\n }),\n });\n\n if (!response.ok) {\n throw new Error(`讯飞 TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: 'xiaoyan', name: '小燕', lang: 'zh-CN', gender: 'female', provider: 'Xunfei' },\n { id: 'aisjiuxu', name: '许久', lang: 'zh-CN', gender: 'male', provider: 'Xunfei' },\n { id: 'aisxping', name: '小萍', lang: 'zh-CN', gender: 'female', provider: 'Xunfei' },\n { id: 'aisjinger', name: '小婧', lang: 'zh-CN', gender: 'female', provider: 'Xunfei' },\n ]);\n }\n}\n\n/**\n * 腾讯云适配器\n */\nexport class TencentSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Tencent';\n\n constructor(\n private secretId: string,\n private secretKey: string,\n private defaultVoice: string = '101001'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // TC3-HMAC-SHA256 签名应在后端完成\n const response = await fetch('/api/tencent-tts/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n text,\n secretId: this.secretId,\n secretKey: this.secretKey,\n voiceType: Number(voice),\n speed: config?.rate ?? 1.0,\n volume: config?.volume ?? 0,\n codec: 'mp3',\n }),\n });\n\n if (!response.ok) {\n throw new Error(`腾讯云 TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: '101001', name: '智瑜', lang: 'zh-CN', gender: 'female', provider: 'Tencent' },\n { id: '101002', name: '智聆', lang: 'zh-CN', gender: 'male', provider: 'Tencent' },\n { id: '101003', name: '智美', lang: 'zh-CN', gender: 'female', provider: 'Tencent' },\n ]);\n }\n}\n\n/**\n * 百度云适配器\n */\nexport class BaiduSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Baidu';\n\n constructor(\n private accessToken: string,\n private defaultVoice: string = '0'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n const params = new URLSearchParams({\n tex: encodeURIComponent(text),\n tok: this.accessToken,\n cuid: `sdk-user-${Date.now()}`,\n ctp: '1',\n lan: config?.lang === 'en-US' ? 'en' : 'zh',\n spd: String(Math.round((config?.rate ?? 1.0) * 5)),\n pit: String(Math.round((config?.pitch ?? 1.0) * 5)),\n vol: String(Math.round((config?.volume ?? 1.0) * 15)),\n per: voice,\n aue: '3', // mp3\n });\n\n // 建议通过 BFF 代理调用,避免 CORS 问题\n const response = await fetch('/api/baidu-tts/synthesize', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: params.toString(),\n });\n\n const contentType = response.headers.get('Content-Type') ?? '';\n if (contentType.includes('audio')) {\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n // 错误响应是 JSON\n const error = (await response.json()) as { err_msg?: string };\n throw new Error(error.err_msg ?? '百度 TTS Error');\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: '0', name: '度小美', lang: 'zh-CN', gender: 'female', provider: 'Baidu' },\n { id: '1', name: '度小宇', lang: 'zh-CN', gender: 'male', provider: 'Baidu' },\n { id: '3', name: '度逍遥', lang: 'zh-CN', gender: 'male', provider: 'Baidu' },\n { id: '4', name: '度丫丫', lang: 'zh-CN', gender: 'female', provider: 'Baidu' },\n ]);\n }\n}\n\n/**\n * 阿里云适配器\n */\nexport class AlibabaSynthesisAdapter implements ICloudSynthesisAdapter {\n readonly name = 'Alibaba';\n\n // Note: accessKeySecret is reserved for future direct API authentication\n // Currently using BFF proxy mode which handles auth server-side\n constructor(\n private accessKeyId: string,\n _accessKeySecret: string,\n private appKey: string,\n private defaultVoice: string = 'xiaoyun'\n ) {}\n\n async synthesize(text: string, config?: IAdvancedSynthesisConfig): Promise<ISynthesisResult> {\n const voice =\n typeof config?.voice === 'string' ? config.voice : (config?.voice?.id ?? this.defaultVoice);\n\n // 建议通过 BFF 代理调用\n const response = await fetch('/api/alibaba-tts/synthesize', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-NLS-Token': this.accessKeyId,\n },\n body: JSON.stringify({\n appkey: this.appKey,\n text,\n format: 'mp3',\n voice,\n sample_rate: 16000,\n speech_rate: Math.round((config?.rate ?? 1.0 - 1) * 500),\n pitch_rate: Math.round((config?.pitch ?? 1.0 - 1) * 500),\n volume: Math.round((config?.volume ?? 1.0) * 100),\n }),\n });\n\n if (!response.ok) {\n throw new Error(`阿里云 TTS Error: ${response.status}`);\n }\n\n const audioData = await response.arrayBuffer();\n return { audioData, format: 'mp3' };\n }\n\n getVoices(): Promise<ICloudVoice[]> {\n return Promise.resolve([\n { id: 'xiaoyun', name: '小云', lang: 'zh-CN', gender: 'female', provider: 'Alibaba' },\n { id: 'xiaogang', name: '小刚', lang: 'zh-CN', gender: 'male', provider: 'Alibaba' },\n { id: 'ruoxi', name: '若兮', lang: 'zh-CN', gender: 'female', provider: 'Alibaba' },\n { id: 'siqi', name: '思琪', lang: 'zh-CN', gender: 'female', provider: 'Alibaba' },\n ]);\n }\n}\n\n// ============================================================================\n// 5. 抽象策略基类\n// ============================================================================\n\n/**\n * 事件监听器类型定义\n */\ntype SynthesisEventListeners = {\n start: Array<() => void>;\n end: Array<() => void>;\n pause: Array<() => void>;\n resume: Array<() => void>;\n boundary: Array<\n (data: { charIndex?: number; charLength?: number; elapsedTime?: number; name?: string }) => void\n >;\n mark: Array<(data: { name?: string }) => void>;\n error: Array<(err: ISynthesisError) => void>;\n state: Array<(status: SynthesisStatus) => void>;\n};\n\n/**\n * 合成策略基类\n */\nabstract class BaseSynthesisStrategy {\n protected listeners: SynthesisEventListeners = {\n start: [],\n end: [],\n pause: [],\n resume: [],\n boundary: [],\n mark: [],\n error: [],\n state: [],\n };\n\n protected _status: SynthesisStatus = SynthesisStatus.IDLE;\n\n constructor(protected config: IAdvancedSynthesisConfig) {}\n\n /**\n * 获取当前状态\n */\n get status(): SynthesisStatus {\n return this._status;\n }\n\n /**\n * 朗读文本\n */\n abstract speak(text: string, config?: SynthesisConfig): Promise<void>;\n\n /**\n * 暂停\n */\n abstract pause(): void;\n\n /**\n * 继续\n */\n abstract resume(): void;\n\n /**\n * 取消\n */\n abstract cancel(): void;\n\n /**\n * 是否正在朗读\n */\n abstract isSpeaking(): boolean;\n\n /**\n * 是否已暂停\n */\n abstract isPaused(): boolean;\n\n /**\n * 获取可用语音\n */\n abstract getVoices(): Promise<VoiceInfo[]>;\n\n /**\n * 检查是否可用\n */\n abstract isAvailable(): boolean;\n\n /**\n * 设置状态\n */\n protected setStatus(status: SynthesisStatus): void {\n if (this._status !== status) {\n this._status = status;\n this.emit('state', status);\n }\n }\n\n /**\n * 添加事件监听\n */\n on<K extends keyof SynthesisEventListeners>(\n event: K,\n fn: SynthesisEventListeners[K][number]\n ): void {\n (this.listeners[event] as Array<typeof fn>).push(fn);\n }\n\n /**\n * 移除事件监听\n */\n off<K extends keyof SynthesisEventListeners>(\n event: K,\n fn: SynthesisEventListeners[K][number]\n ): void {\n const listeners = this.listeners[event] as Array<typeof fn>;\n const index = listeners.indexOf(fn);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n }\n\n /**\n * 触发事件\n */\n protected emit<K extends keyof SynthesisEventListeners>(\n event: K,\n data?: Parameters<SynthesisEventListeners[K][number]>[0]\n ): void {\n const listeners = this.listeners[event] as Array<(arg?: typeof data) => void>;\n listeners.forEach(fn => {\n try {\n fn(data);\n } catch (e) {\n console.error(`[Synthesis] 事件处理器错误 (${event}):`, e);\n }\n });\n }\n\n /**\n * 销毁资源\n */\n dispose(): void {\n this.cancel();\n Object.keys(this.listeners).forEach(key => {\n (this.listeners as Record<string, unknown[]>)[key] = [];\n });\n }\n}\n\n// ============================================================================\n// 6. 原生合成策略\n// ============================================================================\n\n/**\n * 浏览器原生语音合成策略\n * 使用 Web Speech API SpeechSynthesis\n */\nclass NativeSynthesisStrategy extends BaseSynthesisStrategy {\n private synthesis: SpeechSynthesis | null = null;\n // Internal state tracking for current utterance (write-only, used for GC reference)\n private currentUtterance: SpeechSynthesisUtterance | null = null;\n private voicesLoaded: boolean = false;\n private voicesPromise: Promise<VoiceInfo[]> | null = null;\n\n constructor(config: IAdvancedSynthesisConfig) {\n super(config);\n if (this.isAvailable()) {\n this.synthesis = window.speechSynthesis;\n }\n }\n\n isAvailable(): boolean {\n return typeof window !== 'undefined' && 'speechSynthesis' in window;\n }\n\n async getVoices(): Promise<VoiceInfo[]> {\n if (!this.synthesis) return [];\n\n if (this.voicesPromise) {\n return this.voicesPromise;\n }\n\n this.voicesPromise = new Promise(resolve => {\n const loadVoices = () => {\n const voices = this.synthesis!.getVoices();\n if (voices.length > 0) {\n this.voicesLoaded = true;\n resolve(\n voices.map(voice => ({\n id: voice.voiceURI,\n name: voice.name,\n lang: voice.lang,\n localService: voice.localService,\n default: voice.default,\n provider: 'browser' as SpeechProviderType,\n }))\n );\n }\n };\n\n loadVoices();\n\n if (!this.voicesLoaded) {\n this.synthesis!.addEventListener('voiceschanged', loadVoices, { once: true });\n setTimeout(() => {\n if (!this.voicesLoaded) {\n resolve([]);\n }\n }, 3000);\n }\n });\n\n return this.voicesPromise;\n }\n\n async speak(text: string, config?: SynthesisConfig): Promise<void> {\n if (!this.synthesis) {\n throw { code: 'NOT_SUPPORTED', message: '浏览器不支持语音合成' };\n }\n\n // 取消当前朗读\n this.cancel();\n\n this.setStatus(SynthesisStatus.LOADING);\n\n return new Promise((resolve, reject) => {\n const mergedConfig = { ...this.config, ...config };\n const utterance = new SpeechSynthesisUtterance(text);\n this.currentUtterance = utterance;\n\n // 应用配置\n if (mergedConfig.lang) utterance.lang = mergedConfig.lang;\n if (mergedConfig.volume !== undefined) utterance.volume = mergedConfig.volume;\n if (mergedConfig.rate !== undefined) utterance.rate = mergedConfig.rate;\n if (mergedConfig.pitch !== undefined) utterance.pitch = mergedConfig.pitch;\n\n // 设置语音\n if (mergedConfig.voice) {\n const voices = this.synthesis!.getVoices();\n const voiceConfig = mergedConfig.voice;\n const targetVoice =\n typeof voiceConfig === 'string'\n ? voices.find(v => v.name === voiceConfig || v.voiceURI === voiceConfig)\n : voices.find(v => v.voiceURI === voiceConfig.id);\n if (targetVoice) {\n utterance.voice = targetVoice;\n }\n }\n\n // 事件处理\n utterance.onstart = () => {\n this.setStatus(SynthesisStatus.SPEAKING);\n this.emit('start');\n };\n\n utterance.onend = () => {\n this.setStatus(SynthesisStatus.IDLE);\n this.currentUtterance = null;\n this.emit('end');\n resolve();\n };\n\n utterance.onpause = () => {\n this.setStatus(SynthesisStatus.PAUSED);\n this.emit('pause');\n };\n\n utterance.onresume = () => {\n this.setStatus(SynthesisStatus.SPEAKING);\n this.emit('resume');\n };\n\n utterance.onboundary = event => {\n this.emit('boundary', {\n charIndex: event.charIndex,\n charLength: event.charLength,\n elapsedTime: event.elapsedTime,\n name: event.name,\n });\n };\n\n utterance.onmark = event => {\n this.emit('mark', { name: event.name });\n };\n\n utterance.onerror = event => {\n this.setStatus(SynthesisStatus.IDLE);\n this.currentUtterance = null;\n const error: ISynthesisError = {\n code: 'UNKNOWN',\n message: `语音合成错误: ${event.error}`,\n originalError: event,\n };\n this.emit('error', error);\n reject(error);\n };\n\n this.synthesis!.speak(utterance);\n });\n }\n\n pause(): void {\n if (this.synthesis && this.isSpeaking()) {\n this.synthesis.pause();\n }\n }\n\n resume(): void {\n if (this.synthesis && this.isPaused()) {\n this.synthesis.resume();\n }\n }\n\n cancel(): void {\n if (this.synthesis) {\n this.synthesis.cancel();\n this.currentUtterance = null;\n this.setStatus(SynthesisStatus.IDLE);\n }\n }\n\n isSpeaking(): boolean {\n return this.currentUtterance !== null && (this.synthesis?.speaking ?? false);\n }\n\n isPaused(): boolean {\n return this.synthesis?.paused ?? false;\n }\n}\n\n// ============================================================================\n// 7. 云端合成策略\n// ============================================================================\n\n/**\n * 云端语音合成策略\n * 支持多种第三方 TTS 服务\n */\nclass CloudSynthesisStrategy extends BaseSynthesisStrategy {\n private adapter: ICloudSynthesisAdapter;\n private audioContext: AudioContext | null = null;\n private sourceNode: AudioBufferSourceNode | null = null;\n private gainNode: GainNode | null = null;\n private startTime: number = 0;\n private pauseTime: number = 0;\n private audioBuffer: AudioBuffer | null = null;\n\n constructor(config: IAdvancedSynthesisConfig) {\n super(config);\n if (!config.cloudAdapter) {\n throw new Error('[CloudStrategy] 需要提供 cloudAdapter');\n }\n this.adapter = config.cloudAdapter;\n }\n\n isAvailable(): boolean {\n return typeof window !== 'undefined' && 'AudioContext' in window;\n }\n\n async getVoices(): Promise<VoiceInfo[]> {\n if (!this.adapter.getVoices) return [];\n\n try {\n const cloudVoices = await this.adapter.getVoices();\n return cloudVoices.map(v => ({\n id: v.id,\n name: v.name,\n lang: v.lang,\n localService: false,\n default: false,\n provider: 'custom' as SpeechProviderType,\n }));\n } catch {\n return [];\n }\n }\n\n async speak(text: string, config?: SynthesisConfig): Promise<void> {\n if (!text.trim()) {\n throw { code: 'INVALID_TEXT', message: '文本内容为空' } as ISynthesisError;\n }\n\n // 取消当前播放\n this.cancel();\n\n const mergedConfig = { ...this.config, ...config } as IAdvancedSynthesisConfig;\n this.setStatus(SynthesisStatus.LOADING);\n\n try {\n // 1. 调用适配器合成音频\n this.emit('start');\n const result = await this.adapter.synthesize(text, mergedConfig);\n\n // 2. 初始化音频上下文\n if (!this.audioContext) {\n this.audioContext = SynthesisAudioUtils.createAudioContext();\n }\n\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume();\n }\n\n // 3. 解码音频\n this.audioBuffer = await this.audioContext.decodeAudioData(result.audioData.slice(0));\n\n // 4. 播放\n await this.playBuffer();\n } catch (e: unknown) {\n const error = e as Error;\n this.setStatus(SynthesisStatus.IDLE);\n const synthError: ISynthesisError = {\n code: 'ADAPTER_ERROR',\n message: error.message || '合成失败',\n originalError: e,\n };\n this.emit('error', synthError);\n throw synthError;\n }\n }\n\n private async playBuffer(): Promise<void> {\n if (!this.audioContext || !this.audioBuffer) return;\n\n return new Promise((resolve, reject) => {\n try {\n // 创建节点\n this.sourceNode = this.audioContext!.createBufferSource();\n this.sourceNode.buffer = this.audioBuffer;\n\n this.gainNode = this.audioContext!.createGain();\n this.gainNode.gain.value = this.config.volume ?? 1.0;\n\n // 连接节点\n this.sourceNode.connect(this.gainNode);\n this.gainNode.connect(this.audioContext!.destination);\n\n // 播放结束处理\n this.sourceNode.onended = () => {\n if (this._status === SynthesisStatus.SPEAKING) {\n this.setStatus(SynthesisStatus.IDLE);\n this.emit('end');\n resolve();\n }\n };\n\n // 开始播放\n const offset = this.pauseTime > 0 ? this.pauseTime : 0;\n this.sourceNode.start(0, offset);\n this.startTime = this.audioContext!.currentTime - offset;\n this.pauseTime = 0;\n this.setStatus(SynthesisStatus.SPEAKING);\n } catch (e) {\n reject(e);\n }\n });\n }\n\n pause(): void {\n if (this._status === SynthesisStatus.SPEAKING && this.audioContext && this.sourceNode) {\n this.pauseTime = this.audioContext.currentTime - this.startTime;\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n this.sourceNode = null;\n this.setStatus(SynthesisStatus.PAUSED);\n this.emit('pause');\n }\n }\n\n resume(): void {\n if (this._status === SynthesisStatus.PAUSED && this.audioBuffer) {\n this.emit('resume');\n void this.playBuffer();\n }\n }\n\n cancel(): void {\n if (this.sourceNode) {\n try {\n this.sourceNode.stop();\n this.sourceNode.disconnect();\n } catch {\n // ignore\n }\n this.sourceNode = null;\n }\n\n this.audioBuffer = null;\n this.pauseTime = 0;\n this.startTime = 0;\n this.setStatus(SynthesisStatus.IDLE);\n }\n\n isSpeaking(): boolean {\n return this._status === SynthesisStatus.SPEAKING;\n }\n\n isPaused(): boolean {\n return this._status === SynthesisStatus.PAUSED;\n }\n\n override dispose(): void {\n super.dispose();\n this.cancel();\n if (this.audioContext) {\n void this.audioContext.close();\n this.audioContext = null;\n }\n }\n}\n\n// ============================================================================\n// 8. 主入口类 (Facade)\n// ============================================================================\n\n/**\n * 语音合成器实现\n * 统一封装原生合成和云端合成\n */\nexport class SpeechSynthesizerImpl implements SpeechSynthesizer {\n private strategy: BaseSynthesisStrategy | null = null;\n private config: IAdvancedSynthesisConfig = {};\n private _currentProvider: SpeechProviderType = 'browser';\n private _status: SpeechServiceStatus = 'idle';\n private eventHandlers: Map<SynthesisEventType, Set<SynthesisEventHandler>> = new Map();\n private customProviders: Map<SpeechProviderType, SynthesisProvider> = new Map();\n\n get currentProvider(): SpeechProviderType {\n return this._currentProvider;\n }\n\n get status(): SpeechServiceStatus {\n return this._status;\n }\n\n /**\n * 获取当前合成状态\n */\n get synthesisStatus(): SynthesisStatus {\n return this.strategy?.status ?? SynthesisStatus.IDLE;\n }\n\n /**\n * 初始化语音合成器\n */\n initialize(config?: SynthesisConfig): Promise<void> {\n this._status = 'loading';\n\n // 合并配置\n this.config = {\n lang: 'zh-CN',\n volume: 1.0,\n rate: 1.0,\n pitch: 1.0,\n preferredProvider: 'browser',\n autoFallback: true,\n fallbackProviders: ['azure', 'google', 'aws'],\n mode: 'auto',\n audioFormat: 'mp3',\n ...config,\n } as IAdvancedSynthesisConfig;\n\n try {\n this.initializeStrategy();\n this._status = 'ready';\n return Promise.resolve();\n } catch (error) {\n this._status = 'error';\n return Promise.reject(error);\n }\n }\n\n /**\n * 初始化合成策略\n */\n private initializeStrategy(): void {\n const advConfig = this.config;\n const mode = advConfig.mode ?? 'auto';\n const hasNative = typeof window !== 'undefined' && 'speechSynthesis' in window;\n\n // 选择策略\n if (mode === 'native' || (mode === 'auto' && hasNative && !advConfig.cloudAdapter)) {\n const nativeStrategy = new NativeSynthesisStrategy(advConfig);\n if (!nativeStrategy.isAvailable()) {\n throw new Error('浏览器不支持原生语音合成');\n }\n this.strategy = nativeStrategy;\n this._currentProvider = 'browser';\n } else if (mode === 'cloud' || (mode === 'auto' && advConfig.cloudAdapter)) {\n if (!advConfig.cloudAdapter) {\n throw new Error('云端模式需要提供 cloudAdapter');\n }\n this.strategy = new CloudSynthesisStrategy(advConfig);\n this._currentProvider = 'custom';\n } else {\n throw new Error('没有可用的合成策略');\n }\n\n // 转发事件\n this.forwardStrategyEvents();\n }\n\n /**\n * 转发策略事件\n */\n private forwardStrategyEvents(): void {\n if (!this.strategy) return;\n\n this.strategy.on('start', () => this.emit('start', { type: 'start' }));\n this.strategy.on('end', () => this.emit('end', { type: 'end' }));\n this.strategy.on('pause', () => this.emit('pause', { type: 'pause' }));\n this.strategy.on('resume', () => this.emit('resume', { type: 'resume' }));\n\n this.strategy.on('boundary', data => {\n const event: SynthesisEvent = { type: 'boundary' };\n if (data.charIndex !== undefined) event.charIndex = data.charIndex;\n if (data.charLength !== undefined) event.charLength = data.charLength;\n if (data.elapsedTime !== undefined) event.elapsedTime = data.elapsedTime;\n if (data.name !== undefined) event.name = data.name;\n this.emit('boundary', event);\n });\n\n this.strategy.on('mark', data => {\n const event: SynthesisEvent = { type: 'mark' };\n if (data.name !== undefined) event.name = data.name;\n this.emit('mark', event);\n });\n\n this.strategy.on('error', err => {\n const errorEvent: SynthesisEvent = {\n type: 'error',\n error: {\n code: err.code,\n message: err.message,\n },\n };\n if (err.originalError) {\n errorEvent.error!.originalError = err.originalError as Error;\n }\n this.emit('error', errorEvent);\n });\n }\n\n /**\n * 获取可用语音列表\n */\n async getVoices(): Promise<VoiceInfo[]> {\n if (!this.strategy) {\n throw new Error('语音合成器未初始化');\n }\n return this.strategy.getVoices();\n }\n\n /**\n * 朗读文本\n */\n async speak(text: string, config?: SynthesisConfig): Promise<void> {\n if (this._status !== 'ready') {\n throw new Error('语音合成器未就绪');\n }\n\n return this.strategy?.speak(text, config);\n }\n\n /**\n * 暂停朗读\n */\n pause(): void {\n this.strategy?.pause();\n }\n\n /**\n * 继续朗读\n */\n resume(): void {\n this.strategy?.resume();\n }\n\n /**\n * 取消朗读\n */\n cancel(): void {\n this.strategy?.cancel();\n }\n\n /**\n * 是否正在朗读\n */\n isSpeaking(): boolean {\n return this.strategy?.isSpeaking() ?? false;\n }\n\n /**\n * 是否已暂停\n */\n isPaused(): boolean {\n return this.strategy?.isPaused() ?? false;\n }\n\n /**\n * 添加事件监听\n */\n on(event: SynthesisEventType, handler: SynthesisEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * 移除事件监听\n */\n off(event: SynthesisEventType, handler: SynthesisEventHandler): void {\n this.eventHandlers.get(event)?.delete(handler);\n }\n\n /**\n * 触发事件\n */\n private emit(type: SynthesisEventType, event: SynthesisEvent): void {\n this.eventHandlers.get(type)?.forEach(handler => {\n try {\n handler(event);\n } catch (e) {\n console.error('[SpeechSynthesizer] 事件处理器错误:', e);\n }\n });\n }\n\n /**\n * 销毁实例\n */\n dispose(): void {\n this.strategy?.dispose();\n this.strategy = null;\n this.eventHandlers.clear();\n this._status = 'idle';\n }\n\n /**\n * 注册自定义提供商\n */\n registerProvider(type: SpeechProviderType, provider: SynthesisProvider): void {\n this.customProviders.set(type, provider);\n }\n\n /**\n * 使用云端适配器\n */\n useCloudAdapter(adapter: ICloudSynthesisAdapter): void {\n this.config.cloudAdapter = adapter;\n this.config.mode = 'cloud';\n }\n}\n\n// ============================================================================\n// 9. 工厂函数和工具函数\n// ============================================================================\n\n/**\n * 创建语音合成器实例\n * @param config - 可选的合成配置\n * @returns 语音合成器实例\n *\n * @example\n * ```typescript\n * // 使用原生合成\n * const synthesizer = await createSpeechSynthesizer({\n * lang: 'zh-CN',\n * rate: 1.0,\n * });\n *\n * // 使用云端合成 (Azure)\n * const azureAdapter = new AzureSynthesisAdapter('key', 'eastasia');\n * const cloudSynthesizer = await createSpeechSynthesizer({\n * mode: 'cloud',\n * cloudAdapter: azureAdapter,\n * });\n *\n * await synthesizer.speak('你好,世界!');\n * ```\n */\nexport async function createSpeechSynthesizer(\n config?: SynthesisConfig | IAdvancedSynthesisConfig\n): Promise<SpeechSynthesizer> {\n const synthesizer = new SpeechSynthesizerImpl();\n await synthesizer.initialize(config);\n return synthesizer;\n}\n\n/**\n * 检查当前环境是否支持语音合成\n * @returns 是否支持语音合成\n */\nexport function isSpeechSynthesisSupported(): boolean {\n return typeof window !== 'undefined' && 'speechSynthesis' in window;\n}\n\n/**\n * 快速朗读文本(一次性使用)\n * @param text - 要朗读的文本\n * @param config - 可选的合成配置\n *\n * @example\n * ```typescript\n * // 快速朗读\n * await speak('你好,世界!');\n *\n * // 带配置的朗读\n * await speak('Hello World', { lang: 'en-US', rate: 0.8 });\n * ```\n */\nexport async function speak(\n text: string,\n config?: SynthesisConfig | IAdvancedSynthesisConfig\n): Promise<void> {\n const synthesizer = await createSpeechSynthesizer(config);\n try {\n await synthesizer.speak(text, config);\n } finally {\n synthesizer.dispose();\n }\n}\n\n/**\n * 快速朗读文本(云端模式)\n * @param text - 要朗读的文本\n * @param adapter - 云端适配器\n * @param config - 可选配置\n */\nexport async function speakWithCloud(\n text: string,\n adapter: ICloudSynthesisAdapter,\n config?: SynthesisConfig\n): Promise<void> {\n const synthesizer = await createSpeechSynthesizer({\n ...config,\n mode: 'cloud',\n cloudAdapter: adapter,\n } as IAdvancedSynthesisConfig);\n\n try {\n await synthesizer.speak(text, config);\n } finally {\n synthesizer.dispose();\n }\n}\n","/**\n * @fileoverview 语音识别 (STT) 实现 - 商业级版本 v2.0\n * @module melange/plugins/speech/recognition\n * @description 生产级 Web 语音识别插件\n *\n * 架构:\n * [UI层] -> [SpeechRecognizerImpl] -> [NativeStrategy / CloudStrategy]\n * |\n * +-> [音频核心]: Worklet, VAD, Resample\n * +-> [适配器]: BaiduAdapter, XunfeiAdapter, TencentAdapter...\n *\n * 功能特性:\n * 1. 多模式: 支持 WebSocket 流式识别 & HTTP 短语音识别\n * 2. 状态机: IDLE -> CONNECTING -> RECORDING -> PROCESSING\n * 3. 插件化: 内置 讯飞/腾讯/百度/阿里/Google/Azure 适配器\n * 4. 核心: AudioWorklet + VAD + 自动重采样 + WAV编码\n * 5. 兼容性: 自动降级处理 (ScriptProcessor) + 断网缓冲队列\n */\n\nimport type {\n SpeechProviderType,\n SpeechServiceStatus,\n RecognitionConfig,\n RecognitionEventType,\n RecognitionEvent,\n RecognitionEventHandler,\n RecognitionProvider,\n SpeechRecognizer,\n RecognitionResult,\n} from './types';\n\n// ============================================================================\n// 1. 类型定义 & 枚举\n// ============================================================================\n\n// Window 接口扩展 - 支持浏览器语音 API 和 AudioContext\n// 使用 unknown 避免循环引用,实际类型在下方 BrowserSpeechRecognition 中定义\ndeclare global {\n interface Window {\n SpeechRecognition?: unknown;\n webkitSpeechRecognition?: unknown;\n webkitAudioContext?: typeof AudioContext;\n }\n}\n\n/**\n * 识别器状态枚举\n */\nexport enum RecognitionStatus {\n /** 空闲状态 */\n IDLE = 'IDLE',\n /** 连接中 */\n CONNECTING = 'CONNECTING',\n /** 录音中 */\n RECORDING = 'RECORDING',\n /** 处理中/上传中 */\n PROCESSING = 'PROCESSING',\n}\n\n/**\n * 识别引擎模式\n */\nexport type RecognitionEngineMode = 'native' | 'cloud' | 'auto';\n\n/**\n * 云端传输协议类型\n */\nexport type CloudTransportType = 'websocket' | 'http';\n\n/**\n * 识别结果接口\n */\nexport interface IRecognitionResult {\n /** 识别文本 */\n transcript: string;\n /** 是否为最终结果 */\n isFinal: boolean;\n /** 置信度 (0-1) */\n confidence: number;\n /** 原始响应数据 */\n original?: unknown;\n}\n\n/**\n * 识别错误接口\n */\nexport interface IRecognitionError {\n /** 错误代码 */\n code:\n | 'NETWORK'\n | 'NOT_ALLOWED'\n | 'NO_SPEECH'\n | 'NOT_SUPPORTED'\n | 'VAD_TIMEOUT'\n | 'ADAPTER_ERROR'\n | 'UNKNOWN';\n /** 错误信息 */\n message: string;\n /** 原始错误 */\n originalError?: unknown;\n}\n\n/**\n * 音频配置接口\n */\nexport interface IAudioConfig {\n /** 目标采样率 (默认 16000) */\n sampleRate?: number;\n /** VAD 阈值 (0.01 ~ 0.5) */\n vadThreshold?: number;\n /** VAD 静音超时 (ms) */\n vadDuration?: number;\n /** 是否启用回声消除 */\n echoCancellation?: boolean;\n /** 是否启用噪声抑制 */\n noiseSuppression?: boolean;\n /** 是否启用自动增益控制 */\n autoGainControl?: boolean;\n}\n\n/**\n * 高级识别配置\n */\nexport interface IAdvancedRecognitionConfig extends RecognitionConfig {\n /** 识别引擎模式 */\n mode?: RecognitionEngineMode;\n /** 云端适配器 */\n cloudAdapter?: ICloudRecognitionAdapter;\n /** 传输协议 */\n transport?: CloudTransportType;\n /** 音频配置 */\n audioConfig?: IAudioConfig;\n /** 是否启用自动重连 */\n autoReconnect?: boolean;\n /** 最大重连次数 */\n maxReconnectAttempts?: number;\n /** 重连间隔 (ms) */\n reconnectInterval?: number;\n}\n\n// ============================================================================\n// 2. 云端适配器接口\n// ============================================================================\n\n/**\n * 云端识别适配器接口\n * 提供统一的第三方语音识别服务集成接口\n */\nexport interface ICloudRecognitionAdapter {\n /** 适配器名称 */\n readonly name: string;\n\n /**\n * 获取 WebSocket 连接地址\n * @returns WebSocket URL\n */\n getConnectUrl?(): Promise<string> | string;\n\n /**\n * 获取握手参数\n * @returns 握手消息\n */\n getHandshakeParams?(): unknown;\n\n /**\n * HTTP 短语音识别\n * @param audioData WAV/PCM 二进制数据\n * @returns 识别结果\n */\n recognizeShortAudio?(audioData: ArrayBuffer): Promise<IRecognitionResult>;\n\n /**\n * 转换音频数据格式\n * @param pcmData PCM 原始数据\n * @returns 转换后的数据\n */\n transformAudioData?(pcmData: ArrayBuffer): ArrayBuffer | string;\n\n /**\n * 解析识别结果\n * @param data 原始响应数据\n * @returns 识别结果\n */\n parseResult(data: unknown): IRecognitionResult | null;\n\n /**\n * 检查适配器是否可用\n * @returns 是否可用\n */\n isAvailable?(): boolean;\n}\n\n// ============================================================================\n// 3. 音频工具类 (含 WAV 编码器)\n// ============================================================================\n\n/**\n * 音频处理工具集\n */\nexport const AudioUtils = {\n /**\n * 重采样音频数据\n * @param data 原始音频数据\n * @param inputRate 输入采样率\n * @param outputRate 输出采样率\n * @returns 重采样后的数据\n */\n resample(data: Float32Array, inputRate: number, outputRate: number): Float32Array {\n if (inputRate === outputRate) return data;\n const compression = inputRate / outputRate;\n const length = Math.ceil(data.length / compression);\n const result = new Float32Array(length);\n for (let i = 0; i < length; i++) {\n result[i] = data[Math.floor(i * compression)] ?? 0;\n }\n return result;\n },\n\n /**\n * Float32 转 Int16 PCM\n * @param input Float32 数据\n * @returns Int16 PCM 数据\n */\n floatTo16BitPCM(input: Float32Array): Int16Array {\n const output = new Int16Array(input.length);\n for (let i = 0; i < input.length; i++) {\n const s = Math.max(-1, Math.min(1, input[i] ?? 0));\n output[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n return output;\n },\n\n /**\n * 计算音量 RMS\n * @param data 音频数据\n * @returns RMS 值\n */\n calculateRMS(data: Float32Array): number {\n let sum = 0;\n for (let i = 0; i < data.length; i++) {\n const sample = data[i] ?? 0;\n sum += sample * sample;\n }\n return Math.sqrt(sum / data.length);\n },\n\n /**\n * 合并 PCM 片段\n * @param buffers PCM 缓冲区数组\n * @param totalLength 总采样数\n * @returns 合并后的 Int16 数组\n */\n mergeBuffers(buffers: ArrayBuffer[], totalLength: number): Int16Array {\n const result = new Int16Array(totalLength);\n let offset = 0;\n for (const buffer of buffers) {\n const view = new Int16Array(buffer);\n result.set(view, offset);\n offset += view.length;\n }\n return result;\n },\n\n /**\n * PCM 转 WAV 封装\n * @param samples PCM 采样数据\n * @param sampleRate 采样率\n * @param channels 声道数\n * @returns WAV 格式 ArrayBuffer\n */\n encodeWAV(samples: Int16Array, sampleRate: number = 16000, channels: number = 1): ArrayBuffer {\n const buffer = new ArrayBuffer(44 + samples.length * 2);\n const view = new DataView(buffer);\n\n const writeString = (offset: number, str: string): void => {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n };\n\n // RIFF Header\n writeString(0, 'RIFF');\n view.setUint32(4, 36 + samples.length * 2, true);\n writeString(8, 'WAVE');\n\n // fmt chunk\n writeString(12, 'fmt ');\n view.setUint32(16, 16, true); // chunk size\n view.setUint16(20, 1, true); // PCM format\n view.setUint16(22, channels, true); // channels\n view.setUint32(24, sampleRate, true); // sample rate\n view.setUint32(28, sampleRate * channels * 2, true); // byte rate\n view.setUint16(32, channels * 2, true); // block align\n view.setUint16(34, 16, true); // bits per sample\n\n // data chunk\n writeString(36, 'data');\n view.setUint32(40, samples.length * 2, true);\n\n // 写入采样数据\n const dataOffset = 44;\n for (let i = 0; i < samples.length; i++) {\n view.setInt16(dataOffset + i * 2, samples[i] ?? 0, true);\n }\n\n return buffer;\n },\n\n /**\n * ArrayBuffer 转 Base64\n * @param buffer ArrayBuffer\n * @returns Base64 字符串\n */\n arrayBufferToBase64(buffer: ArrayBuffer): string {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n const len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i] ?? 0);\n }\n return typeof btoa !== 'undefined' ? btoa(binary) : Buffer.from(binary).toString('base64');\n },\n};\n\n// ============================================================================\n// 4. AudioWorklet 核心代码\n// ============================================================================\n\n/**\n * AudioWorklet 处理器代码\n * 在音频线程中运行,实现实时音频处理\n */\nconst WORKLET_CODE = `\nclass SpeechProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffer = [];\n this.targetRate = 16000;\n this.currentRate = 44100;\n this.silenceFrames = 0;\n this.maxSilenceFrames = 0;\n this.vadThreshold = 0.02;\n this.isRecording = false;\n this.port.onmessage = this.handleMessage.bind(this);\n }\n\n static get parameterDescriptors() {\n return [];\n }\n\n process(inputs) {\n const input = inputs[0];\n if (!input || !input.length || !this.isRecording) return true;\n const channelData = input[0];\n\n // VAD 检测\n let sum = 0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const rms = Math.sqrt(sum / channelData.length);\n\n if (rms < this.vadThreshold) {\n this.silenceFrames++;\n if (this.maxSilenceFrames > 0 && this.silenceFrames > this.maxSilenceFrames) {\n this.port.postMessage({ type: 'VAD_TIMEOUT' });\n this.silenceFrames = 0;\n }\n } else {\n this.silenceFrames = 0;\n }\n\n // 重采样\n if (this.targetRate < this.currentRate) {\n const compression = this.currentRate / this.targetRate;\n for (let i = 0; i < channelData.length; i += compression) {\n this.buffer.push(channelData[Math.floor(i)]);\n }\n } else {\n this.buffer.push(...channelData);\n }\n\n // 定期刷新 (~128ms)\n if (this.buffer.length >= 2048) {\n this.flush();\n }\n return true;\n }\n\n flush() {\n if (this.buffer.length === 0) return;\n const pcmData = new Int16Array(this.buffer.length);\n for (let i = 0; i < this.buffer.length; i++) {\n let s = Math.max(-1, Math.min(1, this.buffer[i]));\n s = s < 0 ? s * 0x8000 : s * 0x7FFF;\n pcmData[i] = s;\n }\n this.port.postMessage({ type: 'AUDIO_DATA', payload: pcmData.buffer }, [pcmData.buffer]);\n this.buffer = [];\n }\n\n handleMessage(event) {\n const { type, payload } = event.data;\n if (type === 'CONFIG') {\n this.targetRate = payload.targetRate || 16000;\n this.currentRate = payload.currentRate || 44100;\n this.vadThreshold = payload.vadThreshold || 0.02;\n const secondsPerBlock = 128 / this.currentRate;\n this.maxSilenceFrames = (payload.vadDuration / 1000) / secondsPerBlock;\n }\n if (type === 'SET_RECORDING') {\n this.isRecording = payload;\n if (!payload) this.flush();\n }\n }\n}\nregisterProcessor('speech-processor', SpeechProcessor);\n`;\n\n// ============================================================================\n// 5. 浏览器 Speech Recognition API 类型声明\n// ============================================================================\n\ninterface BrowserSpeechRecognitionResultList {\n readonly length: number;\n item(index: number): BrowserSpeechRecognitionResult | null;\n [index: number]: BrowserSpeechRecognitionResult;\n}\n\ninterface BrowserSpeechRecognitionResult {\n readonly length: number;\n readonly isFinal: boolean;\n item(index: number): BrowserSpeechRecognitionAlternative | null;\n [index: number]: BrowserSpeechRecognitionAlternative;\n}\n\ninterface BrowserSpeechRecognitionAlternative {\n readonly transcript: string;\n readonly confidence: number;\n}\n\ninterface BrowserSpeechRecognitionEvent {\n readonly results: BrowserSpeechRecognitionResultList;\n readonly resultIndex: number;\n}\n\ninterface BrowserSpeechRecognitionErrorEvent {\n readonly error: string;\n readonly message: string;\n}\n\ninterface BrowserSpeechRecognition extends EventTarget {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n maxAlternatives: number;\n start(): void;\n stop(): void;\n abort(): void;\n onstart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onresult: ((this: BrowserSpeechRecognition, ev: BrowserSpeechRecognitionEvent) => void) | null;\n onerror:\n | ((this: BrowserSpeechRecognition, ev: BrowserSpeechRecognitionErrorEvent) => void)\n | null;\n onsoundstart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onsoundend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onspeechstart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onspeechend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onaudiostart: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onaudioend: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n onnomatch: ((this: BrowserSpeechRecognition, ev: Event) => void) | null;\n}\n\ninterface BrowserSpeechRecognitionConstructor {\n new (): BrowserSpeechRecognition;\n}\n\n// ============================================================================\n// 6. 内置云端适配器实现\n// ============================================================================\n\n/**\n * 通用适配器 (BFF 模式 - 推荐)\n * 适用于自建后端代理场景\n */\nexport class GenericAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Generic/BFF';\n\n constructor(private baseUrl: string) {}\n\n getConnectUrl(): string {\n return this.baseUrl.replace(/^http/, 'ws');\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const formData = new FormData();\n formData.append('file', new Blob([audioData], { type: 'audio/wav' }));\n\n const res = await fetch(`${this.baseUrl}/recognize`, {\n method: 'POST',\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}: ${res.statusText}`);\n }\n\n const json = (await res.json()) as Record<string, unknown>;\n const result = this.parseResult(json);\n if (!result) throw new Error('解析结果失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n return {\n transcript: (data['text'] as string) || (data['transcript'] as string) || '',\n isFinal: true,\n confidence: (data['score'] as number) || (data['confidence'] as number) || 0.9,\n original: data,\n };\n }\n}\n\n/**\n * 讯飞云适配器\n * 支持讯飞语音听写 WebAPI\n */\nexport class XunfeiAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Xunfei';\n /** API Key - 生产环境应在后端使用 */\n readonly apiKey: string | undefined;\n /** API Secret - 生产环境应在后端使用 */\n readonly apiSecret: string | undefined;\n\n constructor(\n private appId: string,\n apiKey?: string,\n apiSecret?: string\n ) {\n this.apiKey = apiKey;\n this.apiSecret = apiSecret;\n }\n\n getConnectUrl(): string {\n // 生产环境应在后端生成鉴权 URL\n // 参见: https://www.xfyun.cn/doc/asr/voicedictation/API.html\n const host = 'iat-api.xfyun.cn';\n const path = '/v2/iat';\n // 简化演示,实际需要计算 authorization\n return `wss://${host}${path}?authorization=...&date=...&host=${host}`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n return {\n common: { app_id: this.appId },\n business: {\n language: 'zh_cn',\n domain: 'iat',\n accent: 'mandarin',\n vad_eos: 3000,\n },\n data: {\n status: 0,\n format: 'audio/L16;rate=16000',\n encoding: 'raw',\n },\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const blob = new Blob([audioData], { type: 'audio/wav' });\n const formData = new FormData();\n formData.append('audio', blob);\n formData.append('engine_type', 'sms16k');\n\n const response = await fetch('https://api.xfyun.cn/v1/service/v1/iat', {\n method: 'POST',\n headers: {\n 'X-Appid': this.appId,\n // 生产环境需添加: 'X-CurTime', 'X-Param', 'X-CheckSum'\n },\n body: formData,\n });\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('讯飞识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n // WebSocket 响应格式\n if (data['code'] !== undefined && data['code'] !== 0) {\n return null;\n }\n\n let text = '';\n\n // WebSocket 格式\n const wsData = data['data'] as Record<string, unknown> | undefined;\n if (wsData?.['result']) {\n const result = wsData['result'] as { ws?: Array<{ cw: Array<{ w: string }> }> };\n text = result.ws?.map(w => w.cw[0]?.w ?? '').join('') ?? '';\n }\n\n // HTTP 格式\n if (data['desc'] === 'success' && typeof data['data'] === 'string') {\n text = data['data'];\n }\n\n if (!text) return null;\n\n return {\n transcript: text,\n isFinal: wsData?.['status'] === 2 || !!data['desc'],\n confidence: 0.9,\n original: data,\n };\n }\n}\n\n/**\n * 腾讯云适配器\n * 支持腾讯云一句话识别\n */\nexport class TencentAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Tencent';\n /** Secret ID - 生产环境应在后端使用 */\n readonly secretId: string;\n /** Secret Key - 生产环境应在后端使用 */\n readonly secretKey: string;\n\n constructor(secretId: string, secretKey: string) {\n this.secretId = secretId;\n this.secretKey = secretKey;\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n // TC3-HMAC-SHA256 签名应在后端完成\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n const payload = {\n ProjectId: 0,\n SubServiceType: 2,\n EngSerViceType: '16k_zh',\n SourceType: 1,\n VoiceFormat: 'wav',\n UsrAudioKey: `session-${Date.now()}`,\n Data: base64Audio,\n DataLen: audioData.byteLength,\n };\n\n const res = await fetch('https://asr.tencentcloudapi.com', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-TC-Action': 'SentenceRecognition',\n // 生产环境需添加: 'Authorization', 'X-TC-Timestamp' 等\n },\n body: JSON.stringify(payload),\n });\n\n const json = (await res.json()) as Record<string, unknown>;\n const result = this.parseResult(json);\n if (!result) throw new Error('腾讯云识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n const resp = data['Response'] as Record<string, unknown> | undefined;\n if (resp?.['Error']) {\n const error = resp['Error'] as { Message?: string };\n throw new Error(error.Message ?? '腾讯云 API 错误');\n }\n if (resp?.['Result']) {\n return {\n transcript: resp['Result'] as string,\n isFinal: true,\n confidence: 0.9,\n original: data,\n };\n }\n return null;\n }\n}\n\n/**\n * 百度云适配器\n * 支持百度语音识别 REST API 和 WebSocket API\n */\nexport class BaiduAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Baidu';\n\n constructor(\n private accessToken: string,\n private appId?: string,\n private appKey?: string,\n private devPid: number = 1537\n ) {}\n\n getConnectUrl(): string {\n const sn = Math.random().toString(36).substring(2) + Date.now();\n return `wss://vop.baidu.com/realtime_asr?sn=${sn}`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n if (!this.appId || !this.appKey) {\n console.warn('[BaiduAdapter] WebSocket 模式需要 appId 和 appKey');\n }\n return {\n type: 'START',\n data: {\n appid: Number(this.appId),\n appkey: this.appKey,\n dev_pid: this.devPid,\n cuid: `sdk-user-${Date.now()}`,\n format: 'pcm',\n sample: 16000,\n },\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n const payload = {\n format: 'wav',\n rate: 16000,\n channel: 1,\n cuid: `sdk-user-${Date.now()}`,\n token: this.accessToken,\n dev_pid: this.devPid,\n speech: base64Audio,\n len: audioData.byteLength,\n };\n\n // 建议通过 BFF 代理调用,避免 CORS 问题\n const response = await fetch('/api/baidu-speech/pro_api', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('百度识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n // HTTP 响应\n if (data['err_no'] !== undefined) {\n if (data['err_no'] !== 0) {\n throw new Error(`Baidu API Error [${String(data['err_no'])}]: ${String(data['err_msg'])}`);\n }\n const result = data['result'] as string[] | undefined;\n if (result && result.length > 0) {\n return {\n transcript: result[0] ?? '',\n isFinal: true,\n confidence: 0.9,\n original: data,\n };\n }\n }\n\n // WebSocket 响应\n if (data['type']) {\n if (data['type'] === 'HEARTBEAT') return null;\n if (data['type'] === 'ERROR') {\n throw new Error(`Baidu WS Error: ${String(data['err_msg'])}`);\n }\n if (data['type'] === 'MID_TEXT' || data['type'] === 'FIN_TEXT') {\n return {\n transcript: data['result'] as string,\n isFinal: data['type'] === 'FIN_TEXT',\n confidence: 0.9,\n original: data,\n };\n }\n }\n\n return null;\n }\n}\n\n/**\n * 阿里云适配器\n * 支持阿里云智能语音交互\n */\nexport class AlibabaAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Alibaba';\n /** Access Key Secret - 生产环境应在后端使用 */\n readonly accessKeySecret: string;\n\n constructor(\n private accessKeyId: string,\n accessKeySecret: string,\n private appKey: string\n ) {\n this.accessKeySecret = accessKeySecret;\n }\n\n getConnectUrl(): string {\n // 阿里云实时语音识别 WebSocket 地址\n return `wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n return {\n header: {\n message_id: this.generateUUID(),\n task_id: this.generateUUID(),\n namespace: 'SpeechRecognizer',\n name: 'StartRecognition',\n appkey: this.appKey,\n },\n payload: {\n format: 'pcm',\n sample_rate: 16000,\n enable_intermediate_result: true,\n enable_punctuation_prediction: true,\n enable_inverse_text_normalization: true,\n },\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n // 建议通过 BFF 代理调用\n const response = await fetch('/api/alibaba-speech/recognize', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-NLS-Token': this.accessKeyId,\n },\n body: JSON.stringify({\n appkey: this.appKey,\n format: 'wav',\n sample_rate: 16000,\n audio: base64Audio,\n }),\n });\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('阿里云识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n // WebSocket 响应\n const header = data['header'] as Record<string, unknown> | undefined;\n if (header) {\n const status = header['status'] as number;\n if (status !== 20000000) {\n throw new Error(`Alibaba Error [${status}]: ${String(header['status_text'])}`);\n }\n\n const payload = data['payload'] as Record<string, unknown> | undefined;\n if (payload?.['result']) {\n return {\n transcript: payload['result'] as string,\n isFinal: header['name'] === 'RecognitionCompleted',\n confidence: 0.9,\n original: data,\n };\n }\n }\n\n // HTTP 响应\n if (data['result']) {\n return {\n transcript: data['result'] as string,\n isFinal: true,\n confidence: (data['confidence'] as number) || 0.9,\n original: data,\n };\n }\n\n return null;\n }\n\n private generateUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n\n/**\n * Google Cloud Speech 适配器\n */\nexport class GoogleAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Google';\n\n constructor(\n private apiKey: string,\n private languageCode: string = 'zh-CN'\n ) {}\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const base64Audio = AudioUtils.arrayBufferToBase64(audioData);\n\n const payload = {\n config: {\n encoding: 'LINEAR16',\n sampleRateHertz: 16000,\n languageCode: this.languageCode,\n enableAutomaticPunctuation: true,\n },\n audio: {\n content: base64Audio,\n },\n };\n\n const response = await fetch(\n `https://speech.googleapis.com/v1/speech:recognize?key=${this.apiKey}`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n }\n );\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('Google 识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n if (data['error']) {\n const error = data['error'] as { message?: string };\n throw new Error(error.message ?? 'Google API Error');\n }\n\n const results = data['results'] as Array<{\n alternatives?: Array<{ transcript?: string; confidence?: number }>;\n }>;\n\n if (results && results.length > 0) {\n const alternatives = results[0]?.alternatives;\n if (alternatives && alternatives.length > 0) {\n return {\n transcript: alternatives[0]?.transcript ?? '',\n isFinal: true,\n confidence: alternatives[0]?.confidence ?? 0.9,\n original: data,\n };\n }\n }\n\n return null;\n }\n}\n\n/**\n * Azure Speech 适配器\n */\nexport class AzureAdapter implements ICloudRecognitionAdapter {\n readonly name = 'Azure';\n\n constructor(\n private subscriptionKey: string,\n private region: string,\n private language: string = 'zh-CN'\n ) {}\n\n getConnectUrl(): string {\n return `wss://${this.region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=${this.language}`;\n }\n\n getHandshakeParams(): Record<string, unknown> {\n return {\n 'Ocp-Apim-Subscription-Key': this.subscriptionKey,\n };\n }\n\n async recognizeShortAudio(audioData: ArrayBuffer): Promise<IRecognitionResult> {\n const response = await fetch(\n `https://${this.region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=${this.language}`,\n {\n method: 'POST',\n headers: {\n 'Ocp-Apim-Subscription-Key': this.subscriptionKey,\n 'Content-Type': 'audio/wav; codecs=audio/pcm; samplerate=16000',\n },\n body: audioData,\n }\n );\n\n const data = (await response.json()) as Record<string, unknown>;\n const result = this.parseResult(data);\n if (!result) throw new Error('Azure 识别失败');\n return result;\n }\n\n parseResult(data: Record<string, unknown>): IRecognitionResult | null {\n if (data['RecognitionStatus'] === 'Success') {\n return {\n transcript: (data['DisplayText'] as string) || (data['Text'] as string) || '',\n isFinal: true,\n confidence: (data['Confidence'] as number) || 0.9,\n original: data,\n };\n }\n\n // WebSocket 分片响应\n if (data['Text']) {\n return {\n transcript: data['Text'] as string,\n isFinal: data['RecognitionStatus'] === 'Success',\n confidence: 0.9,\n original: data,\n };\n }\n\n return null;\n }\n}\n\n// ============================================================================\n// 7. 抽象策略基类\n// ============================================================================\n\n/**\n * 事件监听器类型定义\n */\ntype EventListeners = {\n result: Array<(res: IRecognitionResult) => void>;\n error: Array<(err: IRecognitionError) => void>;\n state: Array<(status: RecognitionStatus) => void>;\n start: Array<() => void>;\n end: Array<() => void>;\n soundstart: Array<() => void>;\n soundend: Array<() => void>;\n speechstart: Array<() => void>;\n speechend: Array<() => void>;\n audiostart: Array<() => void>;\n audioend: Array<() => void>;\n};\n\n/**\n * 识别策略基类\n */\nabstract class BaseRecognitionStrategy {\n protected listeners: EventListeners = {\n result: [],\n error: [],\n state: [],\n start: [],\n end: [],\n soundstart: [],\n soundend: [],\n speechstart: [],\n speechend: [],\n audiostart: [],\n audioend: [],\n };\n\n protected _status: RecognitionStatus = RecognitionStatus.IDLE;\n\n constructor(protected config: IAdvancedRecognitionConfig) {}\n\n /**\n * 获取当前状态\n */\n get status(): RecognitionStatus {\n return this._status;\n }\n\n /**\n * 开始识别\n */\n abstract start(): Promise<void>;\n\n /**\n * 停止识别\n */\n abstract stop(): void;\n\n /**\n * 中止识别\n */\n abstract abort(): void;\n\n /**\n * 是否正在录音\n */\n abstract isListening(): boolean;\n\n /**\n * 设置状态\n */\n protected setStatus(status: RecognitionStatus): void {\n if (this._status !== status) {\n this._status = status;\n this.emit('state', status);\n }\n }\n\n /**\n * 添加事件监听\n */\n on<K extends keyof EventListeners>(event: K, fn: EventListeners[K][number]): void {\n (this.listeners[event] as Array<typeof fn>).push(fn);\n }\n\n /**\n * 移除事件监听\n */\n off<K extends keyof EventListeners>(event: K, fn: EventListeners[K][number]): void {\n const listeners = this.listeners[event] as Array<typeof fn>;\n const index = listeners.indexOf(fn);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n }\n\n /**\n * 触发事件\n */\n protected emit<K extends keyof EventListeners>(\n event: K,\n data?: Parameters<EventListeners[K][number]>[0]\n ): void {\n const listeners = this.listeners[event] as Array<(arg?: typeof data) => void>;\n listeners.forEach(fn => {\n try {\n fn(data);\n } catch (e) {\n console.error(`[Recognition] 事件处理器错误 (${event}):`, e);\n }\n });\n }\n\n /**\n * 销毁资源\n */\n dispose(): void {\n this.abort();\n Object.keys(this.listeners).forEach(key => {\n (this.listeners as Record<string, unknown[]>)[key] = [];\n });\n }\n}\n\n// ============================================================================\n// 8. 原生识别策略\n// ============================================================================\n\n/**\n * 浏览器原生语音识别策略\n * 使用 Web Speech API\n */\nclass NativeRecognitionStrategy extends BaseRecognitionStrategy {\n private recognition: BrowserSpeechRecognition | null = null;\n private SpeechRecognitionClass: BrowserSpeechRecognitionConstructor | null = null;\n\n constructor(config: IAdvancedRecognitionConfig) {\n super(config);\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const srClass =\n typeof window !== 'undefined'\n ? ((window.SpeechRecognition as BrowserSpeechRecognitionConstructor | undefined) ??\n (window.webkitSpeechRecognition as BrowserSpeechRecognitionConstructor | undefined))\n : undefined;\n this.SpeechRecognitionClass = srClass ?? null;\n }\n\n /**\n * 检查是否可用\n */\n isAvailable(): boolean {\n return this.SpeechRecognitionClass !== null;\n }\n\n async start(): Promise<void> {\n if (!this.SpeechRecognitionClass) {\n throw { code: 'NOT_SUPPORTED', message: '浏览器不支持语音识别' };\n }\n\n if (this._status !== RecognitionStatus.IDLE) {\n return;\n }\n\n this.setStatus(RecognitionStatus.CONNECTING);\n\n return new Promise((resolve, reject) => {\n this.recognition = new this.SpeechRecognitionClass!();\n\n // 配置\n this.recognition.lang = this.config.lang ?? 'zh-CN';\n this.recognition.continuous = this.config.continuous ?? false;\n this.recognition.interimResults = this.config.interimResults ?? true;\n this.recognition.maxAlternatives = this.config.maxAlternatives ?? 1;\n\n // 事件处理\n this.recognition.onstart = () => {\n this.setStatus(RecognitionStatus.RECORDING);\n this.emit('start');\n this.emit('audiostart');\n resolve();\n };\n\n this.recognition.onend = () => {\n this.setStatus(RecognitionStatus.IDLE);\n this.emit('audioend');\n this.emit('end');\n };\n\n this.recognition.onresult = e => {\n const results = e.results[e.resultIndex];\n if (results?.[0]) {\n this.emit('result', {\n transcript: results[0].transcript,\n isFinal: results.isFinal,\n confidence: results[0].confidence,\n original: e,\n });\n }\n };\n\n this.recognition.onerror = e => {\n const errorMap: Record<string, IRecognitionError['code']> = {\n 'not-allowed': 'NOT_ALLOWED',\n 'no-speech': 'NO_SPEECH',\n network: 'NETWORK',\n };\n\n const error: IRecognitionError = {\n code: errorMap[e.error] ?? 'UNKNOWN',\n message: this.getErrorMessage(e.error),\n originalError: e,\n };\n\n this.setStatus(RecognitionStatus.IDLE);\n this.emit('error', error);\n\n if (e.error === 'not-allowed' || e.error === 'audio-capture') {\n reject(error);\n }\n };\n\n this.recognition.onsoundstart = () => this.emit('soundstart');\n this.recognition.onsoundend = () => this.emit('soundend');\n this.recognition.onspeechstart = () => this.emit('speechstart');\n this.recognition.onspeechend = () => this.emit('speechend');\n\n try {\n this.recognition.start();\n } catch (e) {\n this.setStatus(RecognitionStatus.IDLE);\n reject({ code: 'UNKNOWN', message: '启动识别失败', originalError: e });\n }\n });\n }\n\n stop(): void {\n if (this.recognition && this._status === RecognitionStatus.RECORDING) {\n this.recognition.stop();\n }\n }\n\n abort(): void {\n if (this.recognition) {\n this.recognition.abort();\n this.setStatus(RecognitionStatus.IDLE);\n }\n }\n\n isListening(): boolean {\n return this._status === RecognitionStatus.RECORDING;\n }\n\n private getErrorMessage(errorCode: string): string {\n const messages: Record<string, string> = {\n 'no-speech': '未检测到语音输入',\n 'audio-capture': '无法访问麦克风',\n 'not-allowed': '麦克风权限被拒绝',\n network: '网络错误',\n aborted: '识别被中止',\n 'language-not-supported': '不支持的语言',\n 'service-not-allowed': '语音服务不可用',\n };\n return messages[errorCode] ?? `语音识别错误: ${errorCode}`;\n }\n}\n\n// ============================================================================\n// 9. 云端识别策略\n// ============================================================================\n\n/**\n * 云端语音识别策略\n * 支持 WebSocket 流式识别和 HTTP 短语音识别\n */\nclass CloudRecognitionStrategy extends BaseRecognitionStrategy {\n private audioContext: AudioContext | null = null;\n private mediaStream: MediaStream | null = null;\n private workletNode: AudioWorkletNode | null = null;\n private scriptProcessor: ScriptProcessorNode | null = null;\n private socket: WebSocket | null = null;\n private adapter: ICloudRecognitionAdapter;\n private transport: CloudTransportType;\n\n // HTTP 模式缓冲\n private pcmChunks: ArrayBuffer[] = [];\n private totalPCMLength = 0;\n\n // 页面可见性监听器\n private visibilityHandler: (() => void) | null = null;\n\n // 弱网消息队列\n private msgQueue: ArrayBuffer[] = [];\n private readonly MSG_QUEUE_MAX = 50;\n\n // ScriptProcessor 降级参数\n private spSilenceCount = 0;\n private spMaxSilence = 0;\n private isRecordingFlag = false;\n\n // 重连参数\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Worklet 加载标记\n private workletLoaded = false;\n\n constructor(config: IAdvancedRecognitionConfig) {\n super(config);\n if (!config.cloudAdapter) {\n throw new Error('[CloudStrategy] 需要提供 cloudAdapter');\n }\n this.adapter = config.cloudAdapter;\n this.transport = config.transport ?? 'websocket';\n }\n\n async start(): Promise<void> {\n if (this._status !== RecognitionStatus.IDLE) {\n return;\n }\n\n this.setStatus(RecognitionStatus.CONNECTING);\n this.pcmChunks = [];\n this.totalPCMLength = 0;\n this.reconnectAttempts = 0;\n\n try {\n // 1. WebSocket 模式预连接\n if (this.transport === 'websocket') {\n if (!this.adapter.getConnectUrl) {\n throw new Error('适配器缺少 getConnectUrl 方法');\n }\n const url = await Promise.resolve(this.adapter.getConnectUrl());\n await this.initWebSocket(url);\n }\n\n // 2. 获取麦克风权限\n const audioConfig = this.config.audioConfig ?? {};\n this.mediaStream = await navigator.mediaDevices.getUserMedia({\n audio: {\n echoCancellation: audioConfig.echoCancellation ?? true,\n noiseSuppression: audioConfig.noiseSuppression ?? true,\n autoGainControl: audioConfig.autoGainControl ?? true,\n },\n });\n\n // 3. 初始化音频上下文\n await this.initAudioContext();\n\n // 4. HTTP 模式直接进入录音状态\n if (this.transport === 'http') {\n this.setStatus(RecognitionStatus.RECORDING);\n }\n\n // 5. 监听页面可见性\n this.setupVisibilityListener();\n\n this.emit('start');\n this.emit('audiostart');\n } catch (err: unknown) {\n const error = err as Error;\n this.emit('error', {\n code: 'NOT_ALLOWED',\n message: error.message || '启动失败',\n originalError: err,\n });\n this.cleanup();\n throw err;\n }\n }\n\n /**\n * 初始化 WebSocket 连接\n */\n private initWebSocket(url: string): Promise<void> {\n return new Promise((resolve, reject) => {\n this.socket = new WebSocket(url);\n this.socket.binaryType = 'arraybuffer';\n\n const timeout = setTimeout(() => {\n reject(new Error('WebSocket 连接超时'));\n }, 10000);\n\n this.socket.onopen = () => {\n clearTimeout(timeout);\n this.setStatus(RecognitionStatus.RECORDING);\n this.reconnectAttempts = 0;\n\n // 发送握手消息\n if (this.adapter.getHandshakeParams) {\n const params = this.adapter.getHandshakeParams();\n if (params) {\n const msg = typeof params === 'string' ? params : JSON.stringify(params);\n this.socket?.send(msg);\n }\n }\n resolve();\n };\n\n this.socket.onerror = e => {\n clearTimeout(timeout);\n reject(e);\n };\n\n this.socket.onmessage = e => {\n try {\n const data = e.data as string | ArrayBuffer;\n const raw = typeof data === 'string' ? data : new TextDecoder().decode(data);\n const res = this.adapter.parseResult(JSON.parse(raw));\n if (res) {\n this.emit('result', res);\n }\n } catch {\n // 忽略解析错误\n }\n };\n\n this.socket.onclose = () => {\n if (this._status === RecognitionStatus.RECORDING) {\n this.handleReconnect();\n }\n };\n });\n }\n\n /**\n * 处理重连逻辑\n */\n private handleReconnect(): void {\n const maxAttempts = this.config.maxReconnectAttempts ?? 3;\n const interval = this.config.reconnectInterval ?? 2000;\n\n if (this.config.autoReconnect && this.reconnectAttempts < maxAttempts) {\n this.reconnectAttempts++;\n // eslint-disable-next-line no-console\n console.log(`[CloudStrategy] 尝试重连 (${this.reconnectAttempts}/${maxAttempts})`);\n\n this.reconnectTimer = setTimeout(() => {\n void (async () => {\n try {\n if (this.adapter.getConnectUrl) {\n const url = await Promise.resolve(this.adapter.getConnectUrl());\n await this.initWebSocket(url);\n }\n } catch {\n this.handleReconnect();\n }\n })();\n }, interval);\n } else {\n this.emit('error', {\n code: 'NETWORK',\n message: '连接已断开',\n });\n void this.stop();\n }\n }\n\n /**\n * 初始化音频上下文\n */\n private async initAudioContext(): Promise<void> {\n const AudioCtor =\n typeof window !== 'undefined' && (window.AudioContext || window.webkitAudioContext);\n if (!AudioCtor) {\n throw new Error('浏览器不支持 AudioContext');\n }\n\n this.audioContext = new AudioCtor();\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume();\n }\n\n const source = this.audioContext.createMediaStreamSource(this.mediaStream!);\n\n // 优先使用 AudioWorklet\n if (this.audioContext.audioWorklet && !this.workletLoaded) {\n try {\n const blob = new Blob([WORKLET_CODE], { type: 'application/javascript' });\n await this.audioContext.audioWorklet.addModule(URL.createObjectURL(blob));\n this.workletLoaded = true;\n this.setupWorklet(source);\n console.log('[CloudStrategy] 使用 AudioWorklet 模式');\n return;\n } catch (e) {\n console.warn('[CloudStrategy] AudioWorklet 加载失败,降级到 ScriptProcessor:', e);\n }\n }\n\n // 降级到 ScriptProcessor\n this.setupScriptProcessor(source);\n console.log('[CloudStrategy] 使用 ScriptProcessor 降级模式');\n }\n\n /**\n * 设置 AudioWorklet\n */\n private setupWorklet(source: MediaStreamAudioSourceNode): void {\n this.workletNode = new AudioWorkletNode(this.audioContext!, 'speech-processor');\n\n const audioConfig = this.config.audioConfig ?? {};\n this.workletNode.port.postMessage({\n type: 'CONFIG',\n payload: {\n currentRate: this.audioContext!.sampleRate,\n targetRate: audioConfig.sampleRate ?? 16000,\n vadThreshold: audioConfig.vadThreshold ?? 0.02,\n vadDuration: audioConfig.vadDuration ?? 3000,\n },\n });\n\n this.workletNode.port.onmessage = (\n e: MessageEvent<{ type: string; payload?: ArrayBuffer }>\n ) => {\n const { type, payload } = e.data;\n if (type === 'AUDIO_DATA' && payload) {\n this.handlePCM(payload);\n }\n if (type === 'VAD_TIMEOUT') {\n this.emit('speechend');\n void this.stop();\n }\n };\n\n this.workletNode.port.postMessage({ type: 'SET_RECORDING', payload: true });\n source.connect(this.workletNode);\n this.workletNode.connect(this.audioContext!.destination);\n\n this.emit('speechstart');\n }\n\n /**\n * 设置 ScriptProcessor (降级方案)\n */\n private setupScriptProcessor(source: MediaStreamAudioSourceNode): void {\n const bufferSize = 4096;\n this.scriptProcessor = this.audioContext!.createScriptProcessor(bufferSize, 1, 1);\n\n const audioConfig = this.config.audioConfig ?? {};\n const targetRate = audioConfig.sampleRate ?? 16000;\n const currentRate = this.audioContext!.sampleRate;\n\n // VAD 参数\n const secondsPerBuf = bufferSize / currentRate;\n this.spMaxSilence = (audioConfig.vadDuration ?? 3000) / 1000 / secondsPerBuf;\n this.spSilenceCount = 0;\n this.isRecordingFlag = true;\n\n this.scriptProcessor.onaudioprocess = e => {\n if (!this.isRecordingFlag) return;\n\n const input = e.inputBuffer.getChannelData(0);\n\n // VAD 检测\n const rms = AudioUtils.calculateRMS(input);\n if (rms < (audioConfig.vadThreshold ?? 0.02)) {\n this.spSilenceCount++;\n if (this.spSilenceCount > this.spMaxSilence) {\n this.emit('speechend');\n void this.stop();\n return;\n }\n } else {\n this.spSilenceCount = 0;\n }\n\n // 重采样 + 转换\n const resampled = AudioUtils.resample(input, currentRate, targetRate);\n const pcm = AudioUtils.floatTo16BitPCM(resampled);\n this.handlePCM(pcm.buffer.slice(0));\n };\n\n source.connect(this.scriptProcessor);\n this.scriptProcessor.connect(this.audioContext!.destination);\n\n this.emit('speechstart');\n }\n\n /**\n * 处理 PCM 数据\n */\n private handlePCM(buffer: ArrayBuffer): void {\n if (this.transport === 'websocket') {\n // WebSocket 流式发送\n let payload: ArrayBuffer | string = buffer;\n if (this.adapter.transformAudioData) {\n payload = this.adapter.transformAudioData(buffer);\n }\n\n if (this.socket && this.socket.readyState === WebSocket.OPEN) {\n // 先发送缓存队列\n this.flushMsgQueue();\n this.socket.send(payload);\n } else if (this.socket && this.socket.readyState === WebSocket.CONNECTING) {\n // 缓存到队列\n if (payload instanceof ArrayBuffer && this.msgQueue.length < this.MSG_QUEUE_MAX) {\n this.msgQueue.push(payload);\n }\n }\n } else {\n // HTTP 模式:堆积数据\n const chunk = buffer.slice(0);\n this.pcmChunks.push(chunk);\n this.totalPCMLength += chunk.byteLength / 2;\n }\n }\n\n /**\n * 刷新消息队列\n */\n private flushMsgQueue(): void {\n while (this.msgQueue.length > 0 && this.socket?.readyState === WebSocket.OPEN) {\n const data = this.msgQueue.shift();\n if (data) {\n this.socket.send(data);\n }\n }\n }\n\n /**\n * 设置页面可见性监听\n */\n private setupVisibilityListener(): void {\n if (typeof document === 'undefined') return;\n\n this.visibilityHandler = () => {\n if (document.hidden && this._status === RecognitionStatus.RECORDING) {\n this.emit('error', {\n code: 'NOT_ALLOWED',\n message: '页面已进入后台,录音已暂停',\n });\n void this.stop();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityHandler);\n }\n\n async stop(): Promise<void> {\n if (this._status === RecognitionStatus.IDLE) {\n return;\n }\n\n // 1. 停止录音\n this.isRecordingFlag = false;\n this.workletNode?.port.postMessage({ type: 'SET_RECORDING', payload: false });\n\n // 2. 停止媒体轨道\n this.mediaStream?.getTracks().forEach(t => t.stop());\n\n // 3. HTTP 模式提交音频\n if (\n this.transport === 'http' &&\n this.pcmChunks.length > 0 &&\n this.adapter.recognizeShortAudio\n ) {\n try {\n this.setStatus(RecognitionStatus.PROCESSING);\n\n // 合并 & 编码 WAV\n const mergedPCM = AudioUtils.mergeBuffers(this.pcmChunks, this.totalPCMLength);\n const sampleRate = this.config.audioConfig?.sampleRate ?? 16000;\n const wavBuffer = AudioUtils.encodeWAV(mergedPCM, sampleRate);\n\n // 调用适配器识别\n const result = await this.adapter.recognizeShortAudio(wavBuffer);\n this.emit('result', result);\n } catch (e: unknown) {\n const error = e as Error;\n this.emit('error', {\n code: 'ADAPTER_ERROR',\n message: error.message || '识别失败',\n originalError: e,\n });\n }\n }\n\n // 4. 清理资源\n this.cleanup();\n this.emit('audioend');\n this.emit('end');\n }\n\n abort(): void {\n this.isRecordingFlag = false;\n this.cleanup();\n this.emit('end');\n }\n\n isListening(): boolean {\n return this._status === RecognitionStatus.RECORDING;\n }\n\n /**\n * 清理资源\n */\n private cleanup(): void {\n // 清理重连定时器\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n // 关闭 WebSocket\n if (this.socket) {\n this.socket.close();\n this.socket = null;\n }\n\n // 断开音频节点\n this.workletNode?.disconnect();\n this.scriptProcessor?.disconnect();\n void this.audioContext?.close();\n\n // 移除可见性监听\n if (this.visibilityHandler && typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n this.visibilityHandler = null;\n }\n\n // 清理引用\n this.workletNode = null;\n this.scriptProcessor = null;\n this.audioContext = null;\n this.mediaStream = null;\n this.pcmChunks = [];\n this.totalPCMLength = 0;\n this.msgQueue = [];\n\n this.setStatus(RecognitionStatus.IDLE);\n }\n}\n\n// ============================================================================\n// 10. 主入口类 (Facade)\n// ============================================================================\n\n/**\n * 语音识别器实现\n * 统一封装原生识别和云端识别\n */\nexport class SpeechRecognizerImpl implements SpeechRecognizer {\n private strategy: BaseRecognitionStrategy | null = null;\n private config: IAdvancedRecognitionConfig = {};\n private _currentProvider: SpeechProviderType = 'browser';\n private _status: SpeechServiceStatus = 'idle';\n private eventHandlers: Map<RecognitionEventType, Set<RecognitionEventHandler>> = new Map();\n private customProviders: Map<SpeechProviderType, RecognitionProvider> = new Map();\n\n get currentProvider(): SpeechProviderType {\n return this._currentProvider;\n }\n\n get status(): SpeechServiceStatus {\n return this._status;\n }\n\n /**\n * 获取当前识别状态\n */\n get recognitionStatus(): RecognitionStatus {\n return this.strategy?.status ?? RecognitionStatus.IDLE;\n }\n\n /**\n * 初始化语音识别器\n */\n initialize(config?: RecognitionConfig): Promise<void> {\n this._status = 'loading';\n\n // 合并配置\n this.config = {\n lang: 'zh-CN',\n continuous: false,\n interimResults: true,\n maxAlternatives: 1,\n mode: 'auto',\n autoReconnect: true,\n maxReconnectAttempts: 3,\n reconnectInterval: 2000,\n audioConfig: {\n sampleRate: 16000,\n vadThreshold: 0.02,\n vadDuration: 3000,\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n ...config,\n } as IAdvancedRecognitionConfig;\n\n try {\n this.initializeStrategy();\n this._status = 'ready';\n return Promise.resolve();\n } catch (error) {\n this._status = 'error';\n return Promise.reject(error);\n }\n }\n\n /**\n * 初始化识别策略\n */\n private initializeStrategy(): void {\n const advConfig = this.config;\n const mode = advConfig.mode ?? 'auto';\n const hasNative =\n typeof window !== 'undefined' &&\n ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window);\n\n // 选择策略\n if (mode === 'native' || (mode === 'auto' && hasNative && !advConfig.cloudAdapter)) {\n const nativeStrategy = new NativeRecognitionStrategy(advConfig);\n if (!nativeStrategy.isAvailable()) {\n throw new Error('浏览器不支持原生语音识别');\n }\n this.strategy = nativeStrategy;\n this._currentProvider = 'browser';\n } else if (mode === 'cloud' || (mode === 'auto' && advConfig.cloudAdapter)) {\n if (!advConfig.cloudAdapter) {\n throw new Error('云端模式需要提供 cloudAdapter');\n }\n this.strategy = new CloudRecognitionStrategy(advConfig);\n this._currentProvider = 'custom';\n } else {\n throw new Error('没有可用的识别策略');\n }\n\n // 转发事件\n this.forwardStrategyEvents();\n }\n\n /**\n * 转发策略事件\n */\n private forwardStrategyEvents(): void {\n if (!this.strategy) return;\n\n this.strategy.on('result', res => {\n this.emit('result', {\n type: 'result',\n result: this.convertResult(res),\n });\n });\n\n this.strategy.on('error', err => {\n const errorEvent: RecognitionEvent = {\n type: 'error',\n error: {\n code: err.code,\n message: err.message,\n },\n };\n if (err.originalError) {\n errorEvent.error!.originalError = err.originalError as Error;\n }\n this.emit('error', errorEvent);\n });\n\n this.strategy.on('start', () => this.emit('start', { type: 'start' }));\n this.strategy.on('end', () => this.emit('end', { type: 'end' }));\n this.strategy.on('soundstart', () => this.emit('soundstart', { type: 'soundstart' }));\n this.strategy.on('soundend', () => this.emit('soundend', { type: 'soundend' }));\n this.strategy.on('speechstart', () => this.emit('speechstart', { type: 'speechstart' }));\n this.strategy.on('speechend', () => this.emit('speechend', { type: 'speechend' }));\n this.strategy.on('audiostart', () => this.emit('audiostart', { type: 'audiostart' }));\n this.strategy.on('audioend', () => this.emit('audioend', { type: 'audioend' }));\n }\n\n /**\n * 转换识别结果格式\n */\n private convertResult(res: IRecognitionResult): RecognitionResult {\n return {\n results: [\n {\n transcript: res.transcript,\n confidence: res.confidence,\n isFinal: res.isFinal,\n },\n ],\n bestTranscript: res.transcript,\n bestConfidence: res.confidence,\n isFinal: res.isFinal,\n };\n }\n\n /**\n * 开始识别\n */\n async start(config?: RecognitionConfig): Promise<void> {\n if (this._status !== 'ready') {\n throw new Error('识别器未就绪');\n }\n\n if (config) {\n // 更新配置并重新初始化\n this.config = { ...this.config, ...config } as IAdvancedRecognitionConfig;\n this.initializeStrategy();\n }\n\n return this.strategy?.start();\n }\n\n /**\n * 停止识别\n */\n stop(): void {\n this.strategy?.stop();\n }\n\n /**\n * 中止识别\n */\n abort(): void {\n this.strategy?.abort();\n }\n\n /**\n * 是否正在识别\n */\n isListening(): boolean {\n return this.strategy?.isListening() ?? false;\n }\n\n /**\n * 添加事件监听\n */\n on(event: RecognitionEventType, handler: RecognitionEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * 移除事件监听\n */\n off(event: RecognitionEventType, handler: RecognitionEventHandler): void {\n this.eventHandlers.get(event)?.delete(handler);\n }\n\n /**\n * 触发事件\n */\n private emit(type: RecognitionEventType, event: RecognitionEvent): void {\n this.eventHandlers.get(type)?.forEach(handler => {\n try {\n handler(event);\n } catch (e) {\n console.error('[SpeechRecognizer] 事件处理器错误:', e);\n }\n });\n }\n\n /**\n * 销毁实例\n */\n dispose(): void {\n this.strategy?.dispose();\n this.strategy = null;\n this.eventHandlers.clear();\n this._status = 'idle';\n }\n\n /**\n * 注册自定义提供商\n */\n registerProvider(type: SpeechProviderType, provider: RecognitionProvider): void {\n this.customProviders.set(type, provider);\n }\n\n /**\n * 使用云端适配器\n */\n useCloudAdapter(adapter: ICloudRecognitionAdapter): void {\n this.config.cloudAdapter = adapter;\n this.config.mode = 'cloud';\n }\n}\n\n// ============================================================================\n// 11. 工厂函数和工具函数\n// ============================================================================\n\n/**\n * 获取浏览器的 SpeechRecognition 构造函数\n */\nfunction getSpeechRecognitionConstructor(): BrowserSpeechRecognitionConstructor | null {\n if (typeof window === 'undefined') {\n return null;\n }\n return (\n (window.SpeechRecognition as BrowserSpeechRecognitionConstructor | undefined) ??\n (window.webkitSpeechRecognition as BrowserSpeechRecognitionConstructor | undefined) ??\n null\n );\n}\n\n/**\n * 创建语音识别器实例\n * @param config 识别配置\n * @returns 语音识别器实例\n *\n * @example\n * ```typescript\n * // 使用原生识别\n * const recognizer = await createSpeechRecognizer({\n * lang: 'zh-CN',\n * continuous: true,\n * });\n *\n * // 使用云端识别 (百度)\n * const baiduAdapter = new BaiduAdapter('your-access-token');\n * const cloudRecognizer = await createSpeechRecognizer({\n * mode: 'cloud',\n * cloudAdapter: baiduAdapter,\n * transport: 'http',\n * });\n *\n * recognizer.on('result', (event) => {\n * console.log('识别结果:', event.result?.bestTranscript);\n * });\n *\n * await recognizer.start();\n * ```\n */\nexport async function createSpeechRecognizer(\n config?: RecognitionConfig | IAdvancedRecognitionConfig\n): Promise<SpeechRecognizer> {\n const recognizer = new SpeechRecognizerImpl();\n await recognizer.initialize(config);\n return recognizer;\n}\n\n/**\n * 检查当前环境是否支持语音识别\n * @returns 是否支持\n */\nexport function isSpeechRecognitionSupported(): boolean {\n return getSpeechRecognitionConstructor() !== null;\n}\n\n/**\n * 快速进行一次语音识别\n * @param config 识别配置\n * @returns 识别结果\n *\n * @example\n * ```typescript\n * const result = await listen({ lang: 'zh-CN' });\n * console.log('识别结果:', result.bestTranscript);\n * ```\n */\nexport async function listen(\n config?: RecognitionConfig | IAdvancedRecognitionConfig\n): Promise<RecognitionResult> {\n const recognizer = await createSpeechRecognizer({\n ...config,\n continuous: false,\n });\n\n return new Promise((resolve, reject) => {\n let hasResult = false;\n\n recognizer.on('result', event => {\n if (event.result && event.result.isFinal) {\n hasResult = true;\n recognizer.dispose();\n resolve(event.result);\n }\n });\n\n recognizer.on('error', event => {\n recognizer.dispose();\n reject(event.error);\n });\n\n recognizer.on('end', () => {\n if (!hasResult) {\n recognizer.dispose();\n resolve({\n results: [],\n bestTranscript: '',\n bestConfidence: 0,\n isFinal: true,\n });\n }\n });\n\n recognizer.start().catch(reject);\n });\n}\n\n/**\n * 创建带超时的语音识别\n * @param config 识别配置\n * @param timeout 超时时间 (ms)\n * @returns 识别结果\n */\nexport async function listenWithTimeout(\n config?: RecognitionConfig | IAdvancedRecognitionConfig,\n timeout: number = 10000\n): Promise<RecognitionResult> {\n return Promise.race([\n listen(config),\n new Promise<RecognitionResult>((_, reject) => {\n setTimeout(() => reject(new Error('识别超时')), timeout);\n }),\n ]);\n}\n\n/**\n * [使用示例 - 原生识别]\n *\n * const recognizer = await createSpeechRecognizer({\n * lang: 'zh-CN',\n * continuous: true,\n * interimResults: true,\n * });\n *\n * recognizer.on('result', (event) => {\n * console.log(event.result?.bestTranscript);\n * });\n *\n * recognizer.on('error', (event) => {\n * console.error(event.error?.message);\n * });\n *\n * await recognizer.start();\n */\n\n/**\n * [使用示例 - 云端识别 (百度)]\n *\n * const adapter = new BaiduAdapter('your-access-token', 'appId', 'appKey');\n * const recognizer = await createSpeechRecognizer({\n * mode: 'cloud',\n * transport: 'websocket', // 或 'http'\n * cloudAdapter: adapter,\n * audioConfig: {\n * vadDuration: 2000,\n * vadThreshold: 0.03,\n * },\n * autoReconnect: true,\n * });\n *\n * recognizer.on('result', (event) => {\n * if (event.result?.isFinal) {\n * console.log('最终结果:', event.result.bestTranscript);\n * }\n * });\n *\n * await recognizer.start();\n */\n\n/**\n * [使用示例 - 自定义 BFF 适配器]\n *\n * const adapter = new GenericAdapter('https://api.yoursite.com/speech');\n * const recognizer = await createSpeechRecognizer({\n * mode: 'cloud',\n * transport: 'http',\n * cloudAdapter: adapter,\n * });\n */\n"]}
@@ -1,97 +1,97 @@
1
1
  'use strict';
2
2
 
3
- var chunkQ7XG6YN6_cjs = require('../chunk-Q7XG6YN6.cjs');
3
+ var chunkV5THPEB2_cjs = require('../chunk-V5THPEB2.cjs');
4
4
  require('../chunk-PK6SKIKE.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "Bind", {
9
9
  enumerable: true,
10
- get: function () { return chunkQ7XG6YN6_cjs.Bind; }
10
+ get: function () { return chunkV5THPEB2_cjs.Bind; }
11
11
  });
12
12
  Object.defineProperty(exports, "Container", {
13
13
  enumerable: true,
14
- get: function () { return chunkQ7XG6YN6_cjs.Container; }
14
+ get: function () { return chunkV5THPEB2_cjs.Container; }
15
15
  });
16
16
  Object.defineProperty(exports, "Debounce", {
17
17
  enumerable: true,
18
- get: function () { return chunkQ7XG6YN6_cjs.Debounce; }
18
+ get: function () { return chunkV5THPEB2_cjs.Debounce; }
19
19
  });
20
20
  Object.defineProperty(exports, "Deprecated", {
21
21
  enumerable: true,
22
- get: function () { return chunkQ7XG6YN6_cjs.Deprecated; }
22
+ get: function () { return chunkV5THPEB2_cjs.Deprecated; }
23
23
  });
24
24
  Object.defineProperty(exports, "Disposable", {
25
25
  enumerable: true,
26
- get: function () { return chunkQ7XG6YN6_cjs.Disposable; }
26
+ get: function () { return chunkV5THPEB2_cjs.Disposable; }
27
27
  });
28
28
  Object.defineProperty(exports, "DisposableStore", {
29
29
  enumerable: true,
30
- get: function () { return chunkQ7XG6YN6_cjs.DisposableStore; }
30
+ get: function () { return chunkV5THPEB2_cjs.DisposableStore; }
31
31
  });
32
32
  Object.defineProperty(exports, "EventEmitter", {
33
33
  enumerable: true,
34
- get: function () { return chunkQ7XG6YN6_cjs.EventEmitter; }
34
+ get: function () { return chunkV5THPEB2_cjs.EventEmitter; }
35
35
  });
36
36
  Object.defineProperty(exports, "Frozen", {
37
37
  enumerable: true,
38
- get: function () { return chunkQ7XG6YN6_cjs.Frozen; }
38
+ get: function () { return chunkV5THPEB2_cjs.Frozen; }
39
39
  });
40
40
  Object.defineProperty(exports, "Inject", {
41
41
  enumerable: true,
42
- get: function () { return chunkQ7XG6YN6_cjs.Inject; }
42
+ get: function () { return chunkV5THPEB2_cjs.Inject; }
43
43
  });
44
44
  Object.defineProperty(exports, "Injectable", {
45
45
  enumerable: true,
46
- get: function () { return chunkQ7XG6YN6_cjs.Injectable; }
46
+ get: function () { return chunkV5THPEB2_cjs.Injectable; }
47
47
  });
48
48
  Object.defineProperty(exports, "Lifecycle", {
49
49
  enumerable: true,
50
- get: function () { return chunkQ7XG6YN6_cjs.Lifecycle; }
50
+ get: function () { return chunkV5THPEB2_cjs.Lifecycle; }
51
51
  });
52
52
  Object.defineProperty(exports, "Log", {
53
53
  enumerable: true,
54
- get: function () { return chunkQ7XG6YN6_cjs.Log; }
54
+ get: function () { return chunkV5THPEB2_cjs.Log; }
55
55
  });
56
56
  Object.defineProperty(exports, "Memoize", {
57
57
  enumerable: true,
58
- get: function () { return chunkQ7XG6YN6_cjs.Memoize; }
58
+ get: function () { return chunkV5THPEB2_cjs.Memoize; }
59
59
  });
60
60
  Object.defineProperty(exports, "Retry", {
61
61
  enumerable: true,
62
- get: function () { return chunkQ7XG6YN6_cjs.Retry; }
62
+ get: function () { return chunkV5THPEB2_cjs.Retry; }
63
63
  });
64
64
  Object.defineProperty(exports, "Sealed", {
65
65
  enumerable: true,
66
- get: function () { return chunkQ7XG6YN6_cjs.Sealed; }
66
+ get: function () { return chunkV5THPEB2_cjs.Sealed; }
67
67
  });
68
68
  Object.defineProperty(exports, "Singleton", {
69
69
  enumerable: true,
70
- get: function () { return chunkQ7XG6YN6_cjs.Singleton; }
70
+ get: function () { return chunkV5THPEB2_cjs.Singleton; }
71
71
  });
72
72
  Object.defineProperty(exports, "Throttle", {
73
73
  enumerable: true,
74
- get: function () { return chunkQ7XG6YN6_cjs.Throttle; }
74
+ get: function () { return chunkV5THPEB2_cjs.Throttle; }
75
75
  });
76
76
  Object.defineProperty(exports, "Timeout", {
77
77
  enumerable: true,
78
- get: function () { return chunkQ7XG6YN6_cjs.Timeout; }
78
+ get: function () { return chunkV5THPEB2_cjs.Timeout; }
79
79
  });
80
80
  Object.defineProperty(exports, "Validate", {
81
81
  enumerable: true,
82
- get: function () { return chunkQ7XG6YN6_cjs.Validate; }
82
+ get: function () { return chunkV5THPEB2_cjs.Validate; }
83
83
  });
84
84
  Object.defineProperty(exports, "combineDisposables", {
85
85
  enumerable: true,
86
- get: function () { return chunkQ7XG6YN6_cjs.combineDisposables; }
86
+ get: function () { return chunkV5THPEB2_cjs.combineDisposables; }
87
87
  });
88
88
  Object.defineProperty(exports, "globalContainer", {
89
89
  enumerable: true,
90
- get: function () { return chunkQ7XG6YN6_cjs.globalContainer; }
90
+ get: function () { return chunkV5THPEB2_cjs.globalContainer; }
91
91
  });
92
92
  Object.defineProperty(exports, "toDisposable", {
93
93
  enumerable: true,
94
- get: function () { return chunkQ7XG6YN6_cjs.toDisposable; }
94
+ get: function () { return chunkV5THPEB2_cjs.toDisposable; }
95
95
  });
96
96
  //# sourceMappingURL=index.cjs.map
97
97
  //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- export { Bind, Container, Debounce, Deprecated, Disposable, DisposableStore, EventEmitter, Frozen, Inject, Injectable, Lifecycle, Log, Memoize, Retry, Sealed, Singleton, Throttle, Timeout, Validate, combineDisposables, globalContainer, toDisposable } from '../chunk-2PXWQDZC.js';
1
+ export { Bind, Container, Debounce, Deprecated, Disposable, DisposableStore, EventEmitter, Frozen, Inject, Injectable, Lifecycle, Log, Memoize, Retry, Sealed, Singleton, Throttle, Timeout, Validate, combineDisposables, globalContainer, toDisposable } from '../chunk-MBBJMHTS.js';
2
2
  import '../chunk-7QVYU63E.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map