Ruwana Developer Documentation
Avatar API: image + speech or uploaded audio.
Every Avatar request requires one avatar image and exactly one speech source. Use Ruwana TTS with public voice controls, or upload finished audio and let Platform measure its actual duration.
| Field | Contract |
|---|---|
avatar_image | Required PNG/JPEG/WebP · max 16 MB |
speech | Text up to 3000 characters; mutually exclusive with audio |
audio | MP3/WAV/M4A/MP4 audio · max 32 MB; mutually exclusive with speech |
resolution | 720p Standard (default) or 1080p Pro |
voice | Public Ruwana voice name; TTS requests only |
voice_speed | 80–130 · default 100; TTS requests only |
emotion | Neutral, Confident, Happy, Angry, Sad, Presenter or Luxury |
prompt | Optional visual/performance direction |
Voices and pricing
AxelMayaSiennaEthanMarcusEliasNovaCelesteTobyLilaKaiMimi
Standard · 720p
$0.11/sec
TTS included when speech is used.
Pro · 1080p
$0.22/sec
TTS included when speech is used.
Speech-driven Avatar
cURL
curl https://platform.ruwana.studio/v1/avatar/generate \
-H "Authorization: Bearer $RUWANA_API_KEY" \
-H "Idempotency-Key: avatar-tts-001" \
-F "avatar_image=@portrait.jpg" \
-F "speech=Welcome to the new collection." \
-F "resolution=720p" \
-F "voice=Maya" \
-F "voice_speed=100" \
-F "emotion=Confident" \
-F "prompt=Natural premium presenter delivery with restrained gestures."Node.js
import { readFile } from 'node:fs/promises';
const form = new FormData();
form.set('avatar_image', new Blob([await readFile('portrait.jpg')], {type:'image/jpeg'}), 'portrait.jpg');
form.set('speech', 'Welcome to the new collection.');
form.set('resolution', '720p');
form.set('voice', 'Maya');
form.set('voice_speed', '100');
form.set('emotion', 'Confident');
const response = await fetch('https://platform.ruwana.studio/v1/avatar/generate', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.RUWANA_API_KEY,
'Idempotency-Key': 'avatar-tts-001'
},
body: form
});
console.log(await response.json());Uploaded-audio Avatar
Python
import os, requests
with open('portrait.jpg','rb') as image, open('voice.mp3','rb') as audio:
response = requests.post(
'https://platform.ruwana.studio/v1/avatar/generate',
headers={
'Authorization': 'Bearer ' + os.environ['RUWANA_API_KEY'],
'Idempotency-Key': 'avatar-audio-001'
},
files={
'avatar_image': ('portrait.jpg', image, 'image/jpeg'),
'audio': ('voice.mp3', audio, 'audio/mpeg')
},
data={'resolution':'1080p','emotion':'Luxury','prompt':'Controlled premium delivery.'}
)
print(response.json())Do not send voice or voice_speed with uploaded audio. Platform rejects TTS controls when the speech source is already prepared audio.
Prepared-audio duration
Platform initially creates the request around the minimum production reservation, then measures the actual prepared audio and adjusts the quote before Avatar video submission. Accepted Avatar duration is 3–30 seconds.