# 语音朗读 > 与 [开发构建.md](./开发构建.md) 中的 `src/main/voiceRead/` 目录树互为参照。 ## 语音朗读 **多 TTS 引擎 Provider**(含 **小米 MiMo**)、**多套朗读方案**、**单音色 / 旁白·对白多音色**、**AI 说话人识别**(可选 **情绪标注**)与 **角色专属音色**;与 [开发构建.md](./开发构建.md) 目录树、**`src/main/voiceRead/`**、**`useAppVoiceRead.ts`** 互为参照。 ### 功能与入口 | 项目 | 说明 | | ---- | ---- | | 顶栏 | **`VoiceReadToolbar.vue`**:播放 / 暂停 / 停止、上一行 / 下一行、**音量**滑块、合成状态指示;**定时滚动** 开启时朗读入口禁用(见 **「定时滚动」**) | | 设置 | **设置 → 语音朗读**(**`SettingsVoiceReadPanel.vue`**);**不依赖** AI 总开关(与向量/角色卡页签不同) | | 角色卡 | 侧栏 **「角色」** 编辑面板:多音色方案下可为角色指定 **`voiceReadVoiceId`** 与试听样句 | | 播放限制 | 正在播放(非暂停)时 **`isVoiceReadNavigationBlocked`**:`App.vue` 拦截侧栏 tab 切换;**`ReaderMain`** 禁止打开查找栏 | | 朗读中快捷键 | **`shortcutService`** 的 **`VOICE_READ_SCROLL_BLOCKED_ACTIONS`**:仅吞掉行滚/页滚/上下章/查找;字号等其它快捷键仍可用 | | 与定时滚动 | 朗读与定时滚动互斥;朗读进行中 **`useAppTimedScroll`** 会停止定时滚动 | | 试听 | 设置页试听音频在**切换设置 tab** 或**关闭设置面板**时由 **`cancelPreview`** 停止 | ### TTS 引擎(`@shared/voiceReadEngines`) 主进程 **`voiceRead/providerRegistry.ts`** 统一 **`synthesize` / `listVoices` / `healthCheck`**;渲染侧经 **`voiceReadSynthesisClient.ts`** → preload IPC。 | 引擎 id | 显示名 | 实现 | 密钥 | 音频 | 说明 | | ------- | ------ | ---- | ---- | ---- | ---- | | `edge` | Edge TTS | **`edgeProvider`** + **`voiceReadEdgeTts.ts`** | 无 | MP3 | 微软 Neural 语音;静态音色表 **`voiceReadEdgeTtsVoices.ts`** | | `system` | 系统语音 | 渲染进程 Web Speech API | 无 | MP3 | 离线;**`speechSynthesis`** 动态枚举 | | `dashscope` | 阿里云通义 | **`dashscopeProvider`** | **`engineConfig.dashscopeApiKey`** | PCM | Qwen3-TTS;默认模型见 **`voiceReadDashscopeModels.ts`**(含 **`qwen3-tts-instruct-flash`**);支持 Instruct 自然语言语气 | | `minimax` | MiniMax | **`minimaxProvider`** | **`engineConfig.minimaxApiKey`** | MP3 | 动态 **`listVoices`**(系统 / 快速复刻 / 文生音色);默认 TTS 模型见 **`voiceReadMinimaxModels.ts`** | | `mimo` | 小米 MiMo | **`mimoProvider`** | **`engineConfig.mimoApiKey`** | MP3 | 三模型:**`mimo-v2.5-tts`**(预设音色)、**`-voicedesign`**(VoiceDesign 声音描述)、**`-voiceclone`**(VoiceClone 参考音频);预设音色见 **`voiceReadMimoVoices.ts`**;参考音频 Base64 缓存 | 通义 / MiniMax / MiMo 设置页均提供 **`AppConnectionTestButton`**(仅校验密钥,**不合成**)。 ### 朗读方案(`voiceReadProfiles`) 与对话 **`chatProfiles`** 类似,**最多 12 套**独立命名方案(**`@shared/voiceReadProfiles`**、**`useVoiceReadProfileDraft.ts`**)。 | 项目 | 说明 | | ---- | ---- | | 持久化 | **`colorTxt.ui.settings`** → **`voiceRead`**(引擎、方案 id、单/多音色字段;**不含**密钥明文;根级 **`engineConfig`** 亦剥密钥) | | 活跃方案 | **`activeVoiceReadProfileId`**;设置 **确定** 后写入运行时快照,并 **`persistVoiceReadSecretsToVault`** 写保险库 | | 方案内容 | 引擎 id、**`engineConfig`**(模型名)、**`scheme`**、单音色 **`single.voiceId`** 或多音色 **`multi.*`** | | API 密钥 | 各方案 **`dashscopeApiKey` / `minimaxApiKey` / `mimoApiKey`** 加密存 **`voiceRead.profileKeys`**(JSON,按 **profileId** 索引);**关窗不写**;与 AI 对话/文生图分槽 | ### 单音色 / 旁白·对白多音色(`scheme`) | `scheme` | 说明 | | -------- | ---- | | **`single`** | 全书一段音色朗读 | | **`multi`** | 旁白 + 对白分轨:可设旁白、默认对白、**男声对白**、**女声对白**;**对白引号样式**(`""` / `''` / `「」` / `『』` 多选) | | **AI 识别** | 多音色 + **AI 阅读助手已启用** 时可开 **`aiSpeakerRecognitionEnabled`**:朗读前主进程 **`attributeVoiceReadSpeakers`** **按行**识别说话人姓名、性别与情绪(输入为当前行原文 + 角色表姓名/别名,**不**检索全书;结果缓存于 **`voiceReadSpeakerCache.ts`**);匹配角色 **`voiceReadVoiceId`** 或按男女声回退;消耗对话 Token(可展示在设置/侧栏) | | **情绪标注** | AI 识别开启且引擎/模型支持时,可开 **`emotionEnabled`**(默认 true);关闭则合成时不传情绪。通义 **`qwen3-tts-instruct-flash`** / MiMo:AI 输出 **10~30 字自然语言** 语气描述 → **`mapEmotionForNaturalLanguageEngine`**;MiniMax:固定 **9 枚举**标签,无法映射则不传 | 渲染侧 **`voiceReadLineBuild.ts`** 切段、**`voiceReadVoiceResolve.ts`** 解析每段 voiceId(**`voiceReadEmotionActive`** 控制是否写入 `chunk.emotion`);**`voiceReadLinePlayer.ts`** 统一缓存与 IPC 合成入口。 ### API 密钥分开存储(通义 / MiniMax / MiMo) 同一开放平台账号可复用,但应用内**分槽**保存,互不同步。正式密钥均在 **`userData/ai/secrets.v1.json`**(见 **「API 密钥保险库」**),**`localStorage` 与 `config.json` 不含明文**。 | 功能 | 设置页 | 保险库 slot / 字段 | | ---- | ------ | ------------------ | | 语音朗读 · 通义 TTS | 语音朗读 | **`voiceRead.profileKeys`** → 方案 `dashscopeApiKey` | | 语音朗读 · MiniMax TTS | 语音朗读 | **`voiceRead.profileKeys`** → 方案 `minimaxApiKey` | | 语音朗读 · MiMo TTS | 语音朗读 | **`voiceRead.profileKeys`** → 方案 `mimoApiKey` | | AI 对话 · MiniMax | AI 阅读助手 | **`ai.chatProfileKeys`** → 方案 `apiKey` | | AI 对话 · 小米 MiMo | AI 阅读助手 | **`ai.chatProfileKeys`**(与 MiMo TTS 分开) | | 文生图 · MiniMax | 角色卡 | **`ai.txt2imgProfileKeys`** | | AI 对话 · 通义 | AI 阅读助手 | **`ai.chatProfileKeys`**(与朗读通义密钥分开) | | 文生图 · 通义万相 | 角色卡 | **`ai.txt2imgProfileKeys`**(与朗读通义密钥分开) | | 向量嵌入 · 远程 API | 向量模型 | **`ai.embedding.apiKey`** | ### IPC 与 preload | 通道 | 说明 | | ---- | ---- | | **`secrets:setVoiceReadSecrets`** | 写入 **`voiceRead.profileKeys`**(仅 `profileKeys` 参数);写后清除废弃槽 **`voiceRead.dashscopeApiKey`** | | **`secrets:getDeprecated`** / **`secrets:purgeDeprecated`** | 启动迁移读废弃 slot / 清盘 | | **`voiceRead:edgeTts`** | Edge 专用历史路径(`voiceReadEdgeTts.ts`) | | **`voiceRead:synthesize`** | 统一合成(Provider registry) | | **`voiceRead:listVoices`** | 动态音色列表(MiniMax / MiMo 等) | | **`voiceRead:healthCheck`** | 测试连接 | | **`voiceRead:attributeSpeakers`** | AI 按行识别对白说话人(`ai/voiceReadSpeaker.ts`;可选 **`includeEmotion`**) | preload:**`voiceReadSynthesize`**、**`voiceReadListVoices`**、**`voiceReadHealthCheck`**、**`voiceReadAttributeSpeakers`** 等(见 **`src/preload/index.ts`**)。 ### 源码速查 | 模块 | 职责 | | ---- | ---- | | **`useAppVoiceRead.ts`** | 朗读主循环、行跳转、合成 UI、退出清理 | | **`useAppTimedScroll.ts`** | 定时滚动开关、间隔 tick、与朗读/编辑/到底互斥 | | **`constants/timedScroll.ts`** | 定时滚动默认值与 merge | | **`services/voiceRead/voiceReadLinePlayer.ts`** | Edge/PCM 排播、预取、合成状态 | | **`services/voiceRead/minimaxVoiceCatalog.ts`** | MiniMax 音色目录缓存(设置页 / 角色卡) | | **`utils/voiceReadVoiceGroups.ts`** | 各引擎音色下拉分组 | | **`utils/voiceReadMimoVoiceSelect.ts`** | MiMo VoiceDesign / VoiceClone 音色选择 UI 逻辑 | | **`main/voiceRead/providers/*.ts`** | 各云端 TTS Provider | | **`shared/voiceReadEmotion.ts`** | **`voiceReadEmotionActive`**;通义 instruct / MiMo 自然语言 instructions;MiniMax 枚举映射 |