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

v0.1.0
2026-04-24 03:32:44 +08:00

348 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 讨论记录 (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 - 第十轮修改