From b6157deec9a2938d51cca90bb0a93093af02b2e4 Mon Sep 17 00:00:00 2001 From: abearxiong Date: Tue, 23 Dec 2025 23:53:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E9=9F=B3=E9=A2=91?= =?UTF-8?q?=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=9C=80=E5=90=8E=E8=AF=86=E5=88=AB=E6=96=87=E6=9C=AC=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E7=9B=B8=E5=85=B3=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/astro.config.mjs | 2 +- web/package.json | 4 +- web/src/apps/muse/voice/modules/VadVoice.tsx | 44 ++++++++++++++++---- web/src/apps/muse/voice/store/relatime.ts | 26 +++++++----- web/src/apps/muse/voice/store/voiceStore.ts | 7 +++- 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/web/astro.config.mjs b/web/astro.config.mjs index 1e8cca7..a1c090d 100644 --- a/web/astro.config.mjs +++ b/web/astro.config.mjs @@ -7,7 +7,7 @@ import tailwindcss from '@tailwindcss/vite'; const isDev = process.env.NODE_ENV === 'development'; -let target = process.env.VITE_API_URL || 'http://localhost:51015'; +let target = process.env.VITE_API_URL || 'http://localhost:51515'; const apiProxy = { target: target, changeOrigin: true, ws: true, rewriteWsOrigin: true, secure: false, cookieDomainRewrite: 'localhost' }; let proxy = { diff --git a/web/package.json b/web/package.json index ea9523d..0052f1e 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/light-code-center", - "version": "0.0.1", + "version": "0.0.2", "description": "", "main": "index.js", "basename": "/root/light-code-center", @@ -8,7 +8,7 @@ "dev": "astro dev", "build": "astro build", "preview": "astro preview", - "pub": "envision deploy ./dist -k light-code-center -v 0.0.1 -u", + "pub": "envision deploy ./dist -k light-code-center -v 0.0.2 -u -y y", "ui": "pnpm dlx shadcn@latest add ", "sn": "pnpm dlx shadcn@latest add " }, diff --git a/web/src/apps/muse/voice/modules/VadVoice.tsx b/web/src/apps/muse/voice/modules/VadVoice.tsx index 76edb15..1a3f57e 100644 --- a/web/src/apps/muse/voice/modules/VadVoice.tsx +++ b/web/src/apps/muse/voice/modules/VadVoice.tsx @@ -363,7 +363,8 @@ export const VadVoice = () => { addVoice, setError: setStoreError, relatimeParialText, - relatimeFinalText + relatimeFinalText, + lastRecognizedText } = useVoiceStore(); const showText = relatimeFinalText || relatimeParialText; // 使用设置 store @@ -399,10 +400,11 @@ export const VadVoice = () => { onSpeechEnd: async (audio) => { try { const wavBuffer = utils.encodeWAV(audio) - const audioBlob = new Blob([wavBuffer], { type: 'audio/wav' }) - const tempUrl = URL.createObjectURL(audioBlob) const relatime = useVoiceStore.getState().relatime; relatime?.sendBase64?.(utils.arrayBufferToBase64(wavBuffer)); + const audioBlob = new Blob([wavBuffer], { type: 'audio/wav' }) + const tempUrl = URL.createObjectURL(audioBlob) + // 从实际音频文件获取准确时长 const getDuration = (): Promise => { return new Promise((resolve) => { @@ -413,8 +415,9 @@ export const VadVoice = () => { }); }); }; - + relatime?.showCostTime?.(); const duration = await getDuration(); + relatime?.showCostTime?.(); console.log(`Detected speech end. Duration: ${duration.toFixed(2)}s`); // 使用 store 添加语音记录 @@ -431,7 +434,9 @@ export const VadVoice = () => { onSpeechRealStart: () => { console.log('VAD real start'); setRealListen(true); - } + const relatime = useVoiceStore.getState().relatime; + relatime?.setStartTime?.(Date.now()); + }, }); ref.current = myvad; @@ -524,8 +529,8 @@ export const VadVoice = () => { voiceList.length === 0 ? (
🎤
-
No recordings yet
-
Start talking to record
+
暂无录音
+
开始说话以录音
) : ( @@ -537,8 +542,8 @@ export const VadVoice = () => { initializeVAD(listen) }}>
🎤
-
Click anywhere to initialize microphone
-
Browser requires user interaction for microphone access
+
点击任意位置以初始化麦克风
+
浏览器需要用户交互以访问麦克风
)} @@ -576,6 +581,27 @@ export const VadVoice = () => { )}
+ {lastRecognizedText && ( +
+
+ 🕘 上次识别: {lastRecognizedText} +
+
{ + // copy + navigator.clipboard.writeText(lastRecognizedText).then(() => { + toast.success('已复制', { + autoClose: 500, + position: 'top-center' + }); + }).catch((error) => { + console.error('复制失败:', error); + toast.error('复制失败,请手动选择文字复制'); + }); + }}> + +
+
+ )} {showText && (
diff --git a/web/src/apps/muse/voice/store/relatime.ts b/web/src/apps/muse/voice/store/relatime.ts index 3f4e1d0..5895937 100644 --- a/web/src/apps/muse/voice/store/relatime.ts +++ b/web/src/apps/muse/voice/store/relatime.ts @@ -5,6 +5,7 @@ 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) @@ -51,15 +52,20 @@ export class Relatime { } sendBase64(data: string) { if (!this.ready) return; - this.asr.ws.send(JSON.stringify({ voice: data, format: 'float32' })); - if (this.timeoutHandle) { - clearTimeout(this.timeoutHandle); - } - this.timeoutHandle = setTimeout(() => { - this.asr.sendBlankJson() - this.timeoutHandle = null; - }, 10000); // 5秒钟没有数据则发送空JSON保持连接 - + 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); } - } \ No newline at end of file diff --git a/web/src/apps/muse/voice/store/voiceStore.ts b/web/src/apps/muse/voice/store/voiceStore.ts index 3983edf..ea04852 100644 --- a/web/src/apps/muse/voice/store/voiceStore.ts +++ b/web/src/apps/muse/voice/store/voiceStore.ts @@ -26,6 +26,7 @@ interface VoiceState { setLoading: (loading: boolean) => void; relatime: Relatime; relatimeParialText: string; + lastRecognizedText: string; relatimeFinalText: string; setRelatimeParialText: (text: string) => void; setRelatimeFinalText: (text: string) => void; @@ -338,12 +339,14 @@ export const useVoiceStore = create()( relatimeFinalText: '', setRelatimeFinalText: (text: string) => { - set({ relatimeFinalText: text, relatimeParialText: '' }); + const { relatimeFinalText } = get(); + set(() => ({ relatimeFinalText: text, relatimeParialText: '', lastRecognizedText: relatimeFinalText })); }, setRelatimeParialText: (text: string) => { - set({ relatimeFinalText: '', relatimeParialText: text }); + set({ relatimeParialText: text }); }, relatimeParialText: '', + lastRecognizedText: '', }), { name: 'voice-store', // persist key