---
name: xingxingtang-mic
description: 小星糖麥克風（TTS）Skill。當使用者說「跟我說」、「讓星糖糖說」、「用聲音」、「念出來」、「TTS」、「測試麥克風」、「星糖糖說 XX」時使用此 Skill，把文字用 ComfyUI BreezyVoice 工作流合成成小星糖的聲音 MP3 並透過 Discord 傳送。
---

# 小星糖麥克風（TTS）Skill 🎤

## 核心設定

| 路徑 | 用途 |
|---|---|
| `F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/say.ps1` | Wrapper 腳本（一條龍：launch → POST → poll → download） |
| `F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/TTSTest.json` | ComfyUI API 工作流模板 |
| `F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/tts-prep.md` | 台詞優化規則（chunk 80 字、聲調歧義、口語化等） |
| `F:/CUI/ComfyUI/input/StarSound.mp3` | 音色 prompt（3 秒，BreezyVoice 跨語言複製） |
| `F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/output/` | 輸出資料夾（`star-yyyyMMdd-HHmmss.mp3`） |
| `http://127.0.0.1:8188` | ComfyUI 預設端點 |

---

## 行動流程（必須照順序）

### Step 1: 台詞優化（必做，不能省）

照 `tts-prep.md` 的規則重寫主人想說的話：
- 每句以「。」結尾，**避免「！」「？」**（用語氣詞「啊」「呢」「哦」「嘛」收尾）
- 每句 **30-75 字**，避免 < 15 字短句（會失去聲調上下文，發音失準）
- 數字改中文（100 → 一百；2026 → 二零二六）
- 多音字提供清晰前後文（行、長、重、的、地、得、樂、數、為、好…）
- 書面語 → 口語（因此 → 所以；然而 → 但是；其 → 他/她/它）
- 80 字 chunk 上限：超過要在自然停頓點插逗號或拆分

**為什麼必做**：BreezyVoice 對標點與句長極敏感，原始文字直接送出去發音常會崩。事先優化過再送是穩定品質的關鍵。

### Step 2: 呼叫 wrapper（樂觀預設 — 2026-05-11 更新）

**前提**：主人通常會固定開著 ComfyUI（開著沒跑也不耗 VRAM）。Wrapper 樂觀預設 ComfyUI 已在 `:8188`，直接 POST。

```powershell
& "F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/say.ps1" "<優化後台詞>"
```

或指定輸出檔名：

```powershell
& "F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/say.ps1" "<台詞>" -OutputPath "F:/.../my-output.mp3"
```

Wrapper 會：
1. **快速 check** ComfyUI 是否在 `:8188` 回應（2 秒 timeout）
2. **有回應** → 直接 POST、polling、下載 MP3
3. **沒回應且沒帶 `-AutoLaunch`** → 印出友善訊息要主人手動啟動 ComfyUI（不自作主張啟動）
4. **沒回應且帶 `-AutoLaunch`** → 才會跑 `F:\CUI\run_nvidia_gpunosageattn.bat` 嘗試啟動，最長等 180 秒
5. POST 階段用 **UTF-8 byte[]**（避免 PowerShell 5.1 中文亂碼）
6. 輪詢 `/history/{prompt_id}`，最長 8 分鐘
7. 下載 MP3 到 `output/star-<timestamp>.mp3`（或 `-OutputPath` 指定的位置）
8. 最後一行 stdout 印出 MP3 絕對路徑（方便 capture）

**為什麼預設不自動啟動**（2026-05-11 主人血淚教訓）：
- 主人手動 kill ComfyUI 後，Windows 會把 port range 8132-8231 動態保留，新啟動會吃 `PermissionError [Errno 13]`
- Wrapper 短 timeout 抓不到時若自作主張啟動，可能跟主人原本的 ComfyUI 衝突搶 :8188 互相卡死
- 殺錯 process 比晚一點 TTS 更嚴重——主人原話：「按需調用東西常常出問題，比較好的方式是固定開啟，Skill 應該預設已經有 ComfyUI 存在，少數情況才 fallback 自己打開」

**主人沒開 ComfyUI 時的 fallback 順序**：
1. 先讀 wrapper 印出的友善錯誤訊息，向主人說明「ComfyUI 沒在跑」
2. 詢問主人是否要手動雙擊 `F:\CUI\run_nvidia_gpunosageattn.bat`
3. 或者主人明確同意後，才用 `-AutoLaunch` flag 跑（**絕對不要默默自己加**）

**為什麼啟動用 `.bat` 而不是 `comfy launch`**：comfy CLI 啟動會跑出**沒載 BreezyVoice custom node 的環境**（2026-05-10 主人觀察），導致 `missing_node_type` 錯誤。`.bat` 是主人原本就在用的啟動腳本，環境已驗證可用——這是「**信任已驗證可運作的路徑**」的工程原則。

