Electron + Vue 搭建桌面 TTS 工具的技术选型
MiMo TTS Studio 是一个桌面配音工作台,集成小米 MiMo-V2.5-TTS 引擎,支持多角色音色管理、批量并发生成、波形可视化和 WAV/MP3 导出。本文记录技术选型的核心考量。
架构概览
graph TD
subgraph "Electron 主进程"
M["main.js"] --> C["Controller/tts.js"]
C --> S["Service/tts.js"]
S --> API["小米 TTS API"]
S --> FS["文件系统"]
end
subgraph "Vue 渲染进程"
UI["Vue 3 + Naive UI"] --> IPC["IPC Bridge"]
IPC --> M
end
subgraph "preload"
BR["bridge.js"] -->|"contextBridge"| UI
end
项目基于 electron-egg 框架,采用 Controller → Service 的 MVC 分层。前后端通过 IPC 通信,渲染进程通过 contextBridge 暴露的 ipcRenderer 访问 Node.js API。
为什么选 Electron + Vue?
三个核心原因:
1. 本地文件系统访问:TTS 工具需要读写音频文件、管理缓存、导出 WAV/MP3。Web 应用无法直接操作文件系统,Electron 通过 Node.js 的 fs 模块完全解决这个问题。
2. 跨平台桌面体验:一次开发,Windows/macOS/Linux 三端运行。对于工具类应用,桌面体验(窗口管理、系统托盘、本地通知)比 Web 应用更自然。
3. Vue 3 生态成熟:Composition API + Pinia 状态管理 + Naive UI 组件库,开发效率高。Vite 做构建工具,热更新速度快。
IPC 通信:前后端的安全桥接
Electron 的安全模型要求渲染进程不能直接访问 Node.js API。项目通过 contextBridge 暴露安全的 IPC 接口:
1 | // app/electron/preload/bridge.js — 直接暴露整个 ipcRenderer 对象 |
渲染进程通过封装的 invoke 函数调用主进程,超时机制防止请求挂起:
1 | // app/frontend/src/utils/ipcRenderer.js |
注意:超时默认 60 秒而非 30 秒,且 bridge.js 直接暴露整个 ipcRenderer 对象,不做方法包装。
TTS 引擎接入
小米 MiMo-V2.5-TTS 引擎通过 REST API 接入。Service 层封装了 API 调用、重试和缓存(以下为简化示意,实际实现包含完整的错误处理和重试逻辑):
1 | // app/electron/service/tts.js — 简化示意 |
缓存键用 djb2 哈希算法,由 _buildCacheKey(text, voiceId, speed, styleDesc, format, useVoiceDesign, useVoiceClone, provider) 构建。
批量生成时,通过信号量(_acquireSlot / _releaseSlot)控制并发数,单条失败不影响整体:
1 | // frontend/src/views/mimo/store/ttsStore.js — 简化示意 |
波形可视化
渲染进程接收音频 buffer 后,用 Web Audio API 解码并绘制波形:
1 | const audioContext = new AudioContext() |
这是纯前端能力,不需要 Node.js 参与,所以直接在渲染进程处理。
项目结构
1 | electron/ |
桌面应用的独特挑战
打包体积:Electron 应用打包后约 200MB+。通过 electron-builder 的 asar 压缩和 files 白名单排除不必要的文件,控制体积。
跨平台兼容:文件路径、字体渲染、音频播放三端表现不同。统一用 path.join() 处理路径,音频播放用 Web Audio API 避免平台差异。
自动更新:electron-builder 内置 autoUpdater,配合 GitHub Releases 或自建更新服务器实现静默更新。
选型的本质是匹配问题。桌面 + 文件系统 + 跨平台 = Electron 是最直接的解。