# DotsTTS 本地 TTS 适配

`@speclip/pi-speech` 的默认 TTS 模型为 `dots-tts-mf`，provider ID 为 `dotstts-local`。npm 包不包含模型或 MLX 推理运行时，而是调用已安装并正在运行的 DotsTTS macOS 桌面整合包。

## 使用前提

1. 在 Apple Silicon Mac 上安装并打开 `DotsTTS.app`。
2. 等待桌面面板显示服务已启动，且 `dots-tts-mf` / `dots-tts-soar` 模型为已就绪。
3. 调用 `speech_synthesize`。默认无需 `speech-config.json`、`speech-credentials.json` 或 API Key。

本地服务固定使用无鉴权回环地址 `http://127.0.0.1:7860`。适配器拒绝 HTTPS、非回环主机、URL 凭证和带路径的 origin，防止本地请求被改发到外部服务。

## 模型与音色

- `dots-tts-mf`：默认模型，优先速度，适合日常合成。
- `dots-tts-soar`：更偏向质量，显式选择后使用。
- `voice: "default"`：使用模型默认音色。
- `voice: "voice_..."`：使用已经在 DotsTTS 中授权注册、且与所选模型绑定的音色。

`pi-speech` 只消费现有音色，不负责注册、删除或迁移音色。音色复刻属于生物特征处理，应在 DotsTTS 应用中完成，并确认声音本人所有权或明确授权；参考录音原文必须准确匹配音频。

## 调用链与字段映射

每次本地合成按以下公共接口执行：

1. `GET /health` 必须返回 `status: "ok"` 和 `service: "dotstts-pack"`。
2. `GET /v1/models` 中所选模型必须返回 `downloaded: true`。
3. `POST /v1/audio/speech` 接收 OpenAI 兼容字段。

工具输入会映射为：

```json
{
  "model": "dots-tts-mf",
  "input": "你好，这是本地生成的语音。",
  "voice": "default",
  "response_format": "mp3",
  "stream_format": "audio",
  "speed": 1.0,
  "dots": {
    "language": "ZH",
    "seed": 42,
    "long_text": true,
    "max_chars": 300,
    "gap_ms": 80,
    "max_retries": 2,
    "speaker_scale": 1.5
  }
}
```

`speech_synthesize` 以 camelCase 接收 `dots.longText`、`maxChars`、`gapMs`、`maxRetries`、`speakerScale`，adapter 会转换为上面的 DotsTTS API 字段；`language` 与 `seed` 原样传递。`speed` 范围为 0.25–4.0。以上控制只适用于 `dotstts-local`，与云模型一起使用会在请求前被拒绝。

`pi-speech` 当前统一输出只开放 `mp3` 和 `wav`。`sampleRate` 对本地 DotsTTS 不生效；采样率由 DotsTTS 编码结果决定。`stream_format: "audio"` 只是 MLX 完整生成后的缓冲式响应，不代表低首包实时流式。

成功响应的 `X-Dots-Output-Id` 同时记录为 generation attempt 的 `providerRequestId` 与 `providerAudioId`，音频仍会由 `pi-speech` 以“不覆盖已有文件”的规则写入工作区。目录中的 `catalogVersion: "local"` 与单价 0 仅表示没有云端 provider API 费用。

## 配置

两个本地模型都使用默认地址时，不需要 provider 配置。宿主如需持久化完整默认值，可写入：

```json
{
  "schemaVersion": 1,
  "providers": {},
  "defaults": {
    "asr": {
      "provider": "fireredasr-local",
      "model": "fireredasr2-ctc-int8"
    },
    "tts": {
      "provider": "dotstts-local",
      "model": "dots-tts-mf",
      "voice": "default",
      "format": "mp3"
    }
  }
}
```

## 错误语义

- `LOCAL_SERVICE_UNAVAILABLE`：先打开 DotsTTS.app 并等待面板显示服务已启动。
- `INVALID_HEALTH_RESPONSE` / `INVALID_MODELS_RESPONSE`：当前端口不是兼容的 DotsTTS 服务，或服务响应已损坏。
- `model_not_ready`：模型未就绪；`pi-speech` 不会擅自触发多 GB 下载，应由用户在整合包中修复或明确授权下载。
- `resource_not_found` / `invalid_voice`：刷新 DotsTTS 已有模型和音色，确认音色与模型匹配。
- `NETWORK_UNKNOWN`：合成请求发出后连接中断，generation 记为 `uncertain`，不得自动重跑。

DotsTTS 原生还支持 Opus、AAC、FLAC 与 PCM；这些格式未进入当前 `pi-speech` 的跨 provider 稳定输出接口，不应通过工具说明暗示已经支持。
