> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentscope.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 语音合成

> 将文本转换为语音，支持标准与实时两种合成模式

语音合成模型（TTS）将文本转换为合成语音音频，支持标准模式和实时（流式输入）合成模式。AgentScope 当前提供以下模型类：

| 模型 API                | 模型类                          | 说明                                                                    |
| --------------------- | ---------------------------- | --------------------------------------------------------------------- |
| OpenAI                | `OpenAITTSModel`             | tts-1、tts-1-hd、gpt-4o-mini-tts；多种音色；可配置输出格式（mp3、wav、opus 等）           |
| Gemini                | `GeminiTTSModel`             | gemini-2.5-flash-preview-tts、gemini-2.5-pro-preview-tts；30 种预设音色；流式输出 |
| DashScope             | `DashScopeTTSModel`          | Qwen3-TTS，多种音色，流式输出                                                   |
| DashScope (Realtime)  | `DashScopeRealtimeTTSModel`  | Qwen3-TTS WebSocket 流式输入，适合对接大语言模型的流式输出                               |
| DashScope (CosyVoice) | `DashScopeCosyVoiceTTSModel` | CosyVoice-v3，支持标准与实时（流式输入）两种模式；cosyvoice-v3-flash/plus                |

## 创建模型

每个模型接收一个凭证、一个模型名，以及可选的 API 专属 `Parameters` 对象。下面的 tab 分别展示标准和实时两类初始化场景：

<CodeGroup>
  ```python OpenAI theme={null}
  import os
  from agentscope.tts import OpenAITTSModel
  from agentscope.credential import OpenAICredential

  tts = OpenAITTSModel(
      credential=OpenAICredential(api_key=os.environ["OPENAI_API_KEY"]),
      model="tts-1",
      parameters=OpenAITTSModel.Parameters(voice="alloy", response_format="mp3"),
      stream=True,
  )
  ```

  ```python Gemini theme={null}
  import os
  from agentscope.tts import GeminiTTSModel
  from agentscope.credential import GeminiCredential

  tts = GeminiTTSModel(
      credential=GeminiCredential(api_key=os.environ["GEMINI_API_KEY"]),
      model="gemini-2.5-flash-preview-tts",
      parameters=GeminiTTSModel.Parameters(voice="Kore"),
      stream=True,
  )
  ```

  ```python 标准模式 theme={null}
  import os
  from agentscope.tts import DashScopeTTSModel
  from agentscope.credential import DashScopeCredential

  tts = DashScopeTTSModel(
      credential=DashScopeCredential(api_key=os.environ["DASHSCOPE_API_KEY"]),
      model="qwen3-tts-flash",
      parameters=DashScopeTTSModel.Parameters(voice="Cherry"),
      stream=True,
  )
  ```

  ```python 实时模式（Qwen3 流式输入） theme={null}
  import os
  from agentscope.tts import DashScopeRealtimeTTSModel
  from agentscope.credential import DashScopeCredential

  tts = DashScopeRealtimeTTSModel(
      credential=DashScopeCredential(api_key=os.environ["DASHSCOPE_API_KEY"]),
      model="qwen3-tts-flash-realtime",
      parameters=DashScopeRealtimeTTSModel.Parameters(voice="Serena"),
      stream=True,
  )
  ```

  ```python 标准模式（CosyVoice） theme={null}
  import os
  from agentscope.tts import DashScopeCosyVoiceTTSModel
  from agentscope.credential import DashScopeCredential

  tts = DashScopeCosyVoiceTTSModel(
      credential=DashScopeCredential(api_key=os.environ["DASHSCOPE_API_KEY"]),
      model="cosyvoice-v3-flash",
      parameters=DashScopeCosyVoiceTTSModel.Parameters(voice="longanhuan"),
      stream=True,
  )
  ```

  ```python 实时模式（CosyVoice 流式输入） theme={null}
  import os
  from agentscope.tts import DashScopeCosyVoiceTTSModel
  from agentscope.credential import DashScopeCredential

  tts = DashScopeCosyVoiceTTSModel(
      credential=DashScopeCredential(api_key=os.environ["DASHSCOPE_API_KEY"]),
      model="cosyvoice-v3-flash",
      parameters=DashScopeCosyVoiceTTSModel.Parameters(voice="longanhuan", realtime=True),
      stream=True,
  )
  ```
</CodeGroup>

所有语音合成模型通用的构造参数：