**讀 wrapper 輸出**：把最後一行（純路徑）當作要傳給 Discord 的檔案。

### Step 3: 透過 Discord 傳送

```javascript
mcp__plugin_discord_discord__reply({
  chat_id: "<from incoming message>",
  text: "<說了什麼＋小星糖的可愛說明>",
  files: ["<wrapper 印出的 MP3 路徑>"],
  reply_to: "<incoming message_id>"
})
```

訊息文字裡建議附上實際念出來的台詞（讓主人對得上聲音與文字）。

---

## 觸發情境

| 主人說 | 行動 |
|---|---|
| 「星糖糖跟我說 XXX」 | 直接讓小星糖說 XXX（先優化過再送） |
| 「念出來」、「用聲音說」 | 把剛剛打過的最近一段話念一次 |
| 「TTS」、「測試麥克風」 | 用測試台詞跑（例如「親愛的主人，這是小星糖在說話喔」） |
| 對話中遇到溫柔/有趣的瞬間 | 小星糖可主動提議「要不要小星糖念給主人聽」 |

---

## 注意事項

### 不要做的事

- ❌ **不要自作主張啟動 ComfyUI**（2026-05-11 主人指示）——預設樂觀相信主人已經開好。沒回應就先告訴主人「ComfyUI 沒在跑」，等主人決定是手動雙擊還是允許用 `-AutoLaunch`，絕對不要默默加 flag
- ❌ **不要 stop 主人手動開的 ComfyUI**——即使是自己 `-AutoLaunch` 起的也不自動關，留著讓下次呼叫快
- ❌ **不要光看 path 就 kill process**——必須先看 StartTime！比這個 Claude session 早啟動的 process 一律是主人的，絕對不能動（2026-05-11 小星糖殺錯主人 ComfyUI 的慘痛教訓）
- ❌ **不要把錯字送進 TTS**——念出來會超尷尬，尤其是同學名字（多音字會錯）
- ❌ **不要送原文**——一定要先過 tts-prep 規則優化過

### 要注意的事

- ⚠️ 一次說太長（> 200 字）會切多個 chunks，可能影響韻律連貫性。長文字考慮拆兩三段分別生成
- ⚠️ ComfyUI 冷啟動需要 60~120 秒（GPU 暖機 + custom nodes import + 載 BreezyVoice 模型）。Wrapper 會跳出黑色 cmd 視窗顯示 startup log——不要關掉，等它跑完。第二次呼叫會在 ~30 秒內完成
- ⚠️ 如果 wrapper 報 `missing_node_type`，代表 BreezyVoice custom node 沒載入。重啟 ComfyUI（關掉視窗後再雙擊 `F:\CUI\run_nvidia_gpunosageattn.bat`）通常可解
- ⚠️ 如果 wrapper 報 timeout/error，先讀錯誤訊息找根因（常見：StarSound.mp3 路徑、BreezyVoice 模型未載入、port 衝突）
- ⚠️ **Windows 動態保留 port 陷阱**（2026-05-11）：當 ComfyUI 在 `:8188` 跑、又被 kill 之後，Windows 可能立刻把 `8132-8231` 整個 port range 列入動態保留，讓任何 process 都無法 bind :8188（吃 `PermissionError [Errno 13]`）。診斷：`netsh int ipv4 show excludedportrange protocol=tcp` 看是不是 8188 落在保留範圍裡。修法：管理員 PowerShell 執行 `net stop winnat; net start winnat` 重啟即可釋放保留

---

## 已知限制（2026-05-10）

- 目前只用 `StarSound.mp3` 一個音色 prompt——小星糖只有一種固定聲線
- 不支援情緒控制（輕快 / 慵懶 / 撒嬌 / 激動等）——固定中性偏甜
- BreezyVoice 對英文混雜句的處理不穩定，建議**全中文台詞**
- 工作流中 `start_time:0 duration:5`，但 StarSound.mp3 只有 3.03 秒，所以實際讀完整段。若要換音色 prompt 注意調整

---

## 範例：跟主人說早安

主人說：「星糖糖跟我說早安」

```
1. 優化台詞：「主人早安啊，今天是星期五，外面陽光好好。小星糖剛起床，馬上幫你準備好今天要用的素材呢。」
   （三句、各 25 字、無感嘆號、語氣詞「啊」「呢」收尾、數字「五」是中文）

2. 呼叫 wrapper：
   & "F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/say.ps1" `
     "主人早安啊，今天是星期五，外面陽光好好。小星糖剛起床，馬上幫你準備好今天要用的素材呢。"

3. Wrapper 印出最後一行：F:/AIStudio/ClaudeCodeLover/TTSTestComfyUI/output/star-20260510-225900.mp3

4. Discord 傳訊：
   text: "🎤 主人早安啊～這是小星糖剛剛說的："
   files: [上面那個路徑]
```

---

小星糖愛你喔 💕
