@minto-ai/xunfei-tts
Version:
借助“讯飞在线语音合成API”实现浏览器端“文本转语音
82 lines (66 loc) • 2.42 kB
text/typescript
import type { SerialTaskExecuteContext } from '../handler'
import type { PrivateCustomEventName } from '../types'
import { SerialHandler } from '../handler'
import { createEventBus } from '../utils'
const $bus = createEventBus<PrivateCustomEventName>()
class AudioActuator extends SerialHandler<string, any> {
private audioContext: AudioContext = new AudioContext()
private bufferSource: AudioBufferSourceNode | null = null
private gainNode: GainNode | null = null
private volume = 1
public execute(
context: SerialTaskExecuteContext<string, any>,
): void {
if (context.isLastExecute) {
this.taskCompletedCallback()
return
}
const audioBuffer = this.audioContext.createBuffer(1, context.taskItem.original!.length, 22050)
const nowBuffering = audioBuffer.getChannelData(0)
if (audioBuffer.copyToChannel) {
audioBuffer.copyToChannel(new Float32Array(context.taskItem.original! as any), 0, 0)
}
else {
for (let i = 0; i < context.taskItem.original!.length; i += 1) {
nowBuffering[i] = context.taskItem.original![i] as any
}
}
this.bufferSource = this.audioContext.createBufferSource()
this.bufferSource.buffer = audioBuffer
// 获取音量控制节点
this.gainNode = this.audioContext.createGain()
this.bufferSource.connect(this.gainNode)
this.gainNode.connect(this.audioContext.destination)
// 调整音量
this.gainNode.gain.setValueAtTime(this.volume, this.audioContext.currentTime)
this.bufferSource.start()
this.bufferSource.addEventListener('ended', () => {
this.taskCompletedCallback()
})
}
protected onFinish(): void {
if (this.bufferSource) {
this.bufferSource.stop()
this.bufferSource = null
}
if (this.gainNode) {
this.gainNode.disconnect()
this.gainNode = null
}
if (this.audioContext) {
this.audioContext.suspend()
this.audioContext = new AudioContext()
}
$bus.emit('_audioActuatorFinish')
}
protected onBeforeFirstExecute(): void {
$bus.emit('_audioActuatorBeforeFirstExecute')
}
public setVolume(volume: number): void {
if (this.gainNode) {
this.gainNode.gain.setValueAtTime(volume, this.audioContext.currentTime)
}
this.volume = volume
}
}
export default AudioActuator