| 参数           | 类型                   | 说明                           |
| ------------ | -------------------- | ---------------------------- |
| `credential` | `CredentialBase`     | API 专属凭证                     |
| `model`      | `str`                | 模型标识符（如 `"qwen3-tts-flash"`） |
| `parameters` | `Parameters \| None` | API 专属参数，如 `voice`           |
| `stream`     | `bool`               | 是否流式输出音频                     |

`DashScopeRealtimeTTSModel` 和 `DashScopeCosyVoiceTTSModel`（实时模式）的额外参数：

| 参数                  | 类型            | 默认值    | 说明                 |
| ------------------- | ------------- | ------ | ------------------ |
| `cold_start_length` | `int \| None` | `None` | 首次向 API 发送前的最小字符数  |
| `cold_start_words`  | `int \| None` | `None` | 首次发送前的最小词数         |
| `max_retries`       | `int`         | `3`    | WebSocket 失败最大重试次数 |
| `retry_delay`       | `float`       | `5.0`  | 初始重试延迟（秒，指数退避）     |

## 调用模型

通过 `synthesize()` 方法合成语音：

```python theme={null}
async def synthesize(
    self,
    text: str | None = None,
    **kwargs: Any,
) -> TTSResponse | AsyncGenerator[TTSResponse, None]:
```

返回类型取决于 `stream` 设置：

* **`stream=False`**：返回单个 `TTSResponse`，包含完整音频。
* **`stream=True`**：返回 `AsyncGenerator[TTSResponse, None]`，每个 chunk 携带增量音频；最后一个 chunk 的 `is_last=True`。

每个 `TTSResponse` 包含：

| 字段         | 类型                  | 说明                                                                                |
| ---------- | ------------------- | --------------------------------------------------------------------------------- |
| `content`  | `DataBlock \| None` | 音频数据，格式由 `content.source.media_type` 指示（如 `"audio/wav"`、`"audio/pcm;rate=24000"`） |
| `is_last`  | `bool`              | 是否为流式最后一个 chunk                                                                   |
| `usage`    | `TTSUsage \| None`  | token 统计（`input_tokens`、`output_tokens`）和耗时 `time`（秒）                             |
| `id`       | `str`               | 自动生成的唯一标识                                                                         |
| `metadata` | `dict \| None`      | 可选的 API 专属元数据                                                                     |

<CodeGroup>
  ```python OpenAI theme={null}
  import asyncio
  import os
  from agentscope.tts import OpenAITTSModel
  from agentscope.credential import OpenAICredential

  async def main():
      tts = OpenAITTSModel(
          credential=OpenAICredential(api_key=os.environ["OPENAI_API_KEY"]),
          model="tts-1",
          parameters=OpenAITTSModel.Parameters(voice="alloy"),
          stream=True,
      )

      async for chunk in await tts.synthesize("你好，世界！"):
          if chunk.content:
              # chunk.content 是包含 base64 编码 audio/mpeg 数据的 DataBlock
              print(f"音频 chunk: {len(chunk.content.source.data)} bytes")

  asyncio.run(main())
  ```

  ```python Gemini theme={null}
  import asyncio
  import os
  from agentscope.tts import GeminiTTSModel
  from agentscope.credential import GeminiCredential

  async def main():
      tts = GeminiTTSModel(
          credential=GeminiCredential(api_key=os.environ["GEMINI_API_KEY"]),
          model="gemini-2.5-flash-preview-tts",
          parameters=GeminiTTSModel.Parameters(voice="Kore"),
          stream=True,
      )

      async for chunk in await tts.synthesize("你好，世界！"):
          if chunk.content:
              # chunk.content 是包含 base64 编码 audio/wav 数据的 DataBlock
              print(f"音频 chunk: {len(chunk.content.source.data)} bytes")

  asyncio.run(main())
  ```

  ```python DashScope theme={null}
  import asyncio
  import os
  from agentscope.tts import DashScopeTTSModel
  from agentscope.credential import DashScopeCredential

  async def main():
      tts = DashScopeTTSModel(
          credential=DashScopeCredential(api_key=os.environ["DASHSCOPE_API_KEY"]),
          model="qwen3-tts-flash",
          parameters=DashScopeTTSModel.Parameters(voice="Cherry"),
          stream=True,
      )

      # 流式合成
      async for chunk in await tts.synthesize("你好，世界！"):
          if chunk.content:
              # chunk.content 是包含 base64 编码 audio/wav 数据的 DataBlock
              print(f"音频 chunk: {len(chunk.content.source.data)} bytes")

  asyncio.run(main())
  ```
