接入自定义 TTS 服务
更新时间不可用
使用 Agents SDK 的 GenericTTS 将自研、私有化或第三方 TTS 服务接入对话式 AI 引擎。
通过接入自定义文本转语音 (TTS) 服务,你可以将自研 TTS、私有化部署 TTS 或第三方 TTS 服务作为对话式智能体的语音合成模块。本文介绍如何准备兼容 OpenAI TTS 协议的 HTTP 服务,并在创建对话式智能体时通过 TTS 配置接入该服务。
实现原理
Agents SDK 通过 GenericTTS 构造自定义 TTS 配置。启动智能体会话时,SDK 会将该配置序列化为 tts.vendor = "generic_http",并由声网对话式 AI 引擎在需要播报文本时向你的 TTS HTTP 服务发起请求。
前提条件
开始前,请确保你已经:
- 已参考 使用 Agents SDK 或 使用 RESTful API 实现与智能体对话的基本逻辑。
- 准备好可被声网对话式 AI 引擎访问的 TTS HTTP 服务。
- 确保 TTS 服务支持 HTTP/1.1 或更高版本,生产环境建议使用 HTTPS。
- 确保 TTS 服务能够返回 PCM 格式音频数据。
- 安装包含
GenericTTSgeneric_http支持的 Agents SDK 版本。Go 和 TypeScript SDK 需要使用v2.4.0之后的版本;Python SDK 需要使用v2.4.1之后的版本。
注意
GenericTTS 当前只支持 HTTP 和 HTTPS endpoint。不要传入 ws:// 或 wss:// 地址,否则 SDK 会在构造 TTS vendor 时抛出错误。
实现步骤
1. 准备 TTS 服务接口
你的 TTS 服务需要提供一个兼容 OpenAI TTS 协议的 HTTP 接口。基础要求如下:
- 请求方法:
POST - 请求路径:
/audio/speech - 请求 Header:支持通过
Authorization: Bearer <api_key>鉴权 - 请求 Body:JSON 格式
- 响应 Body:PCM 音频数据流
请求体示例如下:
{
"model": "your-tts-model",
"input": "欢迎使用声网对话式 AI 引擎。",
"voice": "alloy",
"speed": 1.0,
"sample_rate": 16000,
"response_format": "pcm",
"instruction": "calm"
}请求体字段说明如下:
| 字段 | 类型 | 说明 |
|---|---|---|
input | String | 待合成的文本内容。由声网对话式 AI 引擎根据智能体回复自动传入。 |
model | String | TTS 模型名称。如果你的 TTS 服务不区分模型,可以忽略该字段。 |
voice | String | 音色名称。如果你的 TTS 服务不区分音色,可以忽略该字段。 |
speed | Number | 语速。 |
sample_rate | Integer | 输出音频采样率,单位为 Hz,默认值为 16000。 |
response_format | String | 输出音频格式,默认值为 pcm。当前仅支持 pcm。 |
instruction | String | 语音风格、情绪或其他播报指令。 |
注意
如果你的 TTS 服务不支持多采样率,请确保实际返回音频的采样率与通过 SDK 配置的 sample_rate 一致。
2. 验证 TTS 服务响应
你可以先使用 curl 验证 TTS 服务是否能正常返回 PCM 音频流:
curl --request POST \
--url https://your-tts-service.example.com/v1/audio/speech \
--header 'Authorization: Bearer <your_tts_api_key>' \
--header 'Content-Type: application/json' \
--data '{
"model": "your-tts-model",
"input": "欢迎使用声网对话式 AI 引擎。",
"voice": "alloy",
"speed": 1.0,
"sample_rate": 16000,
"response_format": "pcm"
}' \
--output test.pcm服务成功处理请求后,应以 HTTP 分块传输编码(Chunked Transfer Encoding)的方式流式返回合成后的 PCM 音频数据。
如果请求失败,建议返回标准 HTTP 错误状态码,并在响应体中携带 JSON 格式错误信息。例如:
{
"error": {
"message": "Incorrect API key provided.",
"type": "invalid_request_error",
"param": null,
"code": "invalid_api_key"
}
}3. 配置智能体使用自定义 TTS
以下示例中的 sttVendor/stt_vendor 和 llmVendor/llm_vendor 表示已创建好的 STT 和 LLM vendor。实际接入时,请根据你的业务选择对应的语音识别和大语言模型服务并完成配置;本文重点展示如何通过 GenericTTS 接入自定义 TTS 服务。
你可以使用 Agents SDK 的 GenericTTS 配置接入自定义 TTS 服务。
import (
Agora "github.com/AgoraIO/agora-agents-go/v2"
agentkit "github.com/AgoraIO/agora-agents-go/v2/agentkit/cn"
vendors "github.com/AgoraIO/agora-agents-go/v2/agentkit/cn/vendors"
)
sampleRate := vendors.SampleRate16kHz
speed := 1.0
client := agentkit.NewAgoraClient(agentkit.ClientOptions{
AppID: requireEnv("AGORA_APP_ID"),
AppCertificate: requireEnv("AGORA_APP_CERTIFICATE"),
})
agent := agentkit.NewAgent(
client,
agentkit.WithTurnDetectionConfig(&agentkit.TurnDetectionConfig{
Language: Agora.AsrLanguageZhCn.Ptr(),
}),
).WithStt(
// 替换为你已配置的 STT vendor。
sttVendor,
).WithLlm(
// 替换为你已配置的 LLM vendor。
llmVendor,
).WithTts(
vendors.NewGenericTTS(vendors.GenericTTSOptions{
URL: "https://your-tts-service.example.com/v1/audio/speech",
Headers: map[string]string{
"Authorization": "Bearer " + requireEnv("CUSTOM_TTS_API_KEY"),
},
Model: "your-tts-model",
Voice: "alloy",
Speed: &speed,
SampleRate: &sampleRate,
ResponseFormat: "pcm",
Instruction: "calm",
AdditionalParams: map[string]interface{}{
"enable_request_id": false,
},
}),
)你可以使用 Agents SDK 的 GenericTTS 配置接入自定义 TTS 服务。
from agora_agent import Agent, GenericTTS
client = Agora(
area=Area.CN,
app_id=os.environ["AGORA_APP_ID"],
app_certificate=os.environ["AGORA_APP_CERTIFICATE"],
)
agent = (
Agent(
client=client,
turn_detection={"language": "zh-CN"},
)
# 替换为你已配置的 STT vendor。
.with_stt(stt_vendor)
# 替换为你已配置的 LLM vendor。
.with_llm(llm_vendor)
.with_tts(
GenericTTS(
url="https://your-tts-service.example.com/v1/audio/speech",
headers={
"Authorization": f"Bearer {require_env('CUSTOM_TTS_API_KEY')}",
},
model="your-tts-model",
voice="alloy",
speed=1.0,
sample_rate=16000,
response_format="pcm",
instruction="calm",
additional_params={
"enable_request_id": False,
},
)
)
)你可以使用 Agents SDK 的 GenericTTS 配置接入自定义 TTS 服务。
import { Agent, GenericTTS } from 'agora-agents';
const client = new AgoraClient({
area: Area.CN,
appId: requireEnv("AGORA_APP_ID"),
appCertificate: requireEnv("AGORA_APP_CERTIFICATE"),
});
const agent = new Agent({
client,
turnDetection: { language: 'zh-CN' },
})
// 替换为你已配置的 STT vendor。
.withStt(sttVendor)
// 替换为你已配置的 LLM vendor。
.withLlm(llmVendor)
.withTts(
new GenericTTS({
url: 'https://your-tts-service.example.com/v1/audio/speech',
headers: {
Authorization: `Bearer ${process.env.CUSTOM_TTS_API_KEY}`,
},
model: 'your-tts-model',
voice: 'alloy',
speed: 1.0,
sampleRate: 16000,
responseFormat: 'pcm',
instruction: 'calm',
additionalParams: {
enable_request_id: false,
},
})
);你可以调用 POST 创建对话式智能体接口时,在 tts 模块中将 vendor 设置为 generic_http,并配置你的 TTS 服务地址和参数。
{
"tts": {
"vendor": "generic_http",
"url": "https://your-tts-service.example.com/v1/audio/speech",
"headers": {
"Authorization": "Bearer <your_tts_api_key>"
},
"params": {
"model": "your-tts-model",
"voice": "alloy",
"speed": 1.0,
"sample_rate": 16000,
"response_format": "pcm",
"instruction": "calm",
"enable_request_id": false
}
}
}相关配置说明如下:
| 参数 | 类型 | 是否必需 | 说明 |
|---|---|---|---|
URL | string | 是 | 自定义 TTS 服务的 HTTP(S) endpoint。 |
Headers | map[string]string | 否 | 调用 TTS 服务时携带的请求头,常用于配置 Authorization。未设置时不会写入 headers。 |
APIKey | string | 否 | TTS 服务鉴权 API key。 |
Model | string | 否 | TTS 模型名称。 |
Voice | string | 否 | 音色名称。 |
Speed | *float64 | 否 | 语速。 |
SampleRate | *vendors.SampleRate | 否 | 输出音频采样率,单位为 Hz。如果你的 TTS 服务暂不支持多采样率,请确保返回音频的采样率与该配置一致。 |
ResponseFormat | string | 否 | 输出音频格式。当前 ConvoAI 支持 pcm。 |
Instruction | string | 否 | 语音风格、情绪或其他播报指令。 |
AdditionalParams | map[string]interface{} | 否 | 透传给 TTS 服务的其他参数;同名字段会被非空的显式字段覆盖。 |
SkipPatterns | []int | 否 | 控制 TTS 跳过特定文本模式。 |
| 参数 | 类型 | 是否必需 | 说明 |
|---|---|---|---|
url | str | 是 | 自定义 TTS 服务的 HTTP(S) endpoint。 |
headers | Dict[str, str] | 否 | 调用 TTS 服务时携带的请求头,常用于配置 Authorization。未设置时不会写入 headers。 |
api_key | str | 否 | TTS 服务鉴权 API key。 |
model | str | 否 | TTS 模型名称。 |
voice | str | 否 | 音色名称。 |
speed | float | 否 | 语速。 |
sample_rate | int | 否 | 输出音频采样率,单位为 Hz。如果你的 TTS 服务暂不支持多采样率,请确保返回音频的采样率与该配置一致。 |
response_format | str | 否 | 输出音频格式。当前 ConvoAI 支持 pcm。 |
instruction | str | 否 | 语音风格、情绪或其他播报指令。 |
additional_params | Dict[str, Any] | 否 | 透传给 TTS 服务的其他参数;同名字段会被显式参数覆盖。 |
skip_patterns | List[int] | 否 | 控制 TTS 跳过特定文本模式。 |
| 参数 | 类型 | 是否必需 | 说明 |
|---|---|---|---|
url | string | 是 | 自定义 TTS 服务的 HTTP(S) endpoint。 |
headers | Record<string, string> | 否 | 调用 TTS 服务时携带的请求头,常用于配置 Authorization。未设置时不会写入 headers。 |
apiKey | string | 否 | TTS 服务鉴权 API key。 |
model | string | 否 | TTS 模型名称。 |
voice | string | 否 | 音色名称。 |
speed | number | 否 | 语速。 |
sampleRate | number | 否 | 输出音频采样率,单位为 Hz。如果你的 TTS 服务暂不支持多采样率,请确保返回音频的采样率与该配置一致。 |
responseFormat | "pcm" | 否 | 输出音频格式。当前 ConvoAI 支持 pcm。 |
instruction | string | 否 | 语音风格、情绪或其他播报指令。 |
additionalParams | Record<string, unknown> | 否 | 透传给 TTS 服务的其他参数;同名字段会被显式字段覆盖。 |
skipPatterns | number[] | 否 | 控制 TTS 跳过特定文本模式。 |
| 配置路径 | 类型 | 是否必需 | 默认值 | 说明 |
|---|---|---|---|---|
tts.vendor | String | 是 | - | 设置为 generic_http,表示使用自定义 TTS 服务。 |
tts.url | String | 是 | - | TTS 服务地址,要求兼容 OpenAI TTS 协议。 |
tts.headers | Object | 否 | - | 调用 TTS 服务时携带的请求头,常用于配置 Authorization。 |
tts.params | Object | 否 | - | TTS 请求参数。除本文列出的字段外,还支持按需配置其他字段,系统会将其透传给 TTS 服务。 |
tts.params.api_key | String | 否 | - | TTS 服务鉴权 API key。如果配置该字段,系统会在调用 TTS 服务时自动携带 Authorization: Bearer <api_key>。 |
tts.params.model | String | 否 | - | TTS 模型名称。 |
tts.params.voice | String | 否 | - | 音色名称。如果你的 TTS 服务暂不支持多音色,可以忽略该参数。 |
tts.params.speed | Number | 否 | - | 语速。 |
tts.params.sample_rate | Integer | 否 | 16000 | 输出音频采样率,单位为 Hz。如果你的 TTS 服务暂不支持多采样率,请确保返回音频的采样率与该配置一致。 |
tts.params.response_format | String | 否 | pcm | 输出音频格式。当前仅支持 pcm。 |
tts.params.instruction | String | 否 | - | 语音风格、情绪或其他播报指令。 |
tts.params.enable_request_id | Boolean | 否 | false | 是否在 TTS 请求体中附带 request_id、request_seq_id 和 request_end。 |
信息
鉴权信息可以通过请求头中的 Authorization 传递,也可以通过 API key 字段传入。如果你的服务同时支持两种方式,建议优先使用请求头,便于和现有 HTTP 鉴权逻辑保持一致。
4. 启动会话
完成配置后,启动智能体会话。会话启动后,对话式 AI 引擎会在智能体需要播报 LLM 回复时自动调用你的 TTS 服务。
session := agent.CreateSession(agentkit.CreateSessionOptions{
Channel: requireEnv("AGORA_CHANNEL"),
AgentUID: requireEnv("AGORA_AGENT_UID"),
RemoteUIDs: []string{"*"},
})
agentSessionID, err := session.Start(ctx)
if err != nil {
log.Fatal(err)
}
log.Printf("Agent started: %s", agentSessionID)session = agent.create_session(
channel=require_env("AGORA_CHANNEL"),
agent_uid=require_env("AGORA_AGENT_UID"),
remote_uids=["*"],
)
agent_session_id = session.start()
print(f"Agent started: {agent_session_id}")const session = agent.createSession({
channel: process.env.AGORA_CHANNEL!,
agentUid: process.env.AGORA_AGENT_UID!,
remoteUids: ['*'],
});
const agentSessionId = await session.start();
console.log('Agent started:', agentSessionId);按需接收请求标识
如果你的 TTS 服务需要区分同一轮播报中的多次请求,可以将 enable_request_id 作为附加参数透传给 TTS 服务。
AdditionalParams: map[string]interface{}{
"enable_request_id": true,
}additional_params={
"enable_request_id": True,
}additionalParams: {
enable_request_id: true,
}开启后,系统会在发送给 TTS 服务的请求体中附带以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
request_id | String | 单次 TTS 请求的唯一标识。 |
request_seq_id | Integer | 同一轮播报内的请求序号,从 0 开始递增。 |
request_end | Boolean | 是否为同一轮播报的最后一次请求。 |
参考信息
示例项目
声网提供了开源的自定义 TTS 示例项目供你参考,你可以前往下载或查看其中的源代码。