Text to speech
Ubah teks menjadi suara. Endpoint ini kompatibel dengan OpenAI Audio Speech, jadi SDK resmi OpenAI bisa dipakai dengan base URL https://kenari.id/v1. Hanya model text to speech yang dilayani di sini. Mengirim model lain mengembalikan 400.
POST /v1/audio/speech
Request
Section titled “Request”Body-nya JSON.
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
model | string | ya | Id model text to speech, misalnya gemini-3-1-flash-tts. |
input | string | ya | Teks yang akan diucapkan. Lihat Batas panjang teks. |
voice | string | tidak | Nama suara. Namanya berbeda per model. Kosongkan untuk memakai suara default model. Lihat Pilih suara. |
response_format | string | tidak | mp3, wav, pcm, opus, aac atau flac. Tidak semua model menghasilkan semuanya. Kosongkan untuk memakai default model. Lihat Pilih format. |
speed | number | tidak | Kecepatan bicara. Hanya berlaku pada model yang mendukungnya. |
language | string | tidak | Kode bahasa, misalnya id atau en. Dideteksi otomatis kalau dikosongkan. |
Response
Section titled “Response”Body response berupa audio mentah, bukan JSON. Content-Type mengikuti format yang kamu minta.
| Format | Content-Type |
|---|---|
mp3 | audio/mpeg |
wav | audio/wav |
pcm | audio/pcm |
opus | audio/ogg |
aac | audio/aac |
flac | audio/flac |
Pilih suara
Section titled “Pilih suara”Setiap model punya nama suara sendiri, dan namanya tidak saling menggantikan. kenari meneruskan voice ke model apa adanya. Daftar suara sebuah model ada di field voices pada GET /v1/models:
curl -s https://kenari.id/v1/models \ | jq '.data[] | select(.endpoints | index("audio_speech")) | {id, voices}'- Entri pertama di
voicesadalah suara default, dipakai kalauvoicedikosongkan. - Nama dicocokkan tanpa memperhatikan huruf besar atau kecil.
- Model tanpa field
voicesbelum punya daftar tercatat. kenari tidak memeriksavoiceuntuk model itu dan meneruskan nilainya ke model. - Suara di luar daftar dijawab
400beserta nama yang diizinkan, dan tidak ada biaya yang terpotong.
Gaya bicara tidak punya field tersendiri. Tulis arahannya di depan teks, misalnya Bacakan seperti pembawa berita: ....
Pilih format
Section titled “Pilih format”Format yang bisa dihasilkan sebuah model ada di field formats pada GET /v1/models:
curl -s https://kenari.id/v1/models \ | jq '.data[] | select(.endpoints | index("audio_speech")) | {id, formats}'- Entri pertama di
formatsadalah format default, dipakai kalauresponse_formatdikosongkan. - Nama dicocokkan tanpa memperhatikan huruf besar atau kecil.
- Format di luar daftar dijawab
400beserta nama yang diizinkan, dan tidak ada biaya yang terpotong. kenari tidak pernah mengganti format diam-diam, karenaContent-Typeakan menyebut file yang salah. - Model tanpa field
formatsmenerimamp3,wavdanpcm. Nilai lain menghasilkanmp3, denganContent-Typeaudio/mpeg. Jadiopus,aacdanflachanya berfungsi pada model yang mencantumkannya diformats.
Batas panjang teks
Section titled “Batas panjang teks”Audio dikembalikan setelah sintesis selesai, bukan melalui streaming, dan setiap provider punya batas waktunya sendiri, jadi teks yang terlalu panjang tidak akan selesai. Kalau sebuah model mencatat batasnya, angkanya muncul sebagai max_input_chars di GET /v1/models, dan teks yang lebih panjang dijawab 400 sebelum ada biaya yang terpotong. Tanpa field itu kenari tidak membatasi panjang teks, tetapi request yang sangat panjang tetap bisa gagal karena batas waktu provider. Pecah teks panjang menjadi beberapa request.
Contoh
Section titled “Contoh”curl https://kenari.id/v1/audio/speech \ -H "Authorization: Bearer $KENARI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gemini-3-1-flash-tts", "input": "Halo, selamat datang di kenari.", "voice": "Kore", "response_format": "mp3" }' \ --output speech.mp3Python
Section titled “Python”import os
from openai import OpenAI
client = OpenAI( base_url="https://kenari.id/v1", api_key=os.environ["KENARI_API_KEY"],)
response = client.audio.speech.create( model="gemini-3-1-flash-tts", input="Halo, selamat datang di kenari.", voice="Kore", response_format="mp3",)response.write_to_file("speech.mp3")JavaScript
Section titled “JavaScript”import fs from "node:fs";import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://kenari.id/v1", apiKey: process.env.KENARI_API_KEY,});
const response = await client.audio.speech.create({ model: "gemini-3-1-flash-tts", input: "Halo, selamat datang di kenari.", voice: "Kore", response_format: "mp3",});fs.writeFileSync("speech.mp3", Buffer.from(await response.arrayBuffer()));Penagihan
Section titled “Penagihan”Text to speech ditagih per 1.000 karakter input, dibulatkan ke atas. Jumlahnya ditahan saat request diterima dan dilepas kalau tidak ada audio yang dikirim. Selengkapnya ada di Cara penagihan, dan harga setiap model ada di Model & harga.
| Status | Kode | Kapan |
|---|---|---|
| 400 | bad_request | Model bukan model text to speech, input kosong, voice atau response_format tidak tersedia untuk model, atau input lebih panjang dari max_input_chars. |
| 402 | insufficient_balance | Saldo tidak cukup untuk request ini. |
| 503 | all_providers_failed, upstream_error | Tidak ada provider yang bisa menghasilkan audio. Tidak ada biaya yang terpotong. Coba lagi. |
Kode lainnya ada di Error.