feat: 初始化 Mimo-TTS CLI 工具

- 实现文本转语音功能(支持多种音色)
- 支持流式输出(--stream)和直接播放(--play)
- 实现自动语气转换器(根据标点自动添加语气标签)
- 使用 crossterm 美化 CLI 输出
- 配置分层设计(项目配置 + 用户配置)
- 独立模块划分:api.rs, cli.rs, config.rs, tone.rs, ui.rs

v0.1.0
This commit is contained in:
2026-04-24 03:32:44 +08:00
commit be83f288a5
13 changed files with 5249 additions and 0 deletions

347
taolun.md Normal file
View File

@@ -0,0 +1,347 @@
# 讨论记录 (taolun.md)
## 2026-04-24 - 项目启动
### 用户需求
基于 Mimo-TTS API 开发 Rust CLI 工具,要求:
- Rust 编写,单一二进制可执行文件
- 后期通过 skill 给其他 claw 工具使用
- CLI 参数调用方式
- OOP + 设计模式架构
- 全程中文沟通
- 详细中文注释
- 每次操作前先更新文档
### API 信息
- Endpoint: `POST https://api.xiaomimimo.com/v1/chat/completions`
- 认证:双 Header (`api-key` + `Authorization: Bearer`)
- 音频格式WAVBase64 编码)
---
## 2026-04-24 - 实施记录
### 第一轮完成
1. ✅ 创建三个文档taolun.md、changelog.md、agents.md
2. ✅ 配置 Rust 国内源(稀疏索引协议)
3. ✅ 实现项目代码config.rs、api.rs、cli.rs、main.rs
4. ✅ Debug + Release 构建成功
5. ✅ 基本功能测试通过
### 第二轮修改
**用户新增需求:**
1. **project.config.toml**: 项目根目录,含 version与 git version 一致
2. **统一配置路径**:所有平台使用 `~/.config/tts/config.toml`
3. **API Key**: sk-csa6s3bvpwqw21zfs3urbmqgrw720eoa1qdz6o42abk5xoj8
4. **onboard 命令**CLI 引导式配置初始化
**执行内容:**
1. ✅ 创建 `project.config.toml` (version = "0.1.0")
2. ✅ 修改 `Cargo.toml`(移除 dirs添加 home 依赖)
3. ✅ 修改 `config.rs`(统一路径为 `~/.config/tts/config.toml`
4. ✅ 修改 `cli.rs`(添加 Onboard 子命令)
5. ✅ 修改 `main.rs`(处理 Onboard恢复 main() 函数)
6. ✅ 配置 API Key 成功
7. ✅ 语音合成测试成功test.wav、final_test.wav
8. ✅ Release 构建成功(无警告)
### 踩坑记录
1. **Cargo 国内源超时**
- 解决改用稀疏索引协议sparse+https://
2. **clap derive 模式缺少 Parser trait 导入**
- 解决:添加 `use clap::Parser;`
3. **main() 函数丢失**
- 原因:编辑时不小心删除
- 解决:恢复 main() 函数和 ExitCode 枚举
4. **配置文件路径统一**
- 需求:所有平台使用 `~/.config/tts/config.toml`
- 解决:使用 home 库获取家目录,手动拼接路径
### 项目最终状态
- **位置**: /Users/titor/tts
- **二进制**: target/release/mimo-tts (4.5MB)
- **配置**: ~/.config/tts/config.toml已配置 API Key
- **项目配置**: project.config.toml (version = "0.1.0")
- **功能**:
- ✅ TTS 语音合成
- ✅ 配置管理config set/show
- ✅ 引导式配置onboard
- ✅ 列出音色voices
- **架构**: Builder 模式 + Singleton 模式 + OOP
### 退出码规范
- 0: 成功
- 1: 参数错误
- 2: 配置错误
- 3: API 调用失败
- 4: 文件操作失败
## 2026-04-24 - 第三轮修改
### 用户新需求
**不要保存语音到本地,使用流式数据输出**
- 语音数据直接输出到 stdout二进制流
- 便于其他程序通过管道读取
- 更适合作为 claw skill 集成
### 修改计划
1. 修改 `synthesize()` 函数,返回音频数据而不是保存文件
2. 修改 `main.rs`,支持输出到 stdout二进制模式
3. 保留可选的 `--output` 参数用于保存到文件(向后兼容)
4. 当输出到 stdout 时,不输出其他文本信息(避免污染二进制流)
5. 流式调用可能需要使用 pcm16 格式(根据 API 文档)
## 2026-04-24 - 第四轮修改
### 用户新需求
**添加音频播放功能**
- 使用 rodio 库直接播放音频
- 添加 --play 参数触发播放模式
- 默认单次播放,不循环
- 保留 --output 和 stdout 输出功能
### 技术选型
- HTTP 客户端reqwest已使用
- 异步运行时tokio已使用
- 音频播放rodio 0.19
- WAV 处理无需额外库rodio 直接支持)
## 2026-04-24 - 第四轮实施完成
### 已完成
1. ✅ 修改 Cargo.toml 添加 rodio 0.19 依赖
2. ✅ 修改 cli.rs 添加 --play 参数
3. ✅ 修改 main.rs
- synthesize() 返回 Vec<u8>(音频数据)
- 添加 play_audio() 函数(使用 rodio 播放)
- 修改 run() 支持三种输出方式(播放/保存/stdout
4. ✅ 修复编译错误synthesize() 重复代码、未使用导入)
5. ✅ 修复 stdout 输出污染问题(移除 synthesize() 中的 println
6. ✅ Release 构建成功(无警告)
7. ✅ 功能测试通过:
- --play 播放音频 ✅
- --output 保存文件 ✅
- stdout 二进制流输出 ✅
### 最终项目状态
- 二进制文件target/release/mimo-tts (约 6MB包含 rodio)
- 支持三种输出方式:播放、保存、流式输出
- 所有功能测试通过
## 2026-04-24 - 第五轮修改
### 用户确认需求
**扩展音色支持**
1. ✅ 更新音色列表为 Mimo-TTS 完整列表8个音色
2. ✅ 默认音色从 default_zh 改为 mimo_default
3. ✅ 添加音色验证,无效时使用默认音色
4. ✅ 废弃 default_zh 和 default_en
### 完整音色列表
| Voice ID | 语言 | 性别 | 说明 |
|----------|------|------|------|
| mimo_default | 多语言 | - | MiMo默认中国集群=冰糖)|
| 冰糖 | 中文 | 女性 | 甜美清脆的女声 |
| 茉莉 | 中文 | 女性 | 温柔知性的女声 |
| 苏打 | 中文 | 男性 | 阳光活力的男声 |
| 白桦 | 中文 | 男性 | 沉稳大气的男声 |
| Mia | 英文 | 女性 | Sweet and gentle female |
| Chloe | 英文 | 女性 | Warm and articulate female |
| Milo | 英文 | 男性 | Energetic young male |
| Dean | 英文 | 男性 | Deep and steady male |
## 2026-04-24 - 第五轮修改(修复)
### 问题修复
- **默认音色未生效**config.rs 中 `default_voice()` 函数返回值仍是 `default_zh`
- 修复:将 `config.rs:39` 默认值改为 `mimo_default`
- 更新配置文件 `~/.config/tts/config.toml` 中的 `default_voice`
- 验证show-config 现在正确显示 `mimo_default`
## 2026-04-24 - 第六轮修改
### 用户需求
**UI 主题化所有 CLI 输出**
1. 使用 ratatui + crossterm 美化 CLI 输出
2. onboard 改为完整表单页面(同时显示所有配置项)
3. API Key 输入支持隐藏(显示 * 代替)
4. 所有命令输出都使用主题美化
5. 不需要简洁模式
### 实施方案
- 新增 src/ui.rs 模块(主题、组件)
- 修改 Cargo.toml 添加 ratatui + crossterm
- 美化 list_voices()、show_config() 输出
- 重写 onboard() 为完整交互式表单
- 美化所有命令输出(播放、保存等)
### 第六轮实施完成
1. ✅ 创建 src/ui.rs 模块(使用 crossterm 美化输出)
2. ✅ 修改 main.rs 引入 ui 模块
3. ✅ 美化 list_voices() 输出(彩色表格)
4. ✅ 美化 show_config() 输出(彩色标签)
5. ✅ 重写 onboard() 为交互式表单(支持密码隐藏输入)
6. ✅ 美化播放和保存完成消息
7. ✅ Release 构建成功(仅有未使用代码警告)
8. ✅ 功能测试通过voices、show-config
### 技术细节
- 使用 crossterm 而非完整的 ratatui Terminal简化实现
- 密码输入使用 enable_raw_mode 实现字符隐藏
- 输出使用颜色主题PRIMARY、SUCCESS、ERROR 等)
- show_onboard_form 返回 Result 类型,由调用者处理错误
### 第七轮修改
### 用户需求
**配置分层设计**
1. `project.config.toml` - 项目默认配置(全量配置)
- version
- base_url
- default_format
2. `~/.config/tts/config.toml` - 用户配置(仅覆盖项)
- api_key
- default_voice
3. 临时文件只允许存放在当前目录下
### 实施方案
- 修改 `project.config.toml` 添加 base_url 和 default_format
- 重写 `config.rs` 实现分层配置加载
- 修改 `cli.rs` 移除 base_url 参数
- 修改 `ui.rs` 简化显示和表单(只处理 api_key 和 default_voice
- 修改 `main.rs` 使用新的配置结构
- 测试时临时文件输出到当前目录
### 第七轮实施完成
1. ✅ 创建分层配置结构ProjectConfig + UserConfig + Config
2.`project.config.toml` 包含默认配置base_url、default_format
3. ✅ 用户配置只保存 api_key 和 default_voice
4. ✅ 修改 cli.rs 移除 base_url 参数
5. ✅ 修改 ui.rs 简化显示和表单
6. ✅ Release 构建成功(仅有未使用字段警告)
7. ✅ 功能测试通过show-config、voices、语音合成
8. ✅ 临时文件生成在当前目录
### 技术细节
- ConfigManager 先加载项目配置,再加载用户配置,最后合并
- save() 只保存 UserConfigapi_key、default_voice
- project.config.toml 从当前项目目录读取
- 用户配置路径:`~/.config/tts/config.toml`
## 2026-04-24 - 第八轮修改
### 用户反馈
**使用 --voice 提示失败**
- 问题:使用 `--voice '茉莉'` 时报错Unknown voice
- 原因:之前使用了错误的 API 文档,实际 API 只支持 3 个预置音色
- 最新发现mimo-v2.5-tts 模型支持更多音色9 个)
- 模型名应为 `mimo-v2.5-tts`(不是 `mimo-v2-tts`
### 音色列表mimo-v2.5-tts
| Voice ID | 语言 | 性别 | 说明 |
|----------|------|------|------|
| mimo_default | 多语言 | - | MiMo默认中国集群=冰糖)|
| 冰糖 | 中文 | 女性 | 甜美清脆的女声 |
| 茉莉 | 中文 | 女性 | 温柔知性的女声 |
| 苏打 | 中文 | 男性 | 阳光活力的男声 |
| 白桦 | 中文 | 男性 | 沉稳大气的男声 |
| Mia | 英文 | 女性 | Sweet and gentle female |
| Chloe | 英文 | 女性 | Warm and articulate female |
| Milo | 英文 | 男性 | Energetic young male |
| Dean | 英文 | 男性 | Deep and steady male |
### 新增功能
- `--style` 参数:风格描述(如:开心、东北话、孙悟空、唱歌等)
- 风格通过 `user` 消息传递(不是 `<style>` 标签)
- 模型名更新为 `mimo-v2.5-tts`
### 第八轮实施完成
1. ✅ 更新模型名为 `mimo-v2.5-tts`
2. ✅ 恢复 9 个音色列表
3. ✅ 添加 `--style` 参数支持
4. ✅ 修改风格传递方式(用 user 消息而非 `<style>` 标签)
5. ✅ 修复编译错误(删除多余代码块)
6. ✅ 测试通过(默认音色、茉莉音色均正常)
7. ✅ 临时文件生成在当前目录
## 2026-04-24 - 第九轮修改
### 用户需求
**实现流式输出功能**
- `--stream` 参数已在 cli.rs 定义,需要实现
- 流式输出时格式自动改为 pcm16
- 使用流式 API 调用Server-Sent Events
- 输出到 stdout二进制流
### 实施方案
- 修改 api.rs 添加流式请求方法
- 使用 reqwest 的流式响应处理
- 处理 SSEServer-Sent Events格式
- 拼接音频数据后输出到 stdout
- 如果指定了 --output则保存到文件
### 第九轮实施完成
1. ✅ 修改 Cargo.toml 添加依赖futures、tokio-util、reqwest stream feature
2. ✅ 修改 main.rs
- synthesize() 函数添加 stream 参数
- 流式输出时自动使用 pcm16 格式
- 传递 stream 参数给 API 调用
- 支持 --stream 和 --play 同时使用PCM16 转 WAV
3. ✅ 修改 api.rs
- 修复 read_stream_response 函数(使用 futures::StreamExt
- 正确处理 SSE 格式流式响应
4. ✅ 新增 pcm16_to_wav() 函数(封装 WAV 头)
5. ✅ Release 构建成功(仅有未使用代码警告)
6. ✅ 流式输出测试通过PCM16 数据正常)
7. ✅ 流式播放测试通过(--stream --play 正常工作)
### 技术细节
- 流式 API 返回原始 PCM16 数据(无 WAV 头)
- 使用 futures::StreamExt 处理 reqwest 的 bytes_stream()
- SSE 格式解析:`data: {...}``data: [DONE]`
- 每个 chunk 包含 Base64 编码的音频数据
- PCM16 转 WAV添加 44 字节 WAV 头24000Hz, 16bit, mono
- --stream 和 --play 同时使用时自动封装 WAV 格式后播放
## 2026-04-24 - 第十轮修改
### 用户需求
**实现自动语气转换器(独立模块)**
- 创建 `src/tone.rs` 独立模块(高内聚低耦合)
- 默认启用,无需额外参数
- 根据标点符号自动添加语气标签
- 支持整体风格标签和细粒度控制标签
### 语气映射规则
#### 整体风格标签(文本开头)
- 包含 ```[激动]`
- 包含 ```[疑惑]`
- 包含 `。``[平静]`(默认)
- 多种标点组合 → `[激动 疑惑]`
#### 细粒度控制标签(文本中间)
- ```!(激动)`
- ```?(疑惑)`
- `。``。(停顿)`
- `……``……(拖长音)`
### 第十轮实施完成
1. ✅ 创建 src/tone.rs 模块
2. ✅ 实现 apply_tone() 函数(整体语气)
3. ✅ 实现 insert_mid_tone() 函数(细粒度控制)
4. ✅ 实现 analyze_tone() 函数(分析语气)
5. ✅ 实现 has_tone_tag() 函数(检测已有标签)
6. ✅ 修改 main.rs 引入 tone 模块
7. ✅ 在 synthesize() 中调用语气转换
8. ✅ Release 构建成功
9. ✅ 单元测试通过4 个测试)
10. ✅ 功能测试通过(激动语气、疑惑语气)
## 2026-04-24 - 第十轮修改