From a7d679d04fc3f9cde35220152190db1427c52551 Mon Sep 17 00:00:00 2001 From: cfy666 <3087823110@qq.com> Date: Sat, 13 Jun 2026 22:20:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/config.yaml | 3 ++ frontend/.gitignore | 4 ++ .../src/components/EdgeProcessor/index.tsx | 2 + frontend/vite.config.ts | 51 +++++++++++++++++-- 功能创意.md | 5 ++ 5 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 功能创意.md diff --git a/backend/config.yaml b/backend/config.yaml index cd6dc66..272e25b 100644 --- a/backend/config.yaml +++ b/backend/config.yaml @@ -18,10 +18,12 @@ ai: provider: mimo model: mimo-v2.5-asr endpoint: "https://api.xiaomimimo.com/v1" + api_key: "sk-c3jhv58rr5djhxw398w2rrij5tfpnpdgxqq1bojagshzviah" llm: provider: dashscope model: qwen3-vl-plus endpoint: "https://dashscope.aliyuncs.com/compatible-mode/v1" + api_key: "sk-ws-H.REHELLY.C4s3.MEUCIQCRee37XWEKp2szaxVLFDtR1rxNNsf372zMvCR0Xl6UvQIgZgvhRTvaa1FmhbCQJgaHu4Jny29AQkn01-3hX9CWBOg" timeout: 30 tts: provider: Xiaomi MiMo @@ -29,6 +31,7 @@ ai: voice: alloy speed: 1.0 endpoint: "https://token-plan-cn.xiaomimimo.com/v1" + api_key: "tp-c9e7scwfx94qvqyhpnahnw8uaiya01za2qzvg4xe24rp3xiv" timeout: 5 storage: diff --git a/frontend/.gitignore b/frontend/.gitignore index a547bf3..f3c1586 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -12,6 +12,10 @@ dist dist-ssr *.local +# VAD 静态资源(从 node_modules 自动复制) +public/silero_vad_*.onnx +public/vad.worklet.bundle.min.js + # Editor directories and files .vscode/* !.vscode/extensions.json diff --git a/frontend/src/components/EdgeProcessor/index.tsx b/frontend/src/components/EdgeProcessor/index.tsx index a7c83a6..a95abc2 100644 --- a/frontend/src/components/EdgeProcessor/index.tsx +++ b/frontend/src/components/EdgeProcessor/index.tsx @@ -48,6 +48,8 @@ export function useVAD(options?: VADOptions) { getStream: () => Promise.resolve(stream), startOnLoad: true, model: "legacy", + // 指向 node_modules 中的 WASM 文件(由 Vite 中间件提供) + onnxWASMBasePath: "/node_modules/onnxruntime-web/dist/", onSpeechStart: () => { setIsSpeaking(true); diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 8b0f57b..d3deedc 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,7 +1,52 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' +import fs from 'fs' +import path from 'path' + +const ortDistDir = path.resolve(__dirname, 'node_modules/onnxruntime-web/dist') +const vadDistDir = path.resolve(__dirname, 'node_modules/@ricky0123/vad-web/dist') +const publicDir = path.resolve(__dirname, 'public') + +// 需要复制到 public 的静态资源 +const staticFiles = [ + { src: vadDistDir, name: 'silero_vad_legacy.onnx' }, + { src: vadDistDir, name: 'silero_vad_v5.onnx' }, + { src: vadDistDir, name: 'vad.worklet.bundle.min.js' }, +] -// https://vite.dev/config/ export default defineConfig({ - plugins: [react()], -}) + plugins: [ + react(), + { + name: 'serve-vad-assets', + // 1. 启动时将 VAD 模型/工作线程复制到 public + configResolved() { + for (const { src, name } of staticFiles) { + const dest = path.join(publicDir, name) + if (!fs.existsSync(dest)) { + fs.copyFileSync(path.join(src, name), dest) + } + } + }, + // 2. 中间件拦截所有 WASM 相关请求,从原始路径提供文件 + configureServer(server) { + server.middlewares.use((req, res, next) => { + const url = req.url?.split('?')[0] ?? '' + // 匹配任意路径下的 ort-wasm 文件(包括 .vite/deps/ 和根路径) + const wasmMatch = url.match(/\/(ort-wasm-simd-threaded\.(mjs|wasm))$/) + if (wasmMatch) { + const fileName = wasmMatch[1] + const filePath = path.join(ortDistDir, fileName) + if (fs.existsSync(filePath)) { + res.setHeader('Content-Type', fileName.endsWith('.wasm') ? 'application/wasm' : 'application/javascript') + res.setHeader('Cache-Control', 'no-cache') + res.end(fs.readFileSync(filePath)) + return + } + } + next() + }) + }, + }, + ], +}) \ No newline at end of file diff --git a/功能创意.md b/功能创意.md new file mode 100644 index 0000000..5cf4036 --- /dev/null +++ b/功能创意.md @@ -0,0 +1,5 @@ +1.视频录制 +2.对话翻译 +3.对话总结 +4.手动对话功能 +5.视频框大小可调整,可最小化然后拖动 \ No newline at end of file