UNPKG

@minto-ai/xunfei-tts

Version:

借助“讯飞在线语音合成API”实现浏览器端“文本转语音

113 lines (95 loc) 3.48 kB
import type { SerialTaskExecuteContext } from '../handler' import type { BusinessParams, PrivateCustomEventName, SystemConfig } from '../types' import { createWebSocket } from '@minto-ai/tools' import CryptoJS from 'crypto-js' import { SerialHandler } from '../handler' import { createEventBus, encodeText } from '../utils' const $bus = createEventBus<PrivateCustomEventName>() const defaultBusinessParams: BusinessParams = { aue: 'raw', sfl: 1, auf: 'audio/L16;rate=16000', vcn: 'xiaoyan', speed: 50, volume: 50, pitch: 50, bgs: 0, tte: 'UTF8', reg: '2', rdn: '0', } class TtsRequest extends SerialHandler<string, string> { private systemConfig!: SystemConfig private businessParams!: BusinessParams private webSockeSet: Set<WebSocket> = new Set() public initProperty(systemConfig: SystemConfig, businessParams: Partial<BusinessParams>): void { this.systemConfig = systemConfig this.businessParams = { ...defaultBusinessParams, ...businessParams } } public execute( context: SerialTaskExecuteContext<string, string>, ): void { if (context.isLastExecute) { this.taskCompletedCallback() return } const webSocketInstance = createWebSocket(this.generateRequestUrl()) this.webSockeSet.add(webSocketInstance) webSocketInstance.addEventListener('open', async () => { webSocketInstance.send(JSON.stringify(this.generateRequestParams(context.taskItem.original!))) webSocketInstance.addEventListener('message', (response: any) => { const { code, data } = JSON.parse(response.data) const { audio: audioData, status } = data if (code === 0) { if (audioData) { this.forwardToHandler(audioData) } } if (status === 2) { this.webSockeSet.delete(webSocketInstance) webSocketInstance.close() this.taskCompletedCallback() } }) }) } private generateRequestParams(text: string): any { return { common: { app_id: this.systemConfig.APPID, }, business: { ...this.businessParams, }, data: { status: 2, text: encodeText(text, this.businessParams.tte!), }, } } private generateRequestUrl(): string { const apiKey = this.systemConfig.API_KEY const apiSecret = this.systemConfig.API_SECRET let url = 'wss://tts-api.xfyun.cn/v2/tts' const { host } = window.location const date = (new Date() as any).toGMTString() const algorithm = 'hmac-sha256' const headers = 'host date request-line' const signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/tts HTTP/1.1` const signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret) const signature = CryptoJS.enc.Base64.stringify(signatureSha) const authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"` const authorization = btoa(authorizationOrigin) url = `${url}?authorization=${authorization}&date=${date}&host=${host}` return url } protected onFinish(): void { $bus.emit('_ttsRequestFinish') if (this.webSockeSet && this.webSockeSet.size) { this.webSockeSet.forEach(ws => ws.close()) this.webSockeSet.clear() } this.webSockeSet = new Set() } } export default TtsRequest