<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: LanguageLit</title>
    <description>The latest articles on DEV Community by LanguageLit (@languagelit).</description>
    <link>https://dev.to/languagelit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4198011%2F3078b37f-f80d-4e26-ad67-8d12e6c8dfa1.png</url>
      <title>DEV Community: LanguageLit</title>
      <link>https://dev.to/languagelit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/languagelit"/>
    <language>en</language>
    <item>
      <title>My TTS kept stressing Russian words wrong. The bug was one line that deleted the answer.</title>
      <dc:creator>LanguageLit</dc:creator>
      <pubDate>Wed, 21 Oct 2026 09:56:03 +0000</pubDate>
      <link>https://dev.to/languagelit/my-tts-kept-stressing-russian-words-wrong-the-bug-was-one-line-that-deleted-the-answer-148b</link>
      <guid>https://dev.to/languagelit/my-tts-kept-stressing-russian-words-wrong-the-bug-was-one-line-that-deleted-the-answer-148b</guid>
      <description>&lt;p&gt;I run a reading site for language learners. Every line of every story has audio, generated with OpenAI's gpt-4o-mini-tts. Russian is the hard case: stress is free, unmarked in normal writing, and it changes meaning (за́мок is a castle, замо́к a lock). A native Russian teacher told me the audio got the stress wrong often enough to be a problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bug
&lt;/h3&gt;

&lt;p&gt;My text already carried the stress. I add an acute accent (U+0301) after the stressed vowel for learners. But a "clean the text before speech" function stripped every combining mark before sending it to the voice. On top of that, the corpus wrote е where the word needs ё, as everyday Russian printing does. So the model guessed the stress on every single word, and it often guessed wrong on ё.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I measured
&lt;/h3&gt;

&lt;p&gt;I rendered 25 test items several ways and checked them with a phone-level recogniser (wav2vec2 xlsr-53 espeak):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;shipped audio: 14 of 21 checkable items right&lt;/li&gt;
&lt;li&gt;same voice, acute marks + ё restored + one sentence in the voice instructions saying what the marks mean: 18 of 21&lt;/li&gt;
&lt;li&gt;an Azure neural voice, marked or not: 11 to 14. The marks barely changed anything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the marks, ё words were right 4 times out of 4 rolls. True context homographs (до́ма vs дома́) stayed around 50% per roll even when marked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Marking 39,465 texts
&lt;/h3&gt;

&lt;p&gt;Stress for each word came from three sources, in this order: my own overrides, the glossary the site already shows learners, then RuAccent (an open-source accent model). Where they disagreed, or the tool was unsure, an LLM reviewer read the word in its sentence. About 12,000 tokens went through that, and roughly 8% of the tool's proposals were wrong, mostly case forms like окна́ / о́кна.&lt;/p&gt;

&lt;h3&gt;
  
  
  The render gate
&lt;/h3&gt;

&lt;p&gt;The model is sampled, so the same input can come out differently. Each clip passes a length check, and single words also pass a stress check from the phone recogniser: vowel quality first, duration as a tie-break. A clip that fails gets re-rolled up to three times. For a stubborn word, the last take respells the unstressed о as а in the copy sent to the voice. That is akanye, the way Russian actually sounds, and it fixed за́мок.&lt;/p&gt;

&lt;p&gt;One trap cost me a whole pilot: ffprobe reports "N/A" for the duration of an MP3 read from a pipe, so my length gate rejected every clip. Decode the audio to measure it, and test one clip before a batch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;About 36,000 clips re-recorded for roughly $35 of API time. On my check set, wrong ё went from about 40% to about 2%, and other stress errors from 13% to under 1%. 82% of clips passed on the first take. 142 single words still failed after three takes; those go to a human ear.&lt;/p&gt;

&lt;p&gt;What a machine still can't certify is a 3-second clip of one word. If you work on Russian TTS and have a better scorer, I'd love to hear about it.&lt;/p&gt;

&lt;p&gt;The site: &lt;a href="https://languagethroughliterature.com" rel="noopener noreferrer"&gt;https://languagethroughliterature.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tom&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>tts</category>
      <category>languagelearning</category>
    </item>
  </channel>
</rss>
