Hakila Docs

Text-to-Speech

以 OpenAI Audio Speech 規格呼叫 OpenAI、Gemini、xAI 與 Azure 的文字轉語音

Hakila 提供 OpenAI 相容的 POST /v1/audio/speech,把文字合成語音。OpenAI 的 TTS 模型原樣轉發; Gemini、xAI 與 Azure AI Speech 由 Gateway 翻譯成各自的原生 API,呼叫端只需要認識 OpenAI 一種格式。 回應本體就是音訊位元組(audio/mpeg、audio/wav …),可以直接寫檔或播放。

TTS 模型與文字生成模型在目錄中是不同類型:GET /v1/models 的每筆回傳帶 type, tts 走 /v1/audio/speech;用錯端點會回 400 並提示正確端點。

支援的模型

種子目錄目前包含(單價以 Console「系統模型」為準):

模型 id供應商輸入上限計費單價
openai/gpt-4o-mini-ttsOpenAI2,000 tokens字元≈ $15 / 1M 字元(OpenAI 實際以 tokens 計,約 $0.015 / 分鐘)
openai/tts-1OpenAI4,096 字元字元$15 / 1M 字元
openai/tts-1-hdOpenAI4,096 字元字元$30 / 1M 字元
google/gemini-3.1-flash-tts-previewGemini8,192 tokenstokens$1 / 1M 文字輸入 tokens、$20 / 1M 音訊輸出 tokens
google/gemini-2.5-flash-preview-ttsGemini8,192 tokenstokens$0.50 / $10
google/gemini-2.5-pro-preview-ttsGemini8,192 tokenstokens$1 / $20
x-ai/ttsxAI60,000 字元字元$15 / 1M 字元
azure/neural-ttsAzure AI Speech20,000 字元字元$16 / 1M 字元(標準 Neural 語音)
azure/neural-hd-ttsAzure AI Speech20,000 字元字元$22 / 1M 字元(Dragon/DragonHD 語音)
azure/mai-voice-2Azure AI Speech20,000 字元字元$22 / 1M 字元(MAI-Voice-2/2.1 語音)
azure/mai-voice-2-flashAzure AI Speech20,000 字元字元$15 / 1M 字元(MAI-Voice-2/2.1 Flash 語音)

TTS 模型的 context_length 代表單次輸入的上限(參考值)。平台可在 Console 新增其他 TTS 模型, 包含後台新增的 OpenAI 相容供應商(例如支援 /audio/speech 的自架服務); Anthropic 沒有 TTS API,無法設為 tts 類型。

快速開始

官方 OpenAI SDK 只要把 base_url 指到 Hakila、api_key 換成 Hakila API Key 就能使用。 裸模型名稱(tts-1)會在已啟用的 tts 模型中比對名稱並補上開發商前綴;有多個同名模型時回 400,找不到時回 404(見不帶前綴的模型名稱)。

curl https://api.hakila.ai/v1/audio/speech \
  -H "Authorization: Bearer $HAKILA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o-mini-tts",
    "input": "今天的天氣真好,適合出門走走。",
    "voice": "coral",
    "instructions": "用溫暖、友善的語氣說話。",
    "response_format": "mp3"
  }' \
  --output speech.mp3

成功時回 200,本體為音訊;Content-Type 依 response_format(audio/mpeg、audio/wav、audio/pcm、audio/opus、audio/ogg …)。

請求欄位

欄位OpenAIGeminixAIAzure說明
model必填必填必填必填目錄中 type: tts 的 id;不支援 hakila/auto 與 Preset
input≤ 4,096 字元建議 ≤ 8k tokens≤ 60,000 字元≤ 20,000 字元;可直接傳 <speak> 開頭的 SSMLHakila 統一擋 100,000 字元以上
voicealloy、ash、coral、nova…(預設 alloy)Kore、Puck、Zephyr…(預設 Kore)eve、ara、rex、sal、leo(預設 eve)完整語音名稱,例如 zh-TW-HsiaoChenNeural;須屬於模型的語音家族(預設依模型,見下方)
instructionsgpt-4o-mini-tts 支援併入提示({instructions}\n\nTRANSCRIPT:\n{input})忽略(用文字內的 speech tags)忽略語氣/情緒指示
response_formatmp3(預設)/opus/aac/flac/wav/pcmwav(預設)/pcmmp3(預設)/wav/pcm/mulaw/alawmp3(預設)/wav/pcm/opus不支援的格式回 400
speed0.25–4.0忽略轉發轉成 SSML prosody rate語速
stream_formataudio(預設)/sse只接受 audio只接受 audio只接受 audiosse 只有 OpenAI 支援
language忽略languageCode(例如 zh-TW)language(預設 auto)SSML xml:lang(預設由語音名稱推得)Hakila 延伸欄位
sample_rate忽略忽略output_format.sample_rate忽略Hakila 延伸欄位
speakers忽略多人對話 [{ "speaker", "voice" }]忽略忽略Hakila 延伸欄位,見下方
style忽略忽略忽略SSML mstts:express-as style,例如 cheerful、happyHakila 延伸欄位,可用值依語音而定
style_degree忽略忽略忽略styledegree,0.01–2(預設 1)Hakila 延伸欄位,需同時帶 style
role忽略忽略忽略role,例如 Girl、YoungAdultFemaleHakila 延伸欄位,少數語音支援

其他欄位對 OpenAI 相容上游原樣透傳,對其他供應商會被忽略。

Gemini 多人對話

Gemini 支援最多兩位說話者,在 input 裡以名稱標出對白,並用 speakers 指定每位的語音:

curl https://api.hakila.ai/v1/audio/speech \
  -H "Authorization: Bearer $HAKILA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemini-2.5-flash-preview-tts",
    "input": "Joe: 嗨,今天過得如何?\nJane: 很好啊,剛跑完步。",
    "speakers": [
      { "speaker": "Joe", "voice": "Kore" },
      { "speaker": "Jane", "voice": "Puck" }
    ],
    "response_format": "wav"
  }' --output dialogue.wav

Gemini TTS 只回 24kHz 16-bit mono PCM,Hakila 在 response_format: wav 時補上 WAV 檔頭; 要 mp3/opus 請改用其他供應商,或自行轉碼。

Gemini 偶發沒有音訊

google/gemini-2.5-flash-preview-tts 對很短、或讀起來像指令的文字(例如「要朗讀的文字」),偶爾會回 200 卻沒有音訊、finishReason 為 OTHER。Hakila 遇到這種回應會原樣自動重送,最多 2 次,呼叫端不需要另外處理; 重送的請求不計費,總延遲會包含重送時間。三次都失敗才回 502。

改寫提示詞(例如加上「Say:」)無法穩定避免這種情況。較完整的句子幾乎不會遇到; 新專案也可以改用 3.x 系列的 Gemini TTS 模型。被安全政策擋下(blockReason)的回應不會重送。

Azure 語音、風格與 SSML

Azure 的 voice 必須是完整語音名稱,可在 Hakila Models 依語言挑選, 或到 Azure 的語音庫查詢。四個 Azure 模型共用同一個端點, 差別在語音家族與單價,每個模型只接受自己家族的語音,帶到其他家族會回 400 並指出該用哪個模型:

模型語音家族語音名稱範例未帶 voice 時的預設
azure/neural-tts標準 Neuralzh-TW-HsiaoChenNeural、ja-JP-NanamiNeuralen-US-AvaMultilingualNeural
azure/neural-hd-ttsDragon/DragonHDzh-CN-Xiaomo:DragonHDFlashLatestNeural、en-US-Ava:DragonLatestNeuralen-US-Tiana:DragonHDFlashLatestNeural
azure/mai-voice-2MAI-Voice-2/2.1zh-CN-Bo:MAI-Voice-2、en-US-Harper:MAI-Voice-2.1en-US-Harper:MAI-Voice-2
azure/mai-voice-2-flashMAI-Voice-2/2.1 Flashzh-CN-Bo:MAI-Voice-2-Flash、en-US-Harper:MAI-Voice-2.1-Flashen-US-Harper:MAI-Voice-2-Flash

台灣中文(zh-TW)目前只有標準 Neural 語音;MAI-Voice 涵蓋英文、簡體中文、韓文、法文、德文等二十多種語言。

許多語音支援說話風格,以 style(可加 style_degree)與 role 指定,Hakila 會轉成 SSML 的 mstts:express-as:

curl https://api.hakila.ai/v1/audio/speech \
  -H "Authorization: Bearer $HAKILA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "azure/mai-voice-2",
    "input": "太好了!我們終於完成這個專案了。",
    "voice": "zh-CN-Bo:MAI-Voice-2",
    "style": "happy",
    "style_degree": 1.5
  }' --output happy.mp3

可用的風格依語音而定(Hakila Models 的「說話風格」選單只列該語音支援的值)。傳統 Neural 語音遇到不支援的風格會改用預設語氣; MAI-Voice 語音則會直接回 400。style_degree 目前只對簡體中文語音與 MAI-Voice 有效。

input 若以 <speak 開頭會視為完整 SSML 原樣送出,voice/speed/language/style 不再套用; SSML 裡每個 <voice name> 仍須屬於模型的語音家族。

路由與允許清單

  • model 必須是這把 API Key 在 GET /v1/models 中看得到、且 type 為 tts 的 id; 不在目錄、未啟用、未被組織或 API Key 允許,一律回 400。API Key 若是自訂允許清單,之後新上線的 TTS 模型要另外勾選(見允許清單)
  • 把 chat/embedding 模型送進 /v1/audio/speech 回 400 並指向正確端點;反過來把 tts 模型送進 Chat/Embeddings 也一樣
  • hakila/auto 不支援 TTS(回 400),候選也只會落在 chat 模型
  • 金鑰解析順序與 Chat 相同:BYOK → 平台金鑰;沒有金鑰回 502
  • 上游位址:OpenAI 相容上游 {BaseUrl}/audio/speech;Gemini 原生 models/{model}:generateContent(responseModalities: ["AUDIO"],金鑰以 x-goog-api-key 帶入); xAI {BaseUrl}/tts;Azure https://{region}.tts.speech.microsoft.com/cognitiveservices/v1(金鑰以 Ocp-Apim-Subscription-Key 帶入)

計費

  • OpenAI/xAI/Azure:上游不回 usage,Hakila 以 input 的字元數(Unicode code point)記在 prompt_tokens, 費用 = 字元數 × 模型輸入單價(單價表的「輸入」欄即 USD / 1M 字元);沒有輸出與 Prompt Cache 單價
  • Gemini:使用 API 回傳的真實 usage,prompt_tokens 為文字輸入 tokens、completion_tokens 為音訊輸出 tokens, 分別乘以模型的輸入/輸出單價
  • 上游回錯誤、或 Gemini 沒有回音訊(安全政策擋下、模型回文字、finishReason: OTHER)時不計費; OTHER 自動重送後成功的請求,只依最後成功那次的 usage 計費
  • 不支援 Response Cache(音訊不進快取);預算與組織儲值的 402 檢查與 Chat 相同
  • 用量紀錄的 response body 只保留 Content-Type、位元組數與計費依據,不保存音訊

錯誤

狀態情境
400缺少 model/input、speed/sample_rate/style/style_degree/role 不合法、模型不是 tts 類型、不在允許清單、供應商沒有 TTS API、供應商不支援該 response_format/stream_format、Azure 模型與語音家族不符、MAI-Voice 語音不支援指定的風格
401API Key 缺少、無效或過期
402儲值用盡或預算超標
502供應商金鑰缺失、上游失敗,或 Gemini 沒有回傳音訊(finishReason: OTHER 會先自動重送 2 次)
504上游在首字元逾時(預設 30 秒)內沒有回應

錯誤為 JSON,形狀與 Chat Completions 相同(error.message/error.code);OpenAI/xAI 的 4xx/5xx 原樣轉出, Gemini 與 Azure 的錯誤會轉成同一形狀。完整欄位請見 API Reference。

本頁目錄