The thing that surprised me about running text to speech on our own hardware is how small the model is. One file, 78 MB, holding 904 distinct speakers. That is less than a phone photo burst and about a tenth of what a single mid-range language model weighs, and out of it comes a voice you would not immediately place as synthetic. I measured three of the eight voices the tool exposes: their median pitches are 103 Hz, 184 Hz and 242 Hz, which is a genuine range from a low male voice to a high female one, out of the same file with a different number passed in.
TL;DR: The engine is Piper running on the site's own box, using the LibriTTS-R model. Measured: 113 characters produced 5.8 to 6.1 seconds of audio in about 3 to 4 seconds of wall time, so it synthesises faster than you can listen. You get a 22,050 Hz mono WAV, which is about 2.6 MB a minute. The speed control works but is compressed: the full 0.7 to 1.5 range produces a 1.61x spread in duration rather than the 2.14x the numbers imply, and 0.85 is indistinguishable from 1.0. The same text is never the same audio twice. The text to speech tool caps input at 3,000 characters.
What is doing the speaking?
Piper, a neural text-to-speech engine, running as its own container beside the web app, with a model trained on LibriTTS-R.
That corpus is worth knowing about, because it explains both the quality and the character of the output. It is roughly 585 hours of read English speech, originally from LibriVox audiobook recordings, then put through a speech restoration model to clean up the recording quality of the source material. The speakers are volunteers reading public-domain books.
So the voices sound like people reading aloud, because that is exactly what they were doing. The model is good at declarative sentences and paragraphs of prose, which is what it heard. It is less convincing at anything conversational, because nobody in the training data was having a conversation.
The model file holds 904 speakers and the tool exposes eight of them. The ids in the code are the model's own, picked to span the range rather than to be the best eight, which is a distinction worth keeping in mind if none of the eight suits you.
Are the eight voices different from each other?
Yes, measurably. I generated the same sentence in three of them and computed the median fundamental frequency of the voiced frames:
| Voice | Speaker id | Median F0 |
|---|---|---|
| Voice 2 | 3 | 103.3 Hz |
| Voice 5 | 45 | 183.8 Hz |
| Voice 8 | 150 | 242.3 Hz |
Those are not variations on a theme. Adult male speech typically centres around 85 to 155 Hz and adult female speech around 165 to 255 Hz, so these three sit at the bottom, the middle and the top of the normal human range.
The durations were nearly identical, 2.07 to 2.08 seconds for the same sentence, so switching voice changes timbre and pitch without changing pace. That makes the eight genuinely interchangeable for a given script, which matters if you are producing a set of clips and want to re-record one.
How fast is it?
Faster than listening, which is the number that matters.
| Measure | Value |
|---|---|
| Input | 113 characters |
| Audio produced | 5.77 to 6.08 seconds |
| Wall time | 2,994 to 3,929 ms |
| Ratio | roughly 1.5 to 1.9 times real time |
So a minute of audio takes thirty to forty seconds to make, and the 3,000 character maximum works out at about two and three quarter minutes of speech for something under two minutes of waiting.
The caveat is that one request is served at a time. The server runs a single synthesis slot deliberately: measured on the box, one text alone takes about 2.2 seconds and three at once take about 9 seconds each, so parallelism buys nothing in total throughput and costs the first person in the queue seven seconds. Up to twenty requests may wait; past that the tool says it is busy rather than making you wait several minutes.
There is also a per-visitor budget of twenty generations every ten minutes, which is high enough that normal use never meets it and low enough that nobody turns the box into a free audiobook factory.
What do you get back?
A WAV file, uncompressed, and the size is worth knowing before you make a long one.
codec pcm_s16le
sample rate 22,050 Hz
channels 1 (mono)
bit depth 16
That is 44.1 KB per second of audio, so roughly 2.6 MB a minute, and a full 3,000 character run lands near 7 MB. The 113 character sample above was 254,508 bytes for 5.77 seconds.
Uncompressed is the right default for something you are going to edit or convert, since it is the format every editor takes without complaint and it has no generation loss to add. It is the wrong default for something you are going to upload or email, and the fix is one step: run the WAV through the audio converter and take the MP3 or M4A. Its guide covers which to pick, and the short answer for speech is that anything at or above 128 kbps is fine.
The 22,050 Hz rate is the model's own, and it is half the CD rate. Worth noticing that LibriTTS-R is distributed at 24 kHz, so the model outputs below the rate of the corpus it learned from; that is Piper's own configuration rather than anything lost here. For a voice it is unremarkable either way, since speech energy sits well below 11 kHz, which is what 22,050 Hz carries. It does mean the output will not pass as a studio recording, and resampling it upward adds nothing.
Does the speed control do what it says?
It changes the speed, and not by as much as the number suggests. This is the measured curve:
| Speed setting | Duration | Ratio to 1.0 | Linear would give |
|---|---|---|---|
| 0.7 | 7.268 s | 1.195 | 1.429 |
| 0.85 | 6.142 s | 1.010 | 1.176 |
| 1.0 | 6.084 s | 1.000 | 1.000 |
| 1.25 | 5.271 s | 0.866 | 0.800 |
| 1.5 | 4.516 s | 0.742 | 0.667 |
Monotonic, so the control works in the direction you expect, and compressed at both ends. The full range from 0.7 to 1.5 should be a 2.14x spread in duration and measures 1.61x. The 0.85 setting is within 1% of 1.0, which is to say it does nothing you can hear.
The mechanism is that the setting is passed to the model as a duration scale, and the model's own duration predictor decides how long each phoneme gets. It treats the scale as a strong hint rather than a multiplier.
The practical reading: use 0.7 or 1.5 if you want a noticeably different pace, and do not expect the intermediate settings to give you fine control. If you need an exact duration, generate at 1.0 and change the tempo in an audio editor, where the number means what it says.
Why is the same text never the same audio twice?
Because the model makes a fresh decision about timing on every run.
I sent an identical request twice, same text, same voice, same speed. The results were 6.084 seconds and 6.002 seconds, and the files differ byte for byte. Nothing is cached and nothing is seeded.
That is inherent to this family of models: the duration predictor is stochastic, so phoneme lengths vary slightly between runs even with every input fixed. The variation measured here is about 1.4%, which is inaudible as a difference in pace and plainly visible as a difference in file length.
Two consequences. If a take has an awkward pause or a word that landed oddly, generating it again is a real fix rather than a superstition. And if you are producing a set of clips that have to match, generate them in one session and keep what you get, because coming back tomorrow for one replacement line gives you a line that is a fraction of a second different.
Why is there a 3,000 character limit?
Because of what sits behind it, rather than anything about the text.
Three thousand characters is roughly two and three quarter minutes of speech and about 7 MB of WAV, produced in a single synthesis slot that everyone shares. A 30,000 character chapter would occupy that slot for twenty minutes and hold a 70 MB buffer in memory while doing it.
For anything longer, split on paragraph boundaries and join the parts. That is better practice anyway: a mistake in paragraph nine costs you paragraph nine rather than the whole chapter, and the audio converter will join and convert the set afterwards.
Splitting mid-sentence is the one thing to avoid, because the model decides intonation per utterance. A sentence cut in half produces two fragments that both sound like complete sentences, with a falling tone in the middle of the thought.
What is it good for, and what is it not?
Good for anything that is written to be read aloud, which is a narrower category than it sounds.
| Works well | Works badly |
|---|---|
| Narration over a video or slides | Dialogue between characters |
| An audio version of an article | Anything needing emotion or emphasis |
| Accessibility: hearing your own draft | Names and places outside common English |
| Placeholder voice for a prototype | Precise timing to a video cut |
| Pronunciation of a sentence you wrote | Singing, or anything musical |
The pattern in the right column is control. The model gives you a voice, a speed and a seat to listen from. There is no way to stress a particular word, insert a pause of a given length, change intonation on a question, or spell out an acronym. Those are the things a professional TTS API exposes through markup, and this has none of it.
The first row of the left column is where it earns its place. A voice reading your own writing back to you is the fastest proofreading tool there is, because a sentence that does not work is obvious the moment somebody else says it.
Can you hear a voice before you commit to it?
No, and that is the one piece of the interface I would change.
The eight voices are a dropdown of labels: Voice 1 through Voice 8, with no sample attached to any of them. The only way to find out what Voice 6 sounds like is to generate with it, which occupies the shared synthesis slot, takes a few seconds, and counts against your twenty generations per ten minutes.
For a one-off that is fine. For choosing a voice for a project it means auditioning eight takes of the same line before you start, which is most of a tenth of your budget spent on deciding.
The practical approach is to audition with a short line rather than your script. A sentence of a dozen words comes back in about two seconds and tells you the pitch and character, which is all you are choosing between. Then switch to the real text once you have picked.
The table earlier in this guide is a partial shortcut: Voice 2 is low, Voice 5 is mid, Voice 8 is high. The five I did not measure sit somewhere among them.
How does it compare to a cloud voice?
Not favourably on polish, and that is not the comparison that matters here.
A commercial API gives you better prosody, dozens of languages, markup control over pauses and emphasis, and voices trained for broadcast. If you are producing something for publication, it is worth the money.
What this gives you instead is that the text never leaves the site's own hardware, and the output is yours with no per-character bill and no account. For the uses in the left column above, particularly hearing your own draft read back, the difference in polish is not worth a cloud account and an API key.
The honest summary is that this is the TTS equivalent of a decent built-in microphone. It is good enough that you stop noticing it is there, and not what you would use to record an album.
Can you use the audio commercially?
Probably, with attribution, and the licence deserves a careful look rather than a yes.
The Piper engine is MIT licensed. The model here is trained on LibriTTS-R, which OpenSLR distributes as "License: CC BY 4.0", and CC BY 4.0 permits commercial use provided attribution is given.
The care is warranted because the LibriTTS-R paper's own citation metadata carries a different licence string, the non-commercial no-derivatives variant. That is most likely a leftover in a citation template rather than a statement of intent, and the distribution page is the stronger signal, but the two disagree and I am not in a position to resolve it for you.
So: for anything incidental, this is not a question anybody will ask. For a commercial product built on the audio, read the licence on the specific voice model yourself and take advice rather than taking my reading of a dataset page.
What should you check before publishing audio?
Four things, in the order they go wrong.
- Listen to the whole thing. This sounds obvious and is routinely skipped, and it is the only way to catch a mispronounced name.
- Any proper noun, acronym or unit. The model has no dictionary you can edit. If "Osei" or "GDPR" comes out wrong, the fix is spelling it phonetically in the input text and accepting that the input is now ugly.
- The length, against the slot it has to fill. Remember the pace is only loosely controllable, so leave room rather than planning to the second.
- Convert before uploading. 2.6 MB a minute of WAV is not what you want on a web page.
Why does it run on the site's own server?
Because the texts people have read aloud are frequently their own unpublished writing.
A draft, a script, a cover letter, a speech, a message they are unsure about sending. The conventional alternative posts it to a service that bills per character, keeps the text under terms nobody reads, and requires an account before the first word.
Here it goes to a container beside the web app, is synthesised, and comes back as a file. The costs are visible in every measurement above: one slot at a time, a 3,000 character ceiling, 22 kHz mono, and a voice that is good rather than broadcast. In exchange the text was read by a machine you were already trusting with the page.



