Voice acting is one of the last things indie devs ship and the first thing players notice is missing.
A professional voice actor costs $200–$400/hr. A full voiced RPG might need 50+ hours — a $10,000+ line item that kills the budget.
With a TTS API, you can voice every character for under $5 — and change any line instantly during development.
The workflow
- Write dialogue in your dialogue system
- Export as JSON or CSV
- Run a generation script — each line gets an audio file
- Import into Unity/Godot
- Hook up to your trigger system
Once set up, changing a line takes 5 seconds and costs fractions of a cent.
Pick voices for your characters
LeanVox has 238+ voices organized by archetype:
- Gaming — hero voices, villain voices, NPC archetypes
- Narrator — world exposition, item descriptions
- Meditation/Calm — sage characters, ancient beings
- Kids — young player characters, sidekicks
Or use Max tier to describe any voice:
result = client.generate(
text="The ancient prophecy speaks of one who will...",
model="max",
instructions="Elderly male wizard, deep gravelly voice, slow deliberate speech, hint of otherworldly echo"
)
Batch generate all dialogue (with async jobs)
Submit all lines in parallel using async jobs — much faster than waiting for each line sequentially:
import json
import os
import requests
from leanvox import Leanvox
client = Leanvox(api_key="lv_live_...")
with open("dialogue.json") as f:
dialogue = json.load(f)
VOICES = {
"town_guard": "gaming_gruff_male",
"village_elder": "narrator_wise_elder",
"young_hero": "podcast_casual_male",
"mysterious_stranger": "narrator_dramatic_male",
"merchant": "podcast_conversational_female",
}
os.makedirs("audio/dialogue", exist_ok=True)
# Submit all jobs in parallel
jobs = {}
for line in dialogue:
output_path = f"audio/dialogue/{line['id']}.mp3"
if os.path.exists(output_path):
continue # skip already generated
voice = VOICES.get(line["character"], "podcast_casual_male")
job = client.generate_async(text=line["text"], model="pro", voice=voice)
jobs[job.job_id] = (line["id"], output_path)
print(f"Submitted {len(jobs)} jobs...")
# Collect results
for job_id, (line_id, output_path) in jobs.items():
result = client.jobs.wait(job_id)
audio = requests.get(result.audio_url).content
with open(output_path, "wb") as f:
f.write(audio)
print(f"✅ {line_id}")
Or use the CLI for single lines:
lvox generate --model pro --voice gaming_gruff_male --file guard_line.txt --output guard_01.mp3
Unity integration
public class DialogueTrigger : MonoBehaviour
{
[SerializeField] private AudioSource audioSource;
public void PlayLine(string lineId)
{
StartCoroutine(LoadAndPlay(lineId));
}
private IEnumerator LoadAndPlay(string lineId)
{
var clip = Resources.Load<AudioClip>($"Audio/Dialogue/{lineId}");
if (clip != null)
{
audioSource.clip = clip;
audioSource.Play();
}
yield return null;
}
}
Godot (GDScript)
extends Node
var http_request = HTTPRequest.new()
func generate_voice_line(text: String, voice: String) -> void:
add_child(http_request)
http_request.request_completed.connect(_on_request_completed)
var headers = ["Authorization: Bearer " + OS.get_environment("LEANVOX_API_KEY"), "Content-Type: application/json"]
var body = JSON.stringify({"text": text, "model": "pro", "voice": voice})
http_request.request("https://api.leanvox.com/v1/tts/generate", headers, HTTPClient.METHOD_POST, body)
What does it cost?
| Game type | Est. dialogue | Pro tier cost |
|---|---|---|
| Small game (200 lines) | ~50K chars | $0.50 |
| Mid-size RPG (2,000 lines) | ~500K chars | $5.00 |
| Large story-driven (5,000 lines) | ~1.5M chars | $15.00 |
Your $1.00 signup credit voices a small game completely.
When to use a real voice actor
AI voice: all NPCs, ambient dialogue, narrator, tutorial prompts, procedural content.
Real voice actors: main protagonist, iconic villain, cutscene moments where delivery needs to be perfect.
Use both — AI voices everything, then swap key lines with pro recordings if your game gets traction.
Try it
Browse the voice library · Get your API key · Docs
Originally published at leanvox.com/blog
Top comments (0)