关于 text-to-speech
此技能通过 HeyGen v3 API 和 Starfish TTS 模型,将文本生成独立语音音频。支持查找音色,并设置 SSML、语速、语言和地区。
主要功能
- 01查找兼容 Starfish 的音色
- 02从文本或 SSML 生成音频
- 03设置语速、语言和地区
- 04使用词级时间戳进行同步
- 05分页查找音色
适用场景
- 01为选定音色生成旁白音频
- 02使用 SSML 停顿或标记生成语音
- 03利用词级时间戳同步字幕
MCP 相关
若有 HeyGen MCP 工具,技能建议用它们列出 TTS 音色并生成语音;否则使用 HeyGen v3 HTTP API。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ heygen-com/ skills --skill text-to-speech安装后在 Claude Code 中输入/text-to-speech确认已加载。
详细介绍
文本转语音(HeyGen Starfish)
通过 v3 API 使用 HeyGen 自研的 Starfish TTS 模型,将文本生成为语音音频文件。此技能用于独立的音频生成,与视频创作分开。
身份验证
所有请求都需要 X-Api-Key 标头。设置 HEYGEN_API_KEY 环境变量。
curl -X GET "https://api.heygen.com/v3/voices?engine=starfish" \
-H "X-Api-Key: $HEYGEN_API_KEY"
工具选择
如果有 HeyGen MCP 工具(mcp__heygen__*),优先使用它们,而不是直接调用 HTTP API。
| 任务 | MCP 工具 | 备用方式(直接调用 API) |
|---|---|---|
| 列出 TTS 语音 | mcp__heygen__list_audio_voices | GET /v3/voices?engine=starfish |
| 生成语音音频 | mcp__heygen__text_to_speech | POST /v3/voices/speech |
默认工作流
- 使用
mcp__heygen__list_audio_voices列出语音(或调用GET /v3/voices?engine=starfish) - 选择符合所需语言、性别和特征的语音
- 使用文本和 voice_id 调用
mcp__heygen__text_to_speech(或调用POST /v3/voices/speech) - 使用返回的
audio_url下载或播放音频
列出 TTS 语音
检索与 Starfish TTS 模型兼容的语音。
**注意:**此操作使用统一的
GET /v3/voices端点,并通过engine=starfish筛选,仅返回兼容 TTS 的语音。并非所有视频语音都支持 Starfish TTS。响应采用分页形式,可使用next_token获取后续页面。
查询参数
| 参数 | 类型 | 说明 |
|---|---|---|
engine | string | 按引擎筛选(TTS 语音使用 starfish) |
type | string | public 或 private |
language | string | 按语言筛选 |
gender | string | 按性别筛选 |
limit | integer | 每页结果数,1-100 |
token | string | 来自 next_token 的分页游标 |
curl
curl -X GET "https://api.heygen.com/v3/voices?engine=starfish" \
-H "X-Api-Key: $HEYGEN_API_KEY"
TypeScript
interface AudioVoiceItem {
voice_id: string;
name: string;
language: string;
gender: "female" | "male" | "unknown";
preview_audio_url: string | null;
support_pause: boolean;
support_locale: boolean;
type: string;
}
interface TTSVoicesResponse {
error: null | string;
data: AudioVoiceItem[];
has_more: boolean;
next_token: string | null;
}
async function listTTSVoices(): Promise<AudioVoiceItem[]> {
const allVoices: AudioVoiceItem[] = [];
let token: string | null = null;
do {
const url = new URL("https://api.heygen.com/v3/voices");
url.searchParams.set("engine", "starfish");
if (token) url.searchParams.set("token", token);
const response = await fetch(url.toString(), {
headers: { "X-Api-Key": process.env.HEYGEN_API_KEY! },
});
const json: TTSVoicesResponse = await response.json();
if (json.error) {
throw new Error(json.error);
}
allVoices.push(...json.data);
token = json.next_token;
} while (token);
return allVoices;
}
Python
import requests
import os
def list_tts_voices() -> list:
all_voices = []
token = None
while True:
params = {"engine": "starfish"}
if token:
params["token"] = token
response = requests.get(
"https://api.heygen.com/v3/voices",
headers={"X-Api-Key": os.environ["HEYGEN_API_KEY"]},
params=params,
)
data = response.json()
if data.get("error"):
raise Exception(data["error"])
all_voices.extend(data["data"])
if not data.get("has_more"):
break
token = data.get("next_token")
return all_voices
响应格式
{
"error": null,
"data": [
{
"voice_id": "f38a635bee7a4d1f9b0a654a31d050d2",
"name": "Chill Brian",
"language": "English",
"gender": "male",
"preview_audio_url": "https://resource.heygen.ai/text_to_speech/WpSDQvmLGXEqXZVZQiVeg6.mp3",
"support_pause": true,
"support_locale": false,
"type": "public"
}
],
"has_more": false,
"next_token": null
}
生成语音音频
使用指定语音将文本转换为语音音频。
端点
POST https://api.heygen.com/v3/voices/speech
请求字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | Y | 要转换的文本内容(1-5000 个字符) |
voice_id | string | Y | 来自 GET /v3/voices?engine=starfish 的语音 ID |
input_type | string | "text"(默认)或用于完整 SSML 标记的 "ssml" | |
speed | number | 语速,0.5-2.0(默认:1.0) | |
language | string | 基础语言代码(例如 "en"、"pt")。若省略则自动检测 | |
locale | string | 多语言语音使用的 BCP-47 区域设置(例如 "en-US"、"pt-BR") |
curl
curl -X POST "https://api.heygen.com/v3/voices/speech" \
-H "X-Api-Key: $HEYGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Hello! Welcome to our product demo.",
"voice_id": "YOUR_VOICE_ID",
"speed": 1.0
}'
TypeScript
interface TTSRequest {
text: string;
voice_id: string;
input_type?: "text" | "ssml";
speed?: number;
language?: string;
locale?: string;
}
interface WordTimestamp {
word: string;
start: number;
end: number;
}
interface TTSResponse {
error: null | string;
data: {
audio_url: string;
duration: number;
request_id?: string;
word_timestamps?: WordTimestamp[];
};
}
async function textToSpeech(request: TTSRequest): Promise<TTSResponse["data"]> {
const response = await fetch(
"https://api.heygen.com/v3/voices/speech",
{
method: "POST",
headers: {
"X-Api-Key": process.env.HEYGEN_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify(request),
}
);
const json: TTSResponse = await response.json();
if (json.error) {
throw new Error(json.error);
}
return json.data;
}
Python
import requests
import os
def text_to_speech(
text: str,
voice_id: str,
input_type: str = "text",
speed: float = 1.0,
language: str | None = None,
locale: str | None = None,
) -> dict:
payload = {
"text": text,
"voice_id": voice_id,
"speed": speed,
}
if input_type != "text":
payload["input_type"] = input_type
if language:
payload["language"] = language
if locale:
payload["locale"] = locale
response = requests.post(
"https://api.heygen.com/v3/voices/speech",
headers={
"X-Api-Key": os.environ["HEYGEN_API_KEY"],
"Content-Type": "application/json",
},
json=payload,
)
data = response.json()
if data.get("error"):
raise Exception(data["error"])
return data["data"]
响应格式
{
"error": null,
"data": {
"audio_url": "https://resource2.heygen.ai/text_to_speech/.../id=365d46bb.wav",
"duration": 5.526,
"request_id": "p38QJ52hfgNlsYKZZmd9",
"word_timestamps": [
{ "word": "<start>", "start": 0.0, "end": 0.0 },
{ "word": "Hey", "start": 0.079, "end": 0.219 },
{ "word": "there,", "start": 0.239, "end": 0.459 },
{ "word": "<end>", "start": 5.526, "end": 5.526 }
]
}
}
使用示例
基本 TTS
const result = await textToSpeech({
text: "Welcome to our quarterly earnings call.",
voice_id: "YOUR_VOICE_ID",
});
console.log(`Audio URL: ${result.audio_url}`);
console.log(`Duration: ${result.duration}s`);
调整语速
const result = await textToSpeech({
text: "We're thrilled to announce our newest feature!",
voice_id: "YOUR_VOICE_ID",
speed: 1.1,
});
为多语言语音指定语言和区域设置
const result = await textToSpeech({
text: "Bem-vindo ao nosso produto.",
voice_id: "MULTILINGUAL_VOICE_ID",
language: "pt",
locale: "pt-BR",
});
使用 SSML 输入
const result = await textToSpeech({
text: '<speak>Hello <break time="1s"/> and welcome!</speak>',
voice_id: "YOUR_VOICE_ID",
input_type: "ssml",
});
查找语音并生成音频
async function generateSpeech(text: string, language: string): Promise<string> {
const voices = await listTTSVoices();
const voice = voices.find(
(v) => v.language.toLowerCase().includes(language.toLowerCase())
);
if (!voice) {
throw new Error(`No TTS voice found for language: ${language}`);
}
const result = await textToSpeech({
text,
voice_id: voice.voice_id,
});
return result.audio_url;
}
const audioUrl = await generateSpeech("Hello and welcome!", "english");
使用 Break 标签插入停顿
在文本中使用 SSML 风格的 break 标签来插入停顿:
word <break time="1s"/> word
规则:
- 使用带
s后缀的秒数:<break time="1.5s"/> - 标签前后必须有空格
- 使用自闭合标签格式
使用 v3 时,也可以通过 input_type: "ssml" 启用完整 SSML 支持,从而使用 break 标签以外的更丰富标记:
{
"text": "<speak>Welcome! <break time=\"1s\"/> Let's get started.</speak>",
"voice_id": "YOUR_VOICE_ID",
"input_type": "ssml"
}
最佳实践
- 使用
GET /v3/voices?engine=starfish查找兼容的声音——统一的/v3/voices端点提供所有类型的声音,因此 TTS 必须使用engine=starfish筛选条件 - 设置
locale前检查support_locale——只有多语言声音支持选择地区 - 将速度保持在 0.8-1.2 之间,以获得自然的输出效果
- 生成语音前,使用
preview_audio_url试听声音(部分声音的值可能为 null) - 在响应中使用
word_timestamps,以同步字幕或定时文本叠加层 - 在文本中使用 SSML break 标签来添加停顿:
word <break time="1s"/> word - 需要完全控制 SSML 标记(而不只是简单的 break 标签)时,使用
input_type: "ssml" - 对声音列表进行分页——v3 端点会分页返回结果;使用
has_more和next_token获取所有声音
评论
支持 Markdown