Lewati ke konten
kenari.

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

Body-nya JSON.

FieldTipeWajibKeterangan
modelstringyaId model text to speech, misalnya gemini-3-1-flash-tts.
inputstringyaTeks yang akan diucapkan. Lihat Batas panjang teks.
voicestringtidakNama suara. Namanya berbeda per model. Kosongkan untuk memakai suara default model. Lihat Pilih suara.
response_formatstringtidakmp3, wav, pcm, opus, aac atau flac. Tidak semua model menghasilkan semuanya. Kosongkan untuk memakai default model. Lihat Pilih format.
speednumbertidakKecepatan bicara. Hanya berlaku pada model yang mendukungnya.
languagestringtidakKode bahasa, misalnya id atau en. Dideteksi otomatis kalau dikosongkan.

Body response berupa audio mentah, bukan JSON. Content-Type mengikuti format yang kamu minta.

FormatContent-Type
mp3audio/mpeg
wavaudio/wav
pcmaudio/pcm
opusaudio/ogg
aacaudio/aac
flacaudio/flac

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:

Terminal window
curl -s https://kenari.id/v1/models \
| jq '.data[] | select(.endpoints | index("audio_speech")) | {id, voices}'
  • Entri pertama di voices adalah suara default, dipakai kalau voice dikosongkan.
  • Nama dicocokkan tanpa memperhatikan huruf besar atau kecil.
  • Model tanpa field voices belum punya daftar tercatat. kenari tidak memeriksa voice untuk model itu dan meneruskan nilainya ke model.
  • Suara di luar daftar dijawab 400 beserta 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: ....

Format yang bisa dihasilkan sebuah model ada di field formats pada GET /v1/models:

Terminal window
curl -s https://kenari.id/v1/models \
| jq '.data[] | select(.endpoints | index("audio_speech")) | {id, formats}'
  • Entri pertama di formats adalah format default, dipakai kalau response_format dikosongkan.
  • Nama dicocokkan tanpa memperhatikan huruf besar atau kecil.
  • Format di luar daftar dijawab 400 beserta nama yang diizinkan, dan tidak ada biaya yang terpotong. kenari tidak pernah mengganti format diam-diam, karena Content-Type akan menyebut file yang salah.
  • Model tanpa field formats menerima mp3, wav dan pcm. Nilai lain menghasilkan mp3, dengan Content-Type audio/mpeg. Jadi opus, aac dan flac hanya berfungsi pada model yang mencantumkannya di formats.

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.

Terminal window
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.mp3
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")
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()));

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.

StatusKodeKapan
400bad_requestModel bukan model text to speech, input kosong, voice atau response_format tidak tersedia untuk model, atau input lebih panjang dari max_input_chars.
402insufficient_balanceSaldo tidak cukup untuk request ini.
503all_providers_failed, upstream_errorTidak ada provider yang bisa menghasilkan audio. Tidak ada biaya yang terpotong. Coba lagi.

Kode lainnya ada di Error.