Voice agent teams keep hitting the same wall. The catalog holds 400 voices and the brief asks for the one that is not in it: a Quebecoise receptionist for a Montreal dealership, a narrator in his sixties with lecture hall authority. Briefs outnumber any catalog, and cloning closes the gap one speaker at a time, each carrying sourcing, consent and a licence.
Gradium, the Paris-based voice AI company spun out of the Kyutai research lab, has shipped a different answer. Voice Design reads a written description and returns complete new voices in a few seconds. No reference audio, no speaker, no rights to clear.
Is it deployable? Yes, Voice Design is live in the Gradium API and in Studio, free on every plan including the free tier, and a kept voice runs on the same streaming Text-to-Speech endpoint as any catalog voice, at the same latency and output formats.
The casting brief is the API
The description is the only input the model gets. Gradium’s documentation lists the attributes it responds to, and they read like a casting call: gender, age band, accent or origin, pitch, pace, energy, timbre and resonance, register and manner, and the job the voice is doing. Descriptions run 1 to 500 characters in English, French, Spanish, Portuguese or German. Gradium advises ending with the intended use, because it steers delivery and register rather than only the colour of the voice.
One request returns 1 to 5 candidates, typically ready in 3 to 5 seconds. They are variations on a single character, so a different character means a different description, not more samples.
From candidate to production voice
The flow is four calls. POST /voice-generator/generate mints candidate ids with ready: false. GET /voice-generator/embeddings polls until they flip. Each candidate auditions through the ordinary TTS endpoint, using the candidate id as voice_id. POST /voices/from-embedding promotes the one you keep.
Candidates carry three restrictions converted voices do not: audition text is capped at 100 characters, they are REST only, and the TTS WebSocket and Speech-to-Speech reject them. Unconverted candidates are deleted after 30 days. Converting is free, clears the expiry, and uses one custom voice slot shared with clones. The free tier holds 5, paid plans 1,000.
Sampling is deliberately non-deterministic. Gradium team expands the description first, and that expansion varies per request, so the same prompt with a fixed seed still yields a different voice.
<div class="panel">
<div class="rowlab">Gender and age</div>
<div class="chips" data-slot="who">
<button class="chip" aria-pressed="false" data-v="A British female voice">British female</button>
<button class="chip" aria-pressed="false" data-v="An Irish English male voice">Irish male</button>
<button class="chip" aria-pressed="false" data-v="An American English male voice">American male</button>
<button class="chip" aria-pressed="false" data-v="A Quebecoise female voice">Quebecoise female</button>
</div>
<div class="rowlab" style="margin-top:12px">Age band</div>
<div class="chips" data-slot="age">
<button class="chip" aria-pressed="false" data-v="20 to 30">20 to 30</button>
<button class="chip" aria-pressed="false" data-v="40 to 55">40 to 55</button>
<button class="chip" aria-pressed="false" data-v="55 to 65">55 to 65</button>
</div>
<div class="rowlab" style="margin-top:12px">Pitch, pace and energy</div>
<div class="chips" data-slot="prosody">
<button class="chip" aria-pressed="false" data-v="high pitch, fast pacing and high energy">high, fast, bright</button>
<button class="chip" aria-pressed="false" data-v="mid-low pitch, steady natural pacing and medium energy">mid-low, steady</button>
<button class="chip" aria-pressed="false" data-v="low pitch, slow pacing and low-to-mid energy">low, slow, calm</button>
</div>
<div class="rowlab" style="margin-top:12px">Timbre</div>
<div class="chips" data-slot="timbre">
<button class="chip" aria-pressed="false" data-v="bright sparkling resonance">bright sparkling</button>
<button class="chip" aria-pressed="false" data-v="warm rounded resonance">warm rounded</button>
<button class="chip" aria-pressed="false" data-v="gravelly timbre with heavy vocal fry">gravelly</button>
</div>
<div class="rowlab" style="margin-top:12px">Intended use, which steers delivery</div>
<div class="chips" data-slot="use">
<button class="chip" aria-pressed="false" data-v="Ideal for a friendly receptionist or assistant.">receptionist</button>
<button class="chip" aria-pressed="false" data-v="Ideal for empathic de-escalation and complex IT support.">support agent</button>
<button class="chip" aria-pressed="false" data-v="Ideal for projecting academic authority.">narrator</button>
<button class="chip" aria-pressed="false" data-v="Ideal for game and character narration.">game character</button>
</div>
<div class="brief" id="briefOut"><span class="ph">Tap options above and your description builds here.</span></div>
<div class="meter"><div class="bar"><span id="briefBar"></span></div><div class="num" id="briefNum">0 / 500</div></div>
<p class="hint">Concrete beats evaluative. Gradium’s docs advise naming pitch, pace and timbre outright rather than asking for "a great narrator voice", and putting the intended use at the end.</p>
</div>
</section>
<section class="slide" data-i="1" aria-label="Step 2: sample candidates">
<div class="step">Step 2 of 5</div>
<h3>Sample the candidates</h3>
<p class="lede">One POST returns 1 to 5 candidate voices, typically ready in a few seconds. They are variations on a single character, not different characters.</p>
<div class="panel">
<div class="ctl">
<div>
<label for="cfg">cfg_scale, how literally the voice follows the text. Default 5.0</label>
<input type="range" id="cfg" min="1" max="20" step="0.5" value="5">
</div>
<div>
<label for="ns">n_samples</label>
<div class="segs" id="ns" role="group" aria-label="number of candidates">
<button class="seg" aria-pressed="false" data-n="1">1</button>
<button class="seg" aria-pressed="true" data-n="3">3</button>
<button class="seg" aria-pressed="false" data-n="5">5</button>
</div>
</div>
<div style="align-self:flex-end">
<button class="go" id="gen">Generate candidates</button>
</div>
</div>
<p class="hint" id="cfgNote"></p>
<div class="cands" id="cands"></div>
<p class="hint">Every request mints new ids. The same description and the same seed still return a different voice, because the description is expanded before sampling. If you like one, keep it.</p>
</div>
</section>
<section class="slide" data-i="2" aria-label="Step 3: audition and convert">
<div class="step">Step 3 of 5</div>
<h3>Audition, then convert</h3>
<p class="lede">A candidate is a draft. It plays through the normal Text-to-Speech route under three restrictions, and it disappears after 30 days unless you promote it.</p>
<div class="panel">
<div class="rowlab">Pick a candidate and play a line</div>
<div class="cands" id="cands2"></div>
<div class="flow" id="limits">
<span class="pill">Audition text capped at 100 characters</span>
<span class="pill">REST only, no WebSocket</span>
<span class="pill">Candidate expires after 30 days</span>
</div>
<div style="margin-top:13px"><button class="go" id="conv">Convert to a permanent voice</button></div>
<div class="vid" id="vidBox">
<div class="k">POST /voices/from-embedding returns</div>
<div class="v" id="vidVal">voice_id</div>
<div class="flow" style="margin-top:10px">
<span class="pill on">REST Text-to-Speech</span>
<span class="pill on">TTS WebSocket</span>
<span class="pill on">Speech-to-Speech</span>
<span class="pill on">No 100 character cap</span>
</div>
</div>
<p class="hint">Converting is free and clears the expiry, but the voice takes one custom-voice slot, shared with voice clones. The free tier holds 5.</p>
</div>
</section>
<section class="slide" data-i="3" aria-label="Step 4: the benchmark">
<div class="step">Step 4 of 5</div>
<h3>What the listening test measured</h3>
<p class="lede">Gradium ran accent prompts through six systems and asked native speakers to pick the closer match, without labels. A model judge was then run over the same prompts.</p>
<div class="toggle" role="group" aria-label="evaluation view">
<button id="tHuman" aria-pressed="true">Human raters, win rate</button>
<button id="tLlm" aria-pressed="false">Gemini 3.1 Pro, score out of 5</button>
</div>
<div class="chart" id="chart"></div>
<p class="par" id="parNote">50 percent is par. Win rate is wins plus half of ties, over all comparisons.</p>
<p class="cap">7,627 blind pairwise comparisons across English, French, German, Spanish and Portuguese, September 2026. The model judge produced the same ranking as the human raters. Both evaluations were designed and run by Gradium, so read them as vendor-reported.</p>
</section>
<section class="slide" data-i="4" aria-label="Step 5: accents and shipping notes">
<div class="step">Step 5 of 5</div>
<h3>Where the accent gap was widest</h3>
<p class="lede">The strongest results came from regional accents that catalogs usually flatten into a single national voice.</p>
<div class="chart" id="chart2"></div>
<div class="panel" style="margin-top:16px">
<div class="rowlab">Before you ship</div>
<div class="flow">
<span class="pill">5 languages: en, fr, es, pt, de</span>
<span class="pill">Description 1 to 500 characters</span>
<span class="pill">Store the voice_id, it cannot be regenerated</span>
<span class="pill">Only 4 json_config keys are accepted</span>
<span class="pill">SSML is spoken aloud, not parsed</span>
</div>
<p class="hint">An unrecognised json_config key does not raise an error. The request returns 201 and the candidates simply never become ready, so bound the polling loop and treat a timeout as a bad request.</p>
</div>
</section>
</div>
<div class="nav">
<button id="prev" disabled>Back</button>
<div class="dots" id="dots" role="tablist" aria-label="steps"></div>
<button id="next">Next</button>
</div>
<div class="foot">
<span>Sources: Gradium launch post and API documentation, September 2026.</span>
<span><b>Built by Marktechpost</b></span>
</div>
</div>
<script>
(function(){
var reduce = window.matchMedia && window.matchMedia(‘(prefers-reduced-motion: reduce)’).matches;
/* ———- resize ———- */
function post(){
var h = document.body.offsetHeight + 40;
try{ parent.postMessage({ mtpGradiumHeight: h }, ‘*’); }catch(e){}
}
window.addEventListener(‘load’, post);
window.addEventListener(‘resize’, post);
setInterval(post, 700);
/* ———- slides ———- */
var slides = [].slice.call(document.querySelectorAll(‘.slide’));
var dots = document.getElementById(‘dots’);
var prev = document.getElementById(‘prev’);
var next = document.getElementById(‘next’);
var cur = 0;
slides.forEach(function(s,i){
var b = document.createElement(‘button’);
b.setAttribute(‘role’,’tab’);
b.setAttribute(‘aria-label’,’Step ‘ + (i+1));
b.setAttribute(‘aria-current’, i===0 ? ‘true’:’false’);
b.addEventListener(‘click’, function(){ show(i); });
dots.appendChild(b);
});
function show(i){
cur = Math.max(0, Math.min(slides.length-1, i));
slides.forEach(function(s,k){ s.classList.toggle(‘on’, k===cur); });
[].slice.call(dots.children).forEach(function(d,k){ d.setAttribute(‘aria-current’, k===cur?’true’:’false’); });
prev.disabled = cur===0;
next.textContent = cur===slides.length-1 ? ‘Start over’ : ‘Next’;
if(cur===3) drawChart();
if(cur===4) drawAccents();
if(cur===2) syncCands2();
post();
}
prev.addEventListener(‘click’, function(){ show(cur-1); });
next.addEventListener(‘click’, function(){ show(cur===slides.length-1 ? 0 : cur+1); });
document.addEventListener(‘keydown’, function(e){
if(e.key===’ArrowRight’){ show(cur+1); }
if(e.key===’ArrowLeft’){ show(cur-1); }
});
/* ———- 1. brief builder ———- */
var order = [‘who’,’age’,’prosody’,’timbre’,’use’];
var picked = {};
document.querySelectorAll(‘.chips’).forEach(function(row){
var slot = row.getAttribute(‘data-slot’);
row.addEventListener(‘click’, function(e){
var b = e.target.closest(‘.chip’);
if(!b) return;
var v = b.getAttribute(‘data-v’);
if(picked[slot] === v){ delete picked[slot]; } else { picked[slot] = v; }
[].slice.call(row.children).forEach(function(c){
c.setAttribute(‘aria-pressed’, c.getAttribute(‘data-v’)===picked[slot] ? ‘true’:’false’);
});
renderBrief();
});
});
function renderBrief(){
var out = document.getElementById(‘briefOut’);
var bar = document.getElementById(‘briefBar’);
var num = document.getElementById(‘briefNum’);
var has = order.some(function(k){ return picked[k]; });
if(!has){
out.innerHTML = ‘<span class="ph">Tap options above and your description builds here.</span>’;
bar.style.width = ‘0%’; num.textContent = ‘0 / 500’;
post(); return;
}
var lead = picked.who || ‘A voice’;
var mid = [];
if(picked.age) mid.push(picked.age);
if(picked.prosody) mid.push(picked.prosody);
if(picked.timbre) mid.push(picked.timbre);
var s = lead + (mid.length ? ‘, ‘ + mid.join(‘, ‘) : ”) + ‘.’;
if(picked.use) s += ‘ ‘ + picked.use;
out.textContent = s;
var pct = Math.min(100, Math.round(s.length/500*100));
bar.style.width = pct + ‘%’;
num.textContent = s.length + ‘ / 500’;
post();
}
/* ———- 2. candidates ———- */
var cfg = document.getElementById(‘cfg’);
var cfgNote = document.getElementById(‘cfgNote’);
function noteFor(v){
if(v <= 6) return ‘At ‘ + v.toFixed(1) + ‘, candidates differ from each other. Gradium recommends this range when exploring with 3 to 5 samples.’;
if(v <= 12) return ‘At ‘ + v.toFixed(1) + ‘, the voice tracks the description more closely. Recommended when candidates drift, or when generating one at a time.’;
return ‘At ‘ + v.toFixed(1) + ‘, the voice follows the description very literally, at the cost of naturalness, and candidates converge on each other.’;
}
cfg.addEventListener(‘input’, function(){ cfgNote.textContent = noteFor(parseFloat(cfg.value)); post(); });
cfgNote.textContent = noteFor(5);
var nSamples = 3;
document.getElementById(‘ns’).addEventListener(‘click’, function(e){
var b = e.target.closest(‘.seg’); if(!b) return;
nSamples = parseInt(b.getAttribute(‘data-n’),10);
[].slice.call(this.children).forEach(function(c){
c.setAttribute(‘aria-pressed’, c===b ? ‘true’:’false’);
});
});
var made = [];
function rid(){
var cs = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789’;
var s = ”;
for(var i=0;i<16;i++){ s += cs.charAt(Math.floor(Math.random()*cs.length)); }
return ‘vox_emb_’ + s;
}
function bars(n){
var h = ”;
for(var i=0;i<n;i++){
var v = 25 + Math.round(Math.random()*75);
h += ‘<b style="height:’ + v + ‘%"></b>’;
}
return h;
}
function card(id, ready){
return ‘<div class="cand’ + (ready?’ ready’:”) + ‘" role="button" tabindex="0" aria-pressed="false" data-id="’ + id + ‘">’ +
‘<div class="wave">’ + bars(14) + ‘</div>’ +
‘<div class="id">’ + id + ‘</div>’ +
‘<div class="state’ + (ready?’ ready’:”) + ‘">’ + (ready ? ‘ready: true’ : ‘ready: false’) + ‘</div></div>’;
}
document.getElementById(‘gen’).addEventListener(‘click’, function(){
made = [];
for(var i=0;i<nSamples;i++){ made.push(rid()); }
var box = document.getElementById(‘cands’);
box.innerHTML = made.map(function(id){ return card(id,false); }).join(”);
post();
var flip = function(){
box.innerHTML = made.map(function(id){ return card(id,true); }).join(”);
syncCands2(); post();
};
if(reduce){ flip(); } else { setTimeout(flip, 1300); }
});
/* ———- 3. audition and convert ———- */
function syncCands2(){
var box = document.getElementById(‘cands2’);
var ids = made.length ? made : [rid(), rid(), rid()];
if(!made.length) made = ids;
box.innerHTML = ids.map(function(id){ return card(id,true); }).join(”);
post();
}
syncCands2();
var chosen = null;
function pick(el){
var box = document.getElementById(‘cands2’);
[].slice.call(box.children).forEach(function(c){
c.setAttribute(‘aria-pressed’, c===el ? ‘true’:’false’);
c.classList.remove(‘play’);
});
chosen = el.getAttribute(‘data-id’);
if(!reduce){
el.classList.add(‘play’);
setTimeout(function(){ el.classList.remove(‘play’); }, 2400);
}
}
document.getElementById(‘cands2’).addEventListener(‘click’, function(e){
var c = e.target.closest(‘.cand’); if(c) pick(c);
});
document.getElementById(‘cands2’).addEventListener(‘keydown’, function(e){
if(e.key===’Enter’ || e.key===’ ‘){
var c = e.target.closest(‘.cand’);
if(c){ e.preventDefault(); pick(c); }
}
});
document.getElementById(‘conv’).addEventListener(‘click’, function(){
var box = document.getElementById(‘cands2’);
if(!chosen){ pick(box.children[0]); }
var cs = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789’;
var s=”; for(var i=0;i<16;i++){ s += cs.charAt(Math.floor(Math.random()*cs.length)); }
document.getElementById(‘vidVal’).textContent = ‘uid: ‘ + s;
document.getElementById(‘vidBox’).classList.add(‘on’);
post();
});
/* ———- 4. charts ———- */
var human = [
[‘Gradium’, 72.6, true],
[‘ElevenLabs v3’, 59.0, false],
[‘Inworld’, 44.8, false],
[‘Fish Audio’, 36.7, false],
[‘MiniMax’, 31.7, false]
];
var llm = [
[‘Gradium’, 4.06, true],
[‘ElevenLabs’, 3.86, false],
[‘Inworld’, 3.64, false],
[‘Fish Audio’, 3.51, false]
];
var accents = [
[‘Quebecois, FR’, 97, true],
[‘Rioplatense, ES’, 86, false],
[‘Bavarian, DE’, 85, false],
[‘Colombian, ES’, 83, false],
[‘African Portuguese’, 83, false]
];
function paint(el, rows, max, suffix){
el.innerHTML = rows.map(function(r){
return ‘<div class="brow’ + (r[2]?’ lead’:”) + ‘">’ +
‘<div class="nm">’ + r[0] + ‘</div>’ +
‘<div class="tr"><span class="fl" data-w="’ + (r[1]/max*100) + ‘"></span></div>’ +
‘<div class="vl">’ + r[1].toFixed(suffix===’%’?1:2) + suffix + ‘</div></div>’;
}).join(”);
var fls = el.querySelectorAll(‘.fl’);
var go = function(){
[].slice.call(fls).forEach(function(f,i){
var w = f.getAttribute(‘data-w’) + ‘%’;
if(reduce){ f.style.width = w; }
else { setTimeout(function(){ f.style.width = w; }, 90*i); }
});
};
requestAnimationFrame(go);
post();
}
var mode = ‘human’;
function drawChart(){
var el = document.getElementById(‘chart’);
if(mode===’human’){
paint(el, human, 100, ‘%’);
document.getElementById(‘parNote’).textContent = ’50 percent is par. Win rate is wins plus half of ties, over all comparisons.’;
} else {
paint(el, llm, 5, ”);
document.getElementById(‘parNote’).textContent = ‘Mean rating over 50 accent prompts. 5 means every requested accent detail is audibly present.’;
}
}
document.getElementById(‘tHuman’).addEventListener(‘click’, function(){
mode=’human’;
this.setAttribute(‘aria-pressed’,’true’);
document.getElementById(‘tLlm’).setAttribute(‘aria-pressed’,’false’);
drawChart();
});
document.getElementById(‘tLlm’).addEventListener(‘click’, function(){
mode=’llm’;
this.setAttribute(‘aria-pressed’,’true’);
document.getElementById(‘tHuman’).setAttribute(‘aria-pressed’,’false’);
drawChart();
});
function drawAccents(){ paint(document.getElementById(‘chart2’), accents, 100, ‘%’); }
renderBrief();
post();
})();
</script>
</body>
</html>
“>
The benchmark, and how to read it
Gradium ran a blind pairwise listening test on accent prompts across six voice design systems reachable through public APIs and five languages. Native speakers heard two unlabelled clips and picked the closer match, or a tie. Across 7,627 comparisons, Gradium reports a 72.6% win rate against the field, 13.6 points ahead of ElevenLabs eleven_ttv_v3 at 59.0%, followed by Inworld at 44.8%, Fish Audio at 36.7% and MiniMax at 31.7%. Win rate is wins plus half of ties, so 50% is par. Gradium placed first in all five languages. The widest margins came on regional accents that most catalogs flatten: Quebecois French at 97%, Rioplatense Spanish at 86%, Bavarian German at 85%, Colombian Spanish and African Portuguese at 83%.
A model judge over the same prompt set agreed. Gemini 3.1 Pro rated single unlabelled clips from 1 to 5 and produced the same ranking: Gradium 4.06, ElevenLabs 3.86, Inworld 3.64, Fish Audio 3.51. Separately, the product page claims 83.4% prompt adherence on the English split of InstructTTSEval, the academic benchmark for instruction following in TTS. (Note: All of these numbers are vendor designed and vendor run.)
Key Takeaways
- Voice Design turns a 500 character description into up to 5 new voices in seconds, no reference audio required.
- It is live and free on every Gradium plan, in the API and Studio, across 5 languages.
- Vendor run blind tests put it at a 72.6% win rate over 7,627 comparisons, first in all 5 languages.
- Kept voices become a normal
voice_idon REST, WebSocket and Speech-to-Speech. - Sampling is non-deterministic, so an unsaved candidate is gone for good after 30 days.
Check out the Technical details and Docs. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post Gradium Launches Voice Design: Write a Prompt, Get a Brand New Synthetic Voice in Seconds appeared first on MarkTechPost.