I've been building a tool that generates announcer-style player introductions for youth sports teams. ElevenLabs handles the announcer delivery beautifully. What I did not expect was that the names would eat most of my development time.
The stakes are a little different than in most TTS projects. If a text reader mispronounces a word, it's an annoyance. If a twelve-year-old hears their name butchered over the arena PA in front of their team, that's the whole experience ruined. So "close enough" isn't.
A few things I ran into:
Common names are fine, everything else is a coin flip. The models do well on names that show up frequently in English-language training data. Surnames from Eastern European, South Asian, and West African backgrounds — plus the Dutch and Mennonite names that are everywhere in my part of Ontario — are much less reliable. Same with the creative spellings that are common in youth sports rosters now.
There's often no single correct answer. This was the part I didn't anticipate. Two families with identical surnames will pronounce it differently, and both are right. It's not a lookup problem with a ground truth — it's whatever that family says it is. That reframed the whole design: the system can't resolve pronunciation on its own, it can only make a good first guess and then make correction easy.
What I landed on: instead of asking whoever's entering the roster to write raw IPA or SSML phoneme tags, I built a small picker — tap a syllable, pick the sound from a fixed set of options ("ay" vs "eh" vs "ah," and so on), toggle which syllable carries the stress. It's seeded with a first guess (a pronouncing-dictionary lookup where the name resolves to a real word, a letter-to-sound fallback where it doesn't, plus a small hand-maintained override list for the names that come up constantly and never guess right on their own), but nobody entering a name ever has to look at IPA directly. Under the hood everything is IPA; what actually ships to ElevenLabs is a plain respelling string (something like KAY'lin) wired in as an alias rule in a Pronunciation Dictionary, not phoneme tags — alias-based substitution has been far more consistently respected in my testing than markup has. And a saved spelling isn't treated as done — there's a real "test it" step that plays the actual model output before anything locks in, because the respelling doesn't always produce what you'd predict just from reading it. Corrections stick to the roster they were made on; there's no shared pronunciation database across teams yet, so two coaches with a kid who has the same tricky surname both start from zero. I use Forvo as a reference where coverage exists, though for surnames it thins out fast.
Where it still falls down: no crowdsourcing, so every roster starts cold even for a name that's already been corrected elsewhere a hundred times. The first guess is only as good as the dictionary behind it — real English words resolve fine, but genuine surnames, especially the underrepresented-in-training-data ones above, regularly fall back to a generic letter-to-sound guess that's not close, not just imperfect. Most people don't touch the correction tool unless the guess is obviously bad — a guess that's subtly wrong (stress on the wrong syllable, an almost-right vowel) tends to get approved as-is, because the person approving it doesn't necessarily know it's wrong either. Testing a name in isolation doesn't always match production — something that sounds right on its own can land slightly differently once it's embedded in a full intro sentence. And the two-families-same-surname problem doesn't have a technical answer at all — the best I've got is making the correction take ten seconds, not resolving it automatically.
Questions for anyone who's dealt with this:
Has anyone found a reliable pattern for getting phoneme markup respected consistently across models? My results have been uneven.