# 讨论记录 (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`) - 音频格式:WAV(Base64 编码) --- ## 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(音频数据) - 添加 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() 只保存 UserConfig(api_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 参数 + 文本内标签同时生效 ### 第十一轮实施完成(继续实施 - 2026-04-25) **已完成**: 1. ✅ 修改 Cargo.toml 添加依赖(dirs、chrono) 2. ✅ 创建 src/daemon.rs(TCP 服务器、请求处理、PID 管理、日志) 3. ✅ 创建 src/client.rs(TCP 客户端、请求发送、响应处理) 4. ✅ 修改 src/cli.rs(Daemon、Send、ttsd 子命令) 5. ✅ 修改 src/main.rs(模块声明、命令分发、spawn_daemon_process) 6. ✅ 编译成功(仅有未使用代码警告) **最新测试结果**(2026-04-25): - ✅ `mimo-tts ttsd --port 9876` - 守护进程模式启动成功 - ✅ `nohup ./mimo-tts ttsd --port 9876 &` - 后台运行成功 - ✅ `mimo-tts send --port 9876 "消息"` - 发送请求成功,返回"播放完成" - ✅ 日志正常:`~/.config/tts/ttsd.log` **用户需求**: - 启动:`mimo-tts daemon start -d --port 9876` 或 `mimo-tts daemon start -d` - 停止:`mimo-tts daemon stop`(无需端口) - 状态:`mimo-tts daemon status`(无需端口) **当前方案**: - 使用 `nohup` 启动后台进程(Unix) - `ttsd` 子命令作为内部守护进程模式 - `stop` 和 `status` 无需端口参数 **尚未完成**: - `daemon start -d` 命令(需要实现 spawn_daemon_process) - `daemon stop` 命令 - `daemon status` 命令 --- ## 2026-04-25 - 第十二轮:日志格式升级 ### 用户需求 升级日志格式,添加级别和 PID 信息: - `[时间戳] [级别] [PID] 消息` - 级别自动检测(INFO/WARN/ERROR) - 与旧日志区分(追加新格式) ### 实施完成 1. ✅ 修改 daemon.rs: - 添加 LogLevel 枚举 - 自动检测消息中的关键词判断级别 - 新格式:`[时间戳] [级别] [PID] 消息` - stdout 输出简化:`[Daemon PID] 消息` 2. ✅ 添加 `daemon logs` 命令 - 支持 `--lines N` 参数 - 默认显示 20 行 3. ✅ 测试通过: - 守护进程启动/停止/状态 ✅ - send 发送播放 ✅ - logs 查看日志 ✅ - 新格式正确显示 ✅ ### 新日志格式 ``` [2026-04-25 05:48:05] [INFO] [15278] 正在播放音频... [2026-04-25 05:48:10] [INFO] [15278] 响应: {"status":"ok","message":"播放完成"} ``` ### 级别自动检测 - `INFO` - 默认(正常运行信息) - `WARN` - 包含"警告"、"注意" - `ERROR` - 包含"错误"、"失败"、"无法" ### 踩坑记录 1. **clap 参数传递问题** - 问题:`--port` 参数无法传递给 `daemon start` 子命令 - 原因:clap derive 模式中,参数定义在父命令,需要在子命令之前使用 - 解决:修改 `DaemonCommand` 为独立结构体,使用正确的参数顺序 - 正确用法:`mimo-tts daemon --port 9876 start` - 错误用法:`mimo-tts daemon start --port 9876` 2. **chrono 依赖缺失** - 问题:daemon.rs 使用 `chrono::Local::now()` 但 Cargo.toml 未添加依赖 - 解决:添加 `chrono = "0.4"` 到 Cargo.toml ### 命令使用示例 ```bash # 启动守护进程(后台运行) mimo-tts daemon --port 9876 start & # 查看状态 mimo-tts daemon --port 9876 status # 发送文本(使用 style 参数) mimo-tts send --port 9876 --style "开心" "你好,世界!" # 发送文本(不使用 style) mimo-tts send --port 9876 "你好,世界!" # 停止守护进程 mimo-tts daemon --port 9876 stop ``` ### 技术细节 - 使用 `tokio::net::TcpListener` 实现 TCP 服务器 - 使用 `tokio::spawn` 处理多个并发连接 - 使用 `serde_json` 序列化/反序列化 JSON 协议 - 使用 `dirs::home_dir()` 获取家目录,拼接配置路径 - PID 文件用于检测守护进程是否运行 - 日志同时输出到文件和控制台 - 播放功能复用现有的 `play_audio()` 函数 - style 参数按官方文档转换为 `` 标签 ## 2026-04-24 - 第十轮修改