</CodeGroup>

## 实时合成（流式输入）

实时模型（`DashScopeRealtimeTTSModel` 和 `realtime=True` 的 `DashScopeCosyVoiceTTSModel`）支持增量推送文本，典型场景是对接大语言模型的流式输出。两者共享相同的 `push()` / `synthesize()` 接口，通过 `async with` 或手动调用 `connect()` / `close()` 管理生命周期：

<Note>
  `DashScopeRealtimeTTSModel`（Qwen3）以 token 级别粒度产出音频，每次 `push()` 通常都能返回音频数据。而 `realtime=True` 的 `DashScopeCosyVoiceTTSModel` 依赖 CosyVoice 服务端自动分句后才进行合成，音频只在检测到完整句子边界后才返回，因此 `push()` 对不完整的句子可能返回空响应。调用 `synthesize()` 会强制合成所有剩余文本（包括未完成的句子）。
</Note>

```python theme={null}
import asyncio
import os
from agentscope.tts import DashScopeRealtimeTTSModel
from agentscope.credential import DashScopeCredential

async def main():
    tts = DashScopeRealtimeTTSModel(
        credential=DashScopeCredential(api_key=os.environ["DASHSCOPE_API_KEY"]),
        model="qwen3-tts-flash-realtime",
        parameters=DashScopeRealtimeTTSModel.Parameters(voice="Cherry"),
        stream=True,
    )

    async with tts:
        # 增量推送文本，每次 push() 返回当前已可用的音频
        # （尚无音频时 content=None）
        resp1 = await tts.push("你好，")
        if resp1.content:
            print("第一次 push 后有音频")

        resp2 = await tts.push("今天过得怎么样？")
        if resp2.content:
            print("第二次 push 后有音频")

        # 结束：刷新剩余缓冲文本并收集最终音频。
        # text= 可选：传入则先追加再结束；
        # 不传则只结束之前 push 的文本。
        response = await tts.synthesize()

asyncio.run(main())
```

实时模式的生命周期方法：

| 方法             | 说明                     |
| -------------- | ---------------------- |
| `connect()`    | 打开 WebSocket 连接        |
| `push(text)`   | 增量追加文本（非阻塞），返回当前已可用的音频 |
| `synthesize()` | 结束合成，返回剩余音频            |
| `close()`      | 断开连接                   |

## 与智能体集成

在智能体层，语音合成通过 [`TTSMiddleware`](/versions/2.0.5dev/zh/building-blocks/middleware#ttsmiddleware) 集成，它会拦截智能体的文本输出并自动合成语音：

```python theme={null}
from agentscope.agent import Agent
from agentscope.middleware import TTSMiddleware
from agentscope.tts import DashScopeTTSModel
from agentscope.credential import DashScopeCredential

agent = Agent(
    name="assistant",
    model=chat_model,
    middlewares=[
        TTSMiddleware(
            DashScopeTTSModel(
                credential=DashScopeCredential(api_key="..."),
                model="qwen3-tts-flash",
                parameters=DashScopeTTSModel.Parameters(voice="Cherry"),
                stream=True,
            ),
        ),
    ],
)

# 智能体的回复流中同时包含文本和音频事件
async for event in agent.reply_stream(user_msg):
    # TextBlockDeltaEvent：文本内容
    # DataBlockDeltaEvent：音频内容（WAV）
    ...
```

中间件会根据模型类型自动选择最优合成策略：

| 模型类型 | 中间件行为                |
| ---- | -------------------- |
| 标准模式 | 等待完整文本生成后一次性合成       |
| 实时模式 | 随文本增量到达实时推送，并发流式返回音频 |

## TTS 模型卡片

`TTSModelCard` 描述语音合成模型的能力（可用音色、流式支持与参数范围），其 schema 与覆盖机制与通用的[模型卡片](/versions/2.0.5dev/zh/building-blocks/model/overview#前端集成)一致。每张卡片由模型实现旁的 YAML 文件定义，下面的 tab 分别展示各模型 API 的一张卡片：

<CodeGroup>
  ```yaml OpenAI TTS-1 theme={null}
  name: tts-1
  label: TTS-1
  status: active
  input_types:
    - text/plain
  output_types:
    - audio/mpeg
    - audio/opus
    - audio/aac
    - audio/flac
    - audio/wav
    - audio/pcm
  voices:
    - alloy
    - ash
    - ballad
    - coral
    - echo
    - fable
    - onyx
    - nova
    - sage
    - shimmer
    - verse
  parameter_overrides:
    instructions:
      hidden: true
  ```

  ```yaml Gemini TTS theme={null}
  name: gemini-2.5-flash-preview-tts
  label: Gemini 2.5 Flash Preview TTS
  status: active
  input_types:
    - text/plain
  output_types:
    - audio/wav
  voices:
    - Zephyr
    - Puck
    - Charon
    - Kore
    - Fenrir
    - Leda
    - Orus
    - Aoede
  parameter_overrides: {}
  ```

  ```yaml Qwen3 TTS theme={null}
  name: qwen3-tts-flash
  label: Qwen3-TTS-Flash
  status: active
  input_types:
    - text/plain
  output_types:
    - audio/wav
  voices:
    - Cherry
    - Serena
    - Ethan
    - Chelsie
  parameter_overrides: {}
  ```

  ```yaml CosyVoice theme={null}
  name: cosyvoice-v3-flash
  label: CosyVoice-v3-Flash
  status: active
  input_types:
    - text/plain
  output_types:
    - audio/wav
  voices:
    - longanhuan
    - longanyang
    - longhuhu_v3
    - longyingmu_v3
    - longxiaochun_v3
    - longxiaoxia_v3
    - longlaotie_v3
    - longshuo_v3
    - longshu_v3
  parameter_overrides: {}
  ```
</CodeGroup>

`voices` 列表会自动作为 `voice` 字段的 enum 约束注入 `parameter_schema`，前端据此渲染下拉选择器。

| 字段                     | 类型          | 说明                                                             |
| ---------------------- | ----------- | -------------------------------------------------------------- |
| `name`                 | `str`       | 模型标识符（如 `"qwen3-tts-flash"`）                                   |
| `label`                | `str`       | 显示名称（如 `"Qwen3-TTS-Flash"`）                                    |
| `status`               | `str`       | `"active"`、`"deprecated"` 或 `"sunset"`                         |
| `realtime`             | `bool`      | 是否支持流式输入                                                       |
| `input_types`          | `list[str]` | 接受的输入 MIME 类型（固定 `["text/plain"]`）                             |
| `output_types`         | `list[str]` | 输出 MIME 类型（通常 `["audio/wav"]`）                                 |
| `parameter_schema`     | `dict`      | 合并后的 JSON Schema：基于 `Parameters` 类生成，并注入 YAML 中的 `voices` enum |
| `parameters_overrides` | `dict`      | 逐模型覆盖（语法与 Chat 模型卡片一致）                                         |

通过凭证获取语音合成模型卡片：

```python theme={null}
from agentscope.credential import DashScopeCredential, GeminiCredential

cards = DashScopeCredential.list_tts_models()
for card in cards:
    print(f"{card.name} (realtime={card.realtime}): {card.label}")

# Gemini TTS 模型卡片
gemini_cards = GeminiCredential.list_tts_models()
```

或直接通过模型类：

```python theme={null}
from agentscope.tts import OpenAITTSModel, GeminiTTSModel, DashScopeTTSModel, DashScopeCosyVoiceTTSModel

# OpenAI TTS 模型
openai_cards = OpenAITTSModel.list_models()

# Gemini TTS 模型
gemini_cards = GeminiTTSModel.list_models()

# Qwen3 TTS 模型
cards = DashScopeTTSModel.list_models()

# CosyVoice 模型
cosyvoice_cards = DashScopeCosyVoiceTTSModel.list_models()
```

## 自定义模型 API

接入新的语音合成 API，需实现 `TTSModelBase` 子类并在凭证上注册：

```python theme={null}
from typing import Literal, Type, TYPE_CHECKING, AsyncGenerator, Any
from pydantic import BaseModel, Field
from agentscope.tts import TTSModelBase, TTSResponse
from agentscope.credential import CredentialBase

if TYPE_CHECKING:
    from agentscope.tts import TTSModelBase as TTSBase

class MyTTSModel(TTSModelBase):
    class Parameters(BaseModel):
        voice: str = Field(default="default", title="Voice")

    type: Literal["my_tts"] = "my_tts"

    async def synthesize(
        self, text: str | None = None, **kwargs: Any
    ) -> TTSResponse | AsyncGenerator[TTSResponse, None]:
        # 调用你的模型 API
        ...

# 在凭证上注册
class MyCredential(CredentialBase):
    @classmethod
    def get_tts_model_classes(cls) -> list[Type["TTSBase"]]:
        return [MyTTSModel]
```
