TTS API 演示:即時請求與回應範例
此演示展示你可以在一分鐘內執行的真實請求,以及回傳的回應格式。API 為文字模型,因此輸出為腳本文字、JSON 和函式呼叫,隨後可由語音引擎朗讀。
更新於

執行前請注意
給任何期望按下播放鍵就能聽到聲音的人一個公平的警告:此 tts api 示範不會產生聲音。該服務透過 uncensored 模型,以 POST /v1/chat/completions 回傳文字。還有另一個端點 GET /v1/models 用於列出可用項目。不會回傳音訊、影像或嵌入向量。
為什麼需要示範?因為許多語音專案需要這部分:腳本撰寫、文字清理、以及決定誰該說話的分割器。以下範例展示了這些工作,輸出格式正是你的語音程式碼會解析的格式。
你需要金鑰。在 API 金鑰頁面 使用 Google 或電子郵件與密碼註冊,然後一鍵領取 $0.50 試用額度。有效期為 7 天,無需信用卡。匯出金鑰以便以下命令可以讀取:
export XTTS_API_KEY="paste-your-key-here"
curl -s https://api.xtts.cc/v1/models -H "Authorization: Bearer $XTTS_API_KEY" | grep uncensored
如果該呼叫回傳包含 uncensored 的 JSON 列表,表示金鑰有效,你可以繼續。
範例 1:一般請求
最小的有效呼叫要求一段口語風格的短段落:
curl -s https://api.xtts.cc/v1/chat/completions \
-H "Authorization: Bearer $XTTS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [
{"role": "system", "content": "You write short lines for a voice actor. No stage directions."},
{"role": "user", "content": "Welcome listeners to a show about lighthouses. Two sentences."}
],
"temperature": 0.7,
"max_tokens": 120
}'
回覆如下列範例所示。content 內的文字每次執行都會不同,因此請將其視為結構說明,而非記錄的輸出。
{
"id": "chatcmpl-example",
"object": "chat.completion",
"model": "uncensored",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Welcome to the show. Tonight we climb the stairs of the world's loneliest lighthouses."
},
"finish_reason": "stop"
}
],
"usage": {"prompt_tokens": 38, "completion_tokens": 21, "total_tokens": 59}
}
你的語音程式碼讀取 choices[0].message.content。finish_reason 會說明生成結束的原因:stop 表示自然結束,length 表示因 max_tokens 而提前截斷。若省略 max_tokens,完成內容可能會使用 100,000 token 上下文視窗中剩餘的所有空間,這包含提示詞與完成內容的總和。
標頭告訴你的資訊
在 curl 指令中加入 -i,你將看到 X-Request-Id、X-Balance-USD、X-RateLimit-Limit-Requests 和 X-RateLimit-Limit-Concurrency。餘額標頭在示範中很有用,因為你可以看到每次呼叫後餘額微幅下降。此請求的用量計算為 38 x $0.15 / 1,000,000 加上 21 x $0.50 / 1,000,000,即 $0.0000057 加上 $0.0000105,約為 $0.0000162。
範例 2:串流輸出腳本
處理音訊時,你通常不希望等待完整文字。加入 "stream": true,API 會發送伺服器發送事件,一次傳送一小段文字片段。下方的 Node 範例會在文字到達時將其列印出來,你可以在這裡將句子餵入佇列。
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.xtts.cc/v1",
apiKey: process.env.XTTS_API_KEY,
});
const stream = await client.chat.completions.create({
model: "uncensored",
stream: true,
messages: [
{ role: "user", content: "Read a four-line weather report for a coastal town." },
],
});
for await (const chunk of stream) {
const piece = chunk.choices[0]?.delta?.content ?? "";
process.stdout.write(piece);
}
process.stdout.write("\n");
將其作為 ES 模組執行(儲存為 demo.mjs,並在執行 node demo.mjs 之前執行 npm install openai)。在 API 傳輸協定層,每個事件都是以 data: 開頭的行,後面接著 JSON,串流則以最終標記結束。token 用量會在串流結束時報告。規劃時有一點很重要:串流請求會保留其並行請求槽位,直到串流結束,因此緩慢的消費者可能會阻塞你自己的下一個請求。
範例 3:以函式呼叫作為語音路由器
函式呼叫讓模型回傳結構化的指示而非一般文字。在語音專案中,這是為每行選擇傳遞風格的乾淨方式。你定義一個名為 say 的函式,模型會填入其參數。你的程式碼接著決定要如何使用這些參數。模型本身不會執行任何操作。
import json
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.xtts.cc/v1", api_key=os.environ["XTTS_API_KEY"])
tools = [{
"type": "function",
"function": {
"name": "say",
"description": "Queue one line for the voice engine.",
"parameters": {
"type": "object",
"properties": {
"text": {"type": "string"},
"style": {"type": "string", "enum": ["calm", "urgent", "whisper"]},
},
"required": ["text", "style"],
},
},
}]
messages = [
{"role": "system", "content": "Always answer by calling say, once per line."},
{"role": "user", "content": "The alarm sounds. The guard tells everyone to leave."},
]
r = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)
msg = r.choices[0].message
for call in msg.tool_calls or []:
args = json.loads(call.function.arguments)
print(args["style"], "->", args["text"])
參數以 JSON 字串形式到達,因此在使用前需解析並驗證。模型可能會產生超出你列舉的風格或遺漏欄位,未經檢查的值不應到達你的引擎。若希望對話繼續,請附加助手訊息和帶有 role: "tool" 及對應 tool_call_id 的回覆,然後再次呼叫 API。
串流時,函式呼叫會分段到達。函式名稱先出現,參數字串在多個區塊中累積,因此請依索引收集片段,並在串流結束後一次性解析。
範例 4:JSON 模式用於演員名單
如果你偏好跳過工具定義,JSON 模式會在訊息內容中提供有效的 JSON。這很適合將粗略的場景轉換為按說話者分行的內容。
curl -s https://api.xtts.cc/v1/chat/completions \
-H "Authorization: Bearer $XTTS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"response_format": {"type": "json_object"},
"temperature": 0.2,
"messages": [
{"role": "system", "content": "Return JSON: {\"lines\": [{\"speaker\": string, \"text\": string}]}"},
{"role": "user", "content": "Ana asks Ben to hold the ladder. Ben agrees reluctantly."}
]
}'
JSON 模式保證輸出可以解析,但不保證符合你的結構。如上所述,在提示詞中描述結構,並在程式碼中檢查金鑰。低溫度可保持結構穩定。
範例 5:一次請求處理長文件
上下文視窗為 100,000 token,由提示詞和完成內容共享。這足以發送長轉錄稿或整個短篇故事,並要求提供口語化版本。請求主體最多可達 8 MB,因此大小很少是限制;token 數量才是。
以下是高負載請求的成本。假設你傳送 80,000 token 並取得 2,000 token 的輸出。輸入:80,000 x $0.15 / 1,000,000 = $0.012。輸出:2,000 x $0.50 / 1,000,000 = $0.001。總計為 $0.013,因此 $0.50 的試用額度可涵蓋約 38 次此類請求。長輸入的成本相對較低,而長輸出則較昂貴,這就是為什麼大型文字的摘要和改寫負擔得起,但一次生成整本小說則不可行的原因。
長輸入的實用技巧:將你的指示放在最前面,並在結尾重複關鍵規則。模型傾向於最好地遵循最近的指示,且在 80,000 token 的原始文本後加上一行提醒,成本幾乎為零。
閱讀演示中的錯誤
故意弄壞一次,以便日後識別。使用錯誤的金鑰發送請求,你會得到驗證錯誤而非完成內容。從試用金鑰同時發送十個請求,部分會以 HTTP 429 回傳。
429 有三個原因,錯誤代碼可區分它們:
rate_limited表示一分鐘內請求過多:試用金鑰為 60,完整金鑰為 300。concurrency表示同時進行中的請求過多:試用金鑰為 2,完整金鑰為 8。- 帶有
Retry-After: 5標頭的 429 表示服務曾短暫過載。等待五秒鐘後再次發送。
失敗或拒絕的請求不會收費,因此錯誤不花錢。要查看你的金鑰有哪些限制,請在任何正常回應上讀取 X-RateLimit-Limit-Requests 和 X-RateLimit-Limit-Concurrency。一個微小的重試迴圈,等待 Retry-After 的值(若缺失則等待五秒),就是演示腳本所需的全部。
下一步嘗試
一旦這四個呼叫運作正常,你就擁有了腳本管線的所有組件。將一般請求包裝在函式中,將串流迴圈運行至佇列,並將佇列連接到你選擇的語音引擎。引擎在價格、授權和品質上有所不同,因此請閱讀它們的當前條款。此服務不提供其中之一,也不對它們發表任何聲明。
在實驗期間,成本保持較低。每百萬輸入 token 為 $0.15,每百萬輸出 token 為 $0.50,典型的演示呼叫成本不到一分錢,而 $0.50 試用額度可涵蓋數百次。請參閱 定價頁面,以 $20 至 $500 進行儲值,並享有 5% 至 15% 的獎金,可透過加密貨幣支付。文件涵蓋完整的參數列表、速率限制(完整金鑰為 8 個並行和每分鐘 300 個)和錯誤代碼。提示詞不用於訓練。
第一個下午的合理順序:執行一般請求直到語調正確,切換到串流輸出並在句子完成時列印句子,然後根據你的語音程式碼希望接收輸入的方式,添加函式呼叫或 JSON 模式。將每個提示詞保存在版本控制下的檔案中。當最終音訊中的某行聽起來不正確時,你可以追溯產生它的精確指示,並一次更改一項。
更多指南
問答
我能在此演示中聽到範例語音嗎?
不行。API 僅回傳文字、JSON 和函式呼叫。你需要自行提供語音引擎將文字轉為音訊。
我要傳送哪個模型 ID?
將模型值設為 uncensored,並使用 base URL https://api.xtts.cc/v1 及你的金鑰於 Authorization: Bearer 標頭中。
試用金鑰能執行這些演示嗎?
可以。試用金鑰允許 2 個並行請求和每分鐘 60 個請求,這對這些範例已足夠。請依序執行。
為什麼會收到 429 回應?
你超過了每分鐘請求數(rate_limited)、同時開啟的請求過多(concurrency),或服務短暫過載。若提供 Retry-After,請等待後再重試。
只差一張表單,即可取得金鑰
建立帳號、複製金鑰、更改基礎 URL。這就是整個設定過程。