import { WSServer } from '@kevisual/video-tools/src/asr/ws.ts' import { useVoiceStore } from './voiceStore' export class Relatime { asr: WSServer ready = false timeoutHandle: NodeJS.Timeout | null = null startTime: number = 0 constructor() { // const url = new URL('/ws/asr', "http://localhost:51015") const url = new URL('/ws/asr', window.location.origin) url.searchParams.set('id', 'muse-voice-relatime') const ws = new WSServer({ url: url.toString(), onConnect: () => { console.log('WebSocket connected'); ws.emitter.on("message", (data) => { // console.log("Received message:", data.data); const json = JSON.parse(data.data); console.log('json', json); if (json && json.type === 'connected') { ws.ws.send(JSON.stringify({ type: 'init' })); } if (json && json.type === 'asr' && json.code === 200) { ws.emitter.emit('asr'); } if (json && json.type === 'partial' || json.type === 'result') { const text = json.text || ''; const isPartial = json.type === 'partial'; const isResult = json.type === 'result'; if (isPartial) { // 部分结果 useVoiceStore.getState().setRelatimeParialText(text); } else { // 最终结果 useVoiceStore.getState().setRelatimeFinalText(text); } } }); ws.emitter.once('asr', async () => { console.log('ASR ready'); this.ready = true; }); } }) this.asr = ws } send(data: Buffer) { if (!this.ready) return; const voice = data.toString('base64'); this.asr.ws.send(JSON.stringify({ voice })); } sendBase64(data: string) { if (!this.ready) return; console.log('send 花费时间:', Date.now() - this.startTime); this.asr.ws.send(JSON.stringify({ voice: data, format: 'float32', time: Date.now() })); // if (this.timeoutHandle) { // clearTimeout(this.timeoutHandle); // } // this.timeoutHandle = setTimeout(() => { // this.asr.sendBlankJson() // this.timeoutHandle = null; // }, 20000); // 20秒钟没有数据则发送空JSON保持连接 } setStartTime(time: number) { this.startTime = time; } showCostTime() { console.log('当前花费时间:', Date.now() - this.startTime); } }