UNPKG

@minto-ai/huoshan-tts

Version:

借助“火山引擎在线语音合成API”实现浏览器端“文本转语音

164 lines (129 loc) 4.59 kB
import type { InterfaceHandler } from './handler/core' import type { BusinessParams, PrivateCustomEventName, PublicCustomEventName, SystemConfig } from './types' import { AudioActuator, ByteBuffer, DecodeData, TextSplit, TtsRequest } from './process' import { SystemStatus } from './types' import { createEventBus } from './utils/event-bus' const $bus = createEventBus<PublicCustomEventName | PrivateCustomEventName>() class TtsController { private textSplitInstance: TextSplit = new TextSplit() private audioActuatorInstance: AudioActuator = new AudioActuator() private ttsRequestInstance: TtsRequest = new TtsRequest() private byteBufferInstance: ByteBuffer = new ByteBuffer() private decodeDataInstance: DecodeData = new DecodeData() public systemStatus: SystemStatus = SystemStatus.OFFLINE constructor(systemConfig: SystemConfig, businessParams: BusinessParams) { this.ttsRequestInstance.initProperty(systemConfig, businessParams) this.textSplitInstance.setExecuteController(this) this.ttsRequestInstance.setExecuteController(this) this.byteBufferInstance.setExecuteController(this) this.decodeDataInstance.setExecuteController(this) this.audioActuatorInstance.setExecuteController(this) this.textSplitInstance.linkHandler(this.ttsRequestInstance as unknown as InterfaceHandler) this.ttsRequestInstance.linkHandler(this.byteBufferInstance as unknown as InterfaceHandler) this.byteBufferInstance.linkHandler(this.decodeDataInstance as unknown as InterfaceHandler) this.decodeDataInstance.linkHandler(this.audioActuatorInstance as unknown as InterfaceHandler) this.bindEvent() } private bindEvent(): void { /** * 音频首次播放 */ $bus.on('_audioActuatorBeforeFirstExecute', () => { this.emit('audioFirstStart') }) $bus.on('_appError', (error) => { this.finish() this.emit('appError', error) }) $bus.on('_appFinish', () => { this.finish() }) } /** * 进入待机状态,等待传入文本数据 */ public start(): TtsController { if (this.systemStatus === SystemStatus.EXECUTE) { return this } this.textSplitInstance.triggerHandlerActive() this.ttsRequestInstance.triggerHandlerActive() this.byteBufferInstance.triggerHandlerActive() this.decodeDataInstance.triggerHandlerActive() this.audioActuatorInstance.triggerHandlerActive() this.systemStatus = SystemStatus.EXECUTE return this } /** * 传入文本数据 * * @param text 待转换的文本 */ public send(text: string): TtsController { if (this.systemStatus !== SystemStatus.EXECUTE) { return this } this.textSplitInstance.handle(text) return this } /** * 应用停止处理传入的文本,但是并不会停止音频播放 */ public end(): TtsController { if (this.systemStatus !== SystemStatus.EXECUTE) { return this } this.textSplitInstance.handle(null) this.textSplitInstance.isHandleDataAcceptedComplete = true return this } /** * 停止所有处理器,并且重置状态,触发 appFinish 事件 */ public finish(): void { if (this.systemStatus === SystemStatus.OFFLINE) { return } this.textSplitInstance.triggerHandlerFinish() this.ttsRequestInstance.triggerHandlerFinish() this.byteBufferInstance.triggerHandlerFinish() this.decodeDataInstance.triggerHandlerFinish() this.audioActuatorInstance.triggerHandlerFinish() this.systemStatus = SystemStatus.OFFLINE this.emit('appFinish') } private emit<T>(eventName: PublicCustomEventName, data?: T): void { $bus.emit(eventName, data) } public on(eventName: PublicCustomEventName, callback: (data?: any) => void): TtsController { $bus.on(eventName, callback) return this } /** * 静音 */ public mute(): void { this.audioActuatorInstance.mute() } /** * 取消静音 */ public unmute(): void { this.audioActuatorInstance.unmute() } /** * 检查音频权限 */ public checkAudioPermission(): Promise<boolean> { const audioContext: AudioContext = new AudioContext() if (audioContext.state === 'running') { audioContext.close() return Promise.resolve(true) } else { audioContext.close() return Promise.resolve(false) } } } export default TtsController