2026-04-24 03:32:44 +08:00
|
|
|
|
# 讨论记录 (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<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() 只保存 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>` 标签)
|
|
|
|
|
|
- 模型名更新为 `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 的流式响应处理
|
|
|
|
|
|
- 处理 SSE(Server-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-25 05:50:28 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2026-04-25 - 第十一轮修改
|
|
|
|
|
|
|
|
|
|
|
|
### 用户需求
|
|
|
|
|
|
**实现守护进程(Daemon)模式,类似 Docker 架构**
|
|
|
|
|
|
- 作为后台服务运行,使用 TCP Socket 监听
|
|
|
|
|
|
- 允许其他应用(包括 Web)通过客户端访问
|
|
|
|
|
|
- 实现类似智能音响的功能:客户端发送文本,守护进程执行 TTS 并播放
|
|
|
|
|
|
- 所有平台统一使用 `~/.config/tts/` 目录
|
|
|
|
|
|
- 支持 style 参数作为宏观场景风格(与文本内 `[style]` 标签并存)
|
|
|
|
|
|
|
|
|
|
|
|
### 技术选型
|
|
|
|
|
|
- **Socket 方案**:TCP Socket(跨平台通用,所有平台统一)
|
|
|
|
|
|
- **协议**:JSON over TCP(简单、易调试)
|
|
|
|
|
|
- **日志路径**:`~/.config/tts/ttsd.log`(所有平台统一)
|
|
|
|
|
|
- **PID 文件路径**:`~/.config/tts/ttsd.pid`
|
|
|
|
|
|
- **默认端口**:9876
|
|
|
|
|
|
|
|
|
|
|
|
### 新增文件
|
|
|
|
|
|
1. `src/daemon.rs` - 守护进程模块
|
|
|
|
|
|
- TCP Socket 服务器(tokio::net::TcpListener)
|
|
|
|
|
|
- 处理客户端请求(JSON 协议)
|
|
|
|
|
|
- PID 文件管理(启动/停止)
|
|
|
|
|
|
- 日志记录(文件 + stdout)
|
|
|
|
|
|
- 调用 TTS API + 播放音频
|
|
|
|
|
|
2. `src/client.rs` - 客户端模块
|
|
|
|
|
|
- TCP 客户端(tokio::net::TcpStream)
|
|
|
|
|
|
- 发送 TTS 请求到守护进程
|
|
|
|
|
|
- 接收并处理响应
|
|
|
|
|
|
|
|
|
|
|
|
### 修改文件
|
|
|
|
|
|
1. `Cargo.toml`
|
|
|
|
|
|
- 添加 `dirs = "5.0"`(跨平台配置目录)
|
|
|
|
|
|
- 添加 `chrono = "0.4"`(日志时间戳)
|
|
|
|
|
|
2. `src/cli.rs`
|
|
|
|
|
|
- 添加 `Daemon` 子命令(start/stop/status)
|
|
|
|
|
|
- 添加 `Send` 子命令(发送文本到守护进程)
|
|
|
|
|
|
- 支持 `--port` 参数(默认 9876)
|
|
|
|
|
|
3. `src/main.rs`
|
|
|
|
|
|
- 声明新模块 `daemon` 和 `client`
|
|
|
|
|
|
- 添加命令分发逻辑
|
|
|
|
|
|
|
|
|
|
|
|
### 协议设计
|
|
|
|
|
|
```json
|
|
|
|
|
|
// 客户端 → 服务端
|
|
|
|
|
|
{
|
|
|
|
|
|
"text": "要合成的文本",
|
|
|
|
|
|
"voice": "mimo_default",
|
|
|
|
|
|
"format": "wav",
|
|
|
|
|
|
"style": "开心"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 服务端 → 客户端
|
|
|
|
|
|
{"status": "ok", "message": "播放完成"}
|
|
|
|
|
|
{"status": "error", "message": "错误信息"}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### style 参数说明
|
|
|
|
|
|
- **文本内标签**:`[开心]你好!`(细粒度,句子级别)
|
|
|
|
|
|
- **style 参数**:宏观场景风格(如"新闻播报"、"开心")
|
|
|
|
|
|
- **服务端处理**:如果有 style 参数,自动添加 `<style>...</style>` 标签到文本开头(符合官方文档)
|
|
|
|
|
|
- **两者可并存**: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` - 包含"错误"、"失败"、"无法"
|
|
|
|
|
|
|
2026-04-25 06:34:54 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2026-04-25 - 第十三轮:添加 HTTP 接口
|
|
|
|
|
|
|
|
|
|
|
|
### 用户需求
|
|
|
|
|
|
让 Postman 可以测试守护进程:
|
|
|
|
|
|
- 添加 HTTP 接口(端口 9877)
|
|
|
|
|
|
- 支持 POST /synthesize 接口
|
|
|
|
|
|
- 支持 GET /health 健康检查
|
|
|
|
|
|
|
|
|
|
|
|
### 实施完成
|
|
|
|
|
|
1. ✅ 添加 tiny_http 依赖
|
|
|
|
|
|
2. ✅ 在 daemon.rs 添加 HTTP 服务器函数
|
|
|
|
|
|
3. ✅ 自动启动 HTTP 服务器(端口 = TCP端口 + 1)
|
|
|
|
|
|
4. ✅ 测试通过:
|
|
|
|
|
|
- `curl http://127.0.0.1:9877/synthesize` ✅
|
|
|
|
|
|
- `curl http://127.0.0.1:9877/health` ✅
|
|
|
|
|
|
|
|
|
|
|
|
### HTTP 接口设计
|
|
|
|
|
|
|
|
|
|
|
|
| 地址 | 方法 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `http://127.0.0.1:9877/synthesize` | POST | 语音合成 |
|
|
|
|
|
|
| `http://127.0.0.1:9877/health` | GET | 健康检查 |
|
|
|
|
|
|
|
|
|
|
|
|
### 端口说明
|
|
|
|
|
|
- TCP: 9876 - 程序客户端用
|
|
|
|
|
|
- HTTP: 9877 - Postman/调试用(TCP端口 + 1)
|
|
|
|
|
|
|
|
|
|
|
|
### Postman 测试示例
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 合成接口
|
|
|
|
|
|
curl -X POST http://127.0.0.1:9877/synthesize \
|
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
|
-d '{"text":"你好世界"}'
|
|
|
|
|
|
|
|
|
|
|
|
# 健康检查
|
|
|
|
|
|
curl http://127.0.0.1:9877/health
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-25 05:50:28 +08:00
|
|
|
|
### 踩坑记录
|
|
|
|
|
|
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 参数按官方文档转换为 `<style>...</style>` 标签
|
|
|
|
|
|
|
2026-04-24 03:32:44 +08:00
|
|
|
|
## 2026-04-24 - 第十轮修改
|