@sakuraspeech/sdk
v0.1.0
Published
Official TypeScript SDK for SakuraSpeech TTS API
Maintainers
Readme
@sakuraspeech/sdk
Official TypeScript/JavaScript SDK for the SakuraSpeech TTS API.
Installation
npm install @sakuraspeech/sdkQuick Start
import { SakuraSpeech } from '@sakuraspeech/sdk'
const client = new SakuraSpeech({ apiKey: 'sk_live_...' })
// Synthesize text to speech
const audio = await client.tts.synthesize({ text: 'こんにちは、世界!' })
await audio.save('output.mp3') // Node.js only
console.log(`Duration: ${audio.duration}s, Size: ${audio.size} bytes`)Configuration
const client = new SakuraSpeech({
apiKey: 'sk_live_...',
baseUrl: 'https://api.sakuraspeech.jp', // default
timeout: 60_000, // milliseconds
maxRetries: 2, // retry on 429/503/network errors
defaultVoice: 'kanon-sakura',
defaultFormat: 'mp3',
})TTS (Text-to-Speech)
Synthesize
const audio = await client.tts.synthesize({
text: 'こんにちは',
voice: 'kanon-sakura',
emotion: 'happy',
speed: 1.0, // 0.5–2.0
pitch: 1.0, // 0.5–2.0
volume: 1.0, // 0.0–1.0
format: 'mp3', // mp3, wav, ogg
sampleRate: 44100, // 44100 のみ対応
})
await audio.save('output.mp3') // Node.js: save to file
audio.content // ArrayBuffer
audio.base64 // base64 string
audio.toBlob() // Blob (browser-compatible)
audio.duration // seconds
audio.charactersUsed // characters consumed
audio.requestId // request IDBatch Synthesis
// Create a batch job
const job = await client.tts.batchCreate({
items: [
{ id: '1', text: 'おはようございます' },
{ id: '2', text: 'こんばんは', voice: 'kanon-sakura', emotion: 'happy' },
],
format: 'mp3',
webhookUrl: 'https://example.com/webhook',
})
console.log(`Batch ID: ${job.batch_id}, Status: ${job.status}`)
// Poll until complete
const completed = await client.tts.batchPoll(job.batch_id, {
interval: 2000, // ms
timeout: 300_000, // ms
})
for (const result of completed.results ?? []) {
console.log(` ${result.id}: ${result.status}`)
}Voices
List Preset Voices
const { voices } = await client.voices.list()
for (const v of voices) {
console.log(`${v.id}: ${v.name} (${v.gender}) - emotions: ${v.emotions}`)
}Preview a Voice
const preview = await client.voices.preview('kanon-sakura')
await preview.save('preview.wav')Voice Cloning
import { readFileSync } from 'fs'
// Clone from a file
const result = await client.voices.clone({
audio: readFileSync('reference.wav'),
name: 'My Custom Voice',
description: 'A friendly female voice',
})
console.log(`Custom voice ID: ${result.custom_voice_id}`)
// Use the cloned voice
const audio = await client.tts.synthesize({
text: 'カスタムボイスのテスト',
voice: `custom:${result.custom_voice_id}`,
})Manage Custom Voices
// List custom voices
const { custom_voices } = await client.voices.customList()
// Get specific custom voice
const voice = await client.voices.customGet('voice-id')
// Delete a custom voice
await client.voices.customDelete('voice-id')User Dictionary
// List entries
const { entries } = await client.dictionary.list()
// Add entries
const result = await client.dictionary.add([
{ word: '東京', reading: 'トウキョウ' },
{ word: 'SakuraSpeech', reading: 'サクラスピーチ', accent: '4' },
])
console.log(`Added ${result.added} entries`)
// Delete entry
await client.dictionary.delete('entry-id')Usage
const usage = await client.usage.get()
console.log(`Plan: ${usage.plan}`)
console.log(`Characters: ${usage.characters.used}/${usage.characters.limit}`)
console.log(`Requests today: ${usage.requests.today}`)Webhooks
// Create a webhook
const webhook = await client.webhooks.create(
'https://example.com/webhook',
['batch.completed']
)
console.log(`Webhook ID: ${webhook.id}, Secret: ${webhook.secret}`)
// List webhooks
const { webhooks } = await client.webhooks.list()
// Delete a webhook
await client.webhooks.delete('webhook-id')Error Handling
import {
SakuraSpeech,
AuthenticationError,
RateLimitError,
NotFoundError,
APIError,
} from '@sakuraspeech/sdk'
const client = new SakuraSpeech({ apiKey: 'sk_live_...' })
try {
const audio = await client.tts.synthesize({ text: 'テスト' })
} catch (e) {
if (e instanceof AuthenticationError) {
console.error('Invalid API key')
} else if (e instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${e.retryAfterSeconds}s`)
} else if (e instanceof NotFoundError) {
console.error('Resource not found')
} else if (e instanceof APIError) {
console.error(`API error: ${e.code} (${e.statusCode}): ${e.message}`)
}
}Error Class Hierarchy
SakuraSpeechError (base)
├── APIError (4xx/5xx, has code, statusCode, requestId)
│ ├── AuthenticationError (401)
│ ├── PermissionError (403)
│ ├── NotFoundError (404)
│ ├── RateLimitError (429, retryAfterSeconds)
│ ├── InternalServerError (500)
│ └── ServiceUnavailableError (503)
├── ConnectionError
└── TimeoutErrorBrowser Usage
The SDK works in browsers with native fetch. The AudioResponse.save() method is Node.js only — in the browser use toBlob() or content instead:
const audio = await client.tts.synthesize({ text: 'ブラウザで再生' })
const blob = audio.toBlob()
const url = URL.createObjectURL(blob)
const audioEl = new Audio(url)
audioEl.play()Requirements
- Node.js >= 18.0.0 (or any browser with native
fetch) - Zero production dependencies
License
MIT
