<?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: Servin Osmanov</title>
    <description>The latest articles on DEV Community by Servin Osmanov (@servin_osmanov).</description>
    <link>https://dev.to/servin_osmanov</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%2F3583111%2Fb3feb8b3-8b2e-4b44-96f8-41d587423dbf.jpg</url>
      <title>DEV Community: Servin Osmanov</title>
      <link>https://dev.to/servin_osmanov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/servin_osmanov"/>
    <language>en</language>
    <item>
      <title>Fine-tuning was the easy part: what shipping ASR for a low-resource language taught me</title>
      <dc:creator>Servin Osmanov</dc:creator>
      <pubDate>Wed, 23 Sep 2026 19:49:45 +0000</pubDate>
      <link>https://dev.to/servin_osmanov/fine-tuning-was-the-easy-part-what-shipping-asr-for-a-low-resource-language-taught-me-4331</link>
      <guid>https://dev.to/servin_osmanov/fine-tuning-was-the-easy-part-what-shipping-asr-for-a-low-resource-language-taught-me-4331</guid>
      <description>&lt;p&gt;The fine-tune took an hour and a half on a single consumer GPU. Everything that made that hour and a half mean anything took months.&lt;/p&gt;

&lt;p&gt;This is the second post in a series about building speech tech for Crimean Tatar, a language with no datasets to speak of. &lt;a href="https://ai.ana-yurt.dev/blog/2026-09-kak-rodilas-ideya/" rel="noopener noreferrer"&gt;The first one&lt;/a&gt; covered synthesis and how the project started; this one is the recogniser — much less a story about training than about measurement.&lt;/p&gt;

&lt;p&gt;The headline, so you can decide whether to keep reading:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;WER&lt;/th&gt;
&lt;th&gt;CER&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;the model I started from&lt;/td&gt;
&lt;td&gt;34.6%&lt;/td&gt;
&lt;td&gt;11.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+ fine-tuning (≈1.5 h, one GPU)&lt;/td&gt;
&lt;td&gt;20.1%&lt;/td&gt;
&lt;td&gt;9.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+ tuning how it decodes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;17.0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F03dw47dphjkxkw148o8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F03dw47dphjkxkw148o8x.png" alt="Left to right: starting model, after fine-tuning, after decode-time tuning. The third bar cost zero training." width="799" height="491"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Left to right: starting model, after fine-tuning, after decode-time tuning. The third bar cost zero training.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now the parts worth your time.&lt;/p&gt;
&lt;h2&gt;
  
  
  I gave the model an exam before I tried to teach it
&lt;/h2&gt;

&lt;p&gt;I already had a "working" Crimean Tatar recogniser: a large Whisper, fine-tuned on our language, which I'd been using on clean studio audio where it looked fine. I had read its transcripts and nodded. I had never scored it.&lt;/p&gt;

&lt;p&gt;So the first thing I did here was not improve anything. I measured. 34.6% WER — every third word wrong. That's not "rough": it can't back archive search, can't produce training pairs for synthesis, and an assistant built on it mishears you constantly. I only knew that because I finally scored the thing I'd been eyeballing for a year.&lt;/p&gt;

&lt;p&gt;One footnote on that baseline: 34.6% slightly &lt;em&gt;understates&lt;/em&gt; it, because the model writes &lt;code&gt;1954&lt;/code&gt; where the book spells out &lt;code&gt;Biñ doquz yüz elli dört&lt;/code&gt; and the scorer counts four substitutions. Small, but if I don't say it, the number is dressed up.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hold out whole recordings, not random clips
&lt;/h2&gt;

&lt;p&gt;Standard practice is a random 90/10 split. Here that would have been meaningless. Adjacent clips come from the same recording, same reader, same microphone, same afternoon — and the segmenter routinely cuts one sentence across two neighbouring clips, so a random split drops half a sentence in train and the other half in eval. What you measure then isn't language ability. It's whether the model memorised a voice and a room.&lt;/p&gt;

&lt;p&gt;So I held out &lt;strong&gt;two entire books, two readers the model had never heard&lt;/strong&gt;: 893 clips, 1 h 52 min. One move removes the voice, the mic, the recording era and the vocabulary of a particular text at once. If your data has structure — speaker, session, document, device — split on it. Random splitting is only safe when clips are genuinely independent, and in low-resource audio they essentially never are.&lt;/p&gt;

&lt;p&gt;That feels like enough caution. It wasn't.&lt;/p&gt;
&lt;h2&gt;
  
  
  Audit your eval set by content, not by filename
&lt;/h2&gt;

&lt;p&gt;Before launching anything I checked the obvious thing: is any of my held-out eval material also sitting in training?&lt;/p&gt;

&lt;p&gt;By filename: zero overlap. Not one collision. The two name sets looked like they came from different universes.&lt;/p&gt;

&lt;p&gt;Then I compared the &lt;em&gt;text&lt;/em&gt; instead: for every eval clip, does any training clip contain the same run of six consecutive words? Word 6-grams — cheap to build, cheap to hash, long enough that natural coincidence is rare at this corpus size.&lt;/p&gt;

&lt;p&gt;Four audiobooks were in my material twice. Same recordings, segmented by two different tools at two different times, under completely unrelated names.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;book&lt;/th&gt;
&lt;th&gt;share of its clips with a twin in training&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;book I'd picked for eval&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;96.9%&lt;/strong&gt; (651 / 672)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;second eval book&lt;/td&gt;
&lt;td&gt;58.8% (130 / 221)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;third book&lt;/td&gt;
&lt;td&gt;82.1% (769 / 937)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fourth book&lt;/td&gt;
&lt;td&gt;69.8% (549 / 787)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2tbvadkcp86erm570bvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2tbvadkcp86erm570bvb.png" alt="Four books stored twice. Zero overlap by filename; the collision only showed up in the text." width="800" height="514"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Four books stored twice. Zero overlap by filename; the collision only showed up in the text.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Top row is the book I was about to grade the model on.&lt;/p&gt;

&lt;p&gt;I wasn't panicked. I just understood two things at once: every measurement I'd ever taken on this data was void, and thank God it surfaced before training rather than after.&lt;/p&gt;

&lt;p&gt;The counterfactual is the point. If I hadn't checked, nothing would have gone wrong. No crash, no warning, no weird loss curve. The model trains on recordings it will later be examined on — different cuts, same sentences, same voices — posts a great number, and I publish it. The number means nothing: the exam questions were handed out in advance. That's the nasty property of this bug class. &lt;strong&gt;It has no symptoms.&lt;/strong&gt; Everything works, the result is better than expected — which is exactly what should make you suspicious.&lt;/p&gt;

&lt;p&gt;And it generalises: &lt;strong&gt;in a low-resource language, re-cut copies of the same recordings are the norm, not the exception.&lt;/strong&gt; There is little material, so you keep returning to it with new tooling, and every pass produces fresh filenames wrapping old content. Deduplicate by content. Filenames are not identity.&lt;/p&gt;

&lt;p&gt;After cleaning I re-verified rather than trusting myself: zero eval clips in training, zero 6-gram matches. Measured and written down, not "I'm pretty sure I got them all".&lt;/p&gt;
&lt;h2&gt;
  
  
  Don't judge a fine-tune by its first checkpoint
&lt;/h2&gt;

&lt;p&gt;Now the part everyone thinks is the project, which was the fastest and dullest bit of it.&lt;/p&gt;

&lt;p&gt;I didn't retrain the model. I froze it and trained a small adapter alongside — &lt;strong&gt;2% of parameters&lt;/strong&gt;, 31M trainable against ~1.5B frozen. 15.5 hours of speech survived the cleanup, 3 epochs, 705 steps, &lt;strong&gt;1 h 30 min on one home GPU&lt;/strong&gt;, 10.4 GB peak VRAM, and a finished adapter of &lt;strong&gt;126 MB&lt;/strong&gt;. Result: 20.1% WER, 9.4% CER — a 42% relative cut in word errors.&lt;/p&gt;

&lt;p&gt;I felt nothing at the time; a number moved as designed. The pride arrived later, when I ran the model over material it had no business handling — films, podcasts, noisy field recordings — and the transcripts came back near-perfect. That's when it stopped being a table row and became working ears.&lt;/p&gt;

&lt;p&gt;Two things from the run are more useful than the headline number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checkpoint 100 was worse than the base model.&lt;/strong&gt; I saved every 100 steps and scored all of them. The first checkpoint came out noticeably &lt;em&gt;worse&lt;/em&gt; than what I started from: the adapter has half-learned the new behaviour, it's already interfering with the old one, and it isn't giving anything back yet. If I'd glanced at it and concluded the approach was a dud, I'd have killed a run that ended up cutting error by 42%. A dip at the first checkpoint is what partial adaptation looks like, not what failure looks like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All the gains landed in epoch 1 of 3.&lt;/strong&gt; Past roughly step 200 the numbers stopped moving; epochs two and three contributed nothing measurable. So "1.5 hours" is itself padded — half an hour would have done. Checkpoint often and score often; runs converge long before the schedule says so.&lt;/p&gt;

&lt;p&gt;One detail that reassured me more than the average: both eval books improved, and the &lt;em&gt;smaller, later, different-reader&lt;/em&gt; one improved more. That's the signal you want — the model didn't just learn one narrator's delivery.&lt;/p&gt;
&lt;h2&gt;
  
  
  Decode-time wins are real — decompose them anyway
&lt;/h2&gt;

&lt;p&gt;Then error dropped again with no training at all.&lt;/p&gt;

&lt;p&gt;A trained model has knowledge, but it also has a &lt;strong&gt;decoding policy&lt;/strong&gt;. The default is greedy — take the locally most probable token, never reconsider. Fast, occasionally catastrophic: take one wrong turn and it can't back out, so it goes in circles. That's exactly what the worst eval clips were. Not mishearing — looping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Qıznıñ qıznıñ qıznıñ qıznıñ …
– dedi Akimoviç, – dedi Akimoviç, – dedi Akimoviç, …
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix is beam search: hold several candidate sequences and score whole hypotheses rather than committing token by token. Costs decode time, costs zero training. I swept 24 configurations on a separate selection set, not on the exam (more below), then ran the winner on the test set once. &lt;strong&gt;17.0% WER, 7.0% CER.&lt;/strong&gt; Not one weight changed. Decoding got 3.1× slower.&lt;/p&gt;

&lt;p&gt;Here it would have been easy to write "beam search: −3 WER points" and move on. True, and half the truth. So I broke the win down.&lt;/p&gt;

&lt;p&gt;409 word errors were recovered in total. &lt;strong&gt;160 of them came from 3 clips out of 893.&lt;/strong&gt; 0.34% of the material delivered 39% of the gain. Those are the loopers: on 41 reference words the greedy model emitted 175 words of repeated garbage. The remaining 890 clips improved by a modest, even 10%.&lt;/p&gt;

&lt;p&gt;Both halves are real, and neither alone justifies a 3.1× slowdown. But they mean different things. The broad 10% is "the model got more careful". The three clips are "it stopped occasionally losing its mind". For archive transcription the second matters far more, because a clip containing 500 bytes of one repeated token isn't merely bad — it poisons anything you train on it later. After the change: zero looping clips, 0 of 893.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decompose your aggregate wins.&lt;/strong&gt; If most of your improvement lives in a handful of examples, you didn't improve accuracy; you fixed a failure mode. Those call for different follow-up work, and averaging hides the difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  The obvious anti-loop knob broke real language
&lt;/h2&gt;

&lt;p&gt;There's a more direct tool against repetition: forbid the model from emitting the same n-gram twice. On paper, exactly the right hammer.&lt;/p&gt;

&lt;p&gt;I tested it. It was net harmful: across 255 selection clips it &lt;strong&gt;broke 17 and fixed 1&lt;/strong&gt;, and 12 of the 17 it broke had been essentially perfect. The transcripts explain themselves. The constraint doesn't stop the model repeating — it forces it to repeat &lt;em&gt;incorrectly&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;book        – Qartbaba, qartbaba, – tez-tez çapıp kelgen kiçkene Aziz
unrestricted– Qartbaba! Qartbaba! – tez-tez çapıp kelgen kiçkene Aziz
restricted  – Qartbaba! Qartbabaa! – tez-tez çapıp kelgen kiçkene Aziz
harder      – Qartbaba! Qartbava! – tez-tez çapıp kelgen kiçkene Aziz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A child runs up calling "Qartbaba, qartbaba!" — grandpa, grandpa. The model heard it perfectly. The ban wouldn't let it write down what it heard, so it corrupted the second word to avoid matching the first. Elsewhere &lt;code&gt;bağışla… bağışla…&lt;/code&gt; ("forgive me… forgive me…") came back the second time as the non-word &lt;code&gt;Bağuşla&lt;/code&gt;; in a third case the model routed around the constraint by inventing a suffix, &lt;code&gt;parçalarnıñ parça&lt;/code&gt; instead of &lt;code&gt;parçalar&lt;/code&gt;. Doubled address and doubled pleading are ordinary Crimean Tatar. People talk that way.&lt;/p&gt;

&lt;p&gt;This is my favourite finding of the stage, and it isn't really about decoding. &lt;strong&gt;You cannot fix a language with prohibitions.&lt;/strong&gt; Any rule of the form "this never occurs" eventually collides with how people actually speak, and it breaks precisely that spot while leaving everything else intact — so you won't notice. A decoding default borrowed from an English-language tutorial encodes assumptions about English. Test it against your own language's rhetoric first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three sets, and the test set gets decoded once per decision
&lt;/h2&gt;

&lt;p&gt;I've mentioned a "selection set" twice. Every number above rests on it. There are three sets, not two.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Train&lt;/strong&gt; — the model learns here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dev / selection&lt;/strong&gt; — 255 clips, half an hour, two short whole works pulled out of the training material. This is where I &lt;em&gt;choose&lt;/em&gt;: which checkpoint, which of the 24 decode configs. Dozens of evaluations, as many as I liked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test&lt;/strong&gt; — the two held-out books. Decoded exactly &lt;strong&gt;twice all stage&lt;/strong&gt;: once on the winning checkpoint, once on the winning decode config. The selection rule was written down before I looked at any result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why so strict? Because if you run the test set repeatedly and take the best result each time, you're no longer selecting the best model — you're selecting the luckiest one. The number comes out pretty and never reproduces.&lt;/p&gt;

&lt;p&gt;The dev set got the same cleanliness audit: zero shared clips, zero 6-gram matches. After the duplicate story I don't file that under paranoia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your dev set measures ranking, not absolute quality
&lt;/h2&gt;

&lt;p&gt;The dev set was &lt;strong&gt;much easier&lt;/strong&gt; than the test set. Same model: &lt;strong&gt;17% WER on dev, 34.6% on test.&lt;/strong&gt; Both honestly held out, neither seen in training. But the dev material comes from the same family of recordings as training, while the test books are two entirely foreign readers.&lt;/p&gt;

&lt;p&gt;So dev is good for "config A beats config B" and useless for "the model errs at X%". Report the dev number as your result and you're not lying exactly — you're reporting the easier exam. Keep both in their lanes: dev ranks, test reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tool I couldn't validate gets no number
&lt;/h2&gt;

&lt;p&gt;One consequence of that discipline. Whisper ships a temperature-fallback mechanism against repetition: it detects circular output and retries. Precisely the tool this problem wants, and nearly free at decode time.&lt;/p&gt;

&lt;p&gt;But my dev set contained &lt;strong&gt;zero&lt;/strong&gt; looping clips. Nothing for it to act on — it looked like a config that does nothing at all. By my own selection rule I couldn't pick it, and I refused to sneak it onto the test set afterwards to see whether it would have helped. So I have no number for it, and I'm not inventing one. If you couldn't validate a tool on the set you're allowed to validate on, write down that it's unvalidated and keep it out of the results table.&lt;/p&gt;

&lt;h2&gt;
  
  
  17% in the studio. What about the world?
&lt;/h2&gt;

&lt;p&gt;Everything above was measured on one kind of audio: one person, one mic, quiet room, reading a book. Honest for its own world, and it says little about the world a voice assistant lives in. So I took the same 893 clips and corrupted them 17 ways — noise, music, competing speech, reverb, telephone-band filtering, time-stretching. The reference text is known, so error is measurable in each.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Telephone band and aggressive compression are free.&lt;/strong&gt; Through a telephone-band filter the model does a hair &lt;em&gt;better&lt;/em&gt; than in the studio. Speech rate barely matters either: ±15% tempo costs at most 6%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competing speech is the enemy, by a wide margin.&lt;/strong&gt; Babble costs roughly 2× what steady noise at the same loudness costs, ~4× what music costs. At equal loudness with the target, WER goes from 17% to &lt;strong&gt;69%&lt;/strong&gt; — the model stops working.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverb is second.&lt;/strong&gt; A hallway-sized room multiplies error by 2.5×.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That points somewhere specific: the highest-leverage investment in robustness is not more data. It's &lt;strong&gt;source separation and microphone placement.&lt;/strong&gt; More training hours will not fix a model whose input holds two people at equal volume.&lt;/p&gt;

&lt;p&gt;One last check that made me happy: on an open Crimean Tatar audiobook set the model had never trained on, clean chapters landed at essentially the same number as my own exam. It didn't memorise my readers. It hears the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd actually tell you
&lt;/h2&gt;

&lt;p&gt;Training was 90 minutes. The months went into auditing the eval set by content, splitting by recording, checkpointing and scoring instead of trusting the schedule, decomposing wins instead of quoting averages, refusing to let an English-shaped default constrain our grammar, and keeping a test set clean enough that its number means something.&lt;/p&gt;

&lt;p&gt;Fine-tuning is the part with a progress bar. It is not the part where the work is.&lt;/p&gt;




&lt;p&gt;Second post in a series. Coming up: a synthesised voice reading an entire book — sixteen chapters, nearly two hours of audio — and what had to be verified chapter by chapter. Then the one where I rented somebody else's GPUs and set money on fire, computing almost nothing.&lt;/p&gt;

&lt;p&gt;Audio samples and project page: &lt;a href="https://ai.ana-yurt.dev/en/blog/2026-09-mashina-nauchilas-slyshat/" rel="noopener noreferrer"&gt;https://ai.ana-yurt.dev/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Two ways to help. If you speak Crimean Tatar, the highest-value contribution is fifteen minutes with headphones — listen to a clip, say whether the machine wrote it down correctly, fix a transcript. No programming needed, and ears like that caught things here that no automated check did; write to &lt;a href="mailto:support@ana-yurt.com"&gt;support@ana-yurt.com&lt;/a&gt;. If you'd rather fuel the work directly, there's &lt;a href="https://ko-fi.com/anayurt" rel="noopener noreferrer"&gt;ko-fi.com/anayurt&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>deeplearning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>What I learned building speech tech for a language with zero datasets</title>
      <dc:creator>Servin Osmanov</dc:creator>
      <pubDate>Thu, 10 Sep 2026 00:44:51 +0000</pubDate>
      <link>https://dev.to/servin_osmanov/what-i-learned-building-speech-tech-for-a-language-with-zero-datasets-2gka</link>
      <guid>https://dev.to/servin_osmanov/what-i-learned-building-speech-tech-for-a-language-with-zero-datasets-2gka</guid>
      <description>&lt;p&gt;The word was &lt;code&gt;qara&lt;/code&gt;, "black". I fed it to an off-the-shelf TTS model, hit play, and got back a soft, polite, very Turkish &lt;em&gt;kara&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In Crimean Tatar къ and к are two separate sounds, and къ sits inside words we say every day: &lt;code&gt;yoq&lt;/code&gt;, &lt;code&gt;qız&lt;/code&gt;, &lt;code&gt;vaqıt&lt;/code&gt;, &lt;code&gt;qadar&lt;/code&gt;. Getting it wrong is not an accent. It is the model quietly speaking a neighbouring language and hoping nobody notices.&lt;/p&gt;

&lt;p&gt;I noticed. That one syllable is why I spent the next several months building speech models for Crimean Tatar on a single consumer GPU, in the evenings, with no dataset to start from. What follows is the engineering residue: what I would tell a solo developer about to do the same for their own low-resource language. Most of it cost me a week per lesson.&lt;/p&gt;

&lt;h2&gt;
  
  
  The chicken and the egg were both endangered
&lt;/h2&gt;

&lt;p&gt;The standard way to build a speech dataset is to take audio and run ASR over it to get text. Except we had no usable ASR for Crimean Tatar, and you cannot build good ASR without a corpus. Classic chicken and egg, except the chicken is also endangered.&lt;/p&gt;

&lt;p&gt;I stared at that loop longer than I want to admit before noticing I was holding the problem the wrong way round. Audiobooks come with the text. It is printed. It exists. There is nothing to recognise.&lt;/p&gt;

&lt;p&gt;So I stopped trying to &lt;em&gt;transcribe&lt;/em&gt; and started trying to &lt;em&gt;align&lt;/em&gt;: known text, audio, find where each word lands, cut on those boundaries. Forced alignment instead of recognition. That flip is the reason the project exists at all, because it sidesteps the exact thing the language did not have.&lt;/p&gt;

&lt;p&gt;If you take one thing from this post, take that one. Before training a recogniser, check whether the ground truth is already sitting on a shelf. If it is, you have an alignment problem, and alignment is enormously cheaper.&lt;/p&gt;

&lt;h2&gt;
  
  
  The run that lied to me for three and a half hours
&lt;/h2&gt;

&lt;p&gt;The first big alignment run covered seven and a half hours of audio. It ran, it did not error, and it produced clean, confident, well-formatted output.&lt;/p&gt;

&lt;p&gt;The first two hours were correct. The remaining three and a half hours were garbage. Not obviously-broken garbage either: plausible timestamps, plausible segments, looking exactly like the good ones. Out of seven hours I got a bit under two of usable material, and I only found out because I went listening.&lt;/p&gt;

&lt;p&gt;I have come to think of a crash as a gift. A crash points at the line. A process that returns confident nonsense takes a week off your life, slowly.&lt;/p&gt;

&lt;p&gt;What fixed it was not a code change but a granularity change. Instead of feeding the aligner three enormous blocks, I split the material into forty chapters and located each independently. Same audio, same text, same tooling, and over five hours of clean speech instead of under two.&lt;/p&gt;

&lt;p&gt;That is the rule I kept: if a stage can fail silently, never run it on big units. Small units fail visibly, and they let you bin the bad ones instead of the whole batch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Words do not line up. Letters do.
&lt;/h2&gt;

&lt;p&gt;That chapter-matching step had its own trap waiting. Locating a chapter inside a book sounds like a string search problem, and my first instinct was word-level similarity. It found nothing. I tested it on a pair I &lt;em&gt;knew&lt;/em&gt; matched, checked by hand, and the similarity came back under one percent.&lt;/p&gt;

&lt;p&gt;The reason will bite anyone working outside English. Crimean Tatar is agglutinative, so the "same" word carries different suffixes in the two sources. Add two alphabets in circulation (Cyrillic and Latin), and word tokens simply do not line up.&lt;/p&gt;

&lt;p&gt;Switching the comparison to short character sequences fixed it in one go: 38 of 40 chapters located. The characters survive the suffixes. The words do not. For anything morphologically rich or multi-script, character-level matching is the default and word tokens are an English-shaped assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  The base model had already decided
&lt;/h2&gt;

&lt;p&gt;Back to &lt;code&gt;qara&lt;/code&gt;. My first assumption was the obvious one: the model had never heard the sound. Easy to test, so I checked. In my data the letter q showed up in 88% of recordings, more often than k. The model had been shown the correct pronunciation thousands of times and had cheerfully ignored every one.&lt;/p&gt;

&lt;p&gt;The problem sat underneath the fine-tuning. In the base model, before it ever saw a word of my language, "q" was already wired to /k/ by English, Spanish and French. Fine-tuning was not overwriting that prior, it was decorating it. Which leads somewhere unpleasant: &lt;strong&gt;more data would not have helped&lt;/strong&gt;. Not ten more hours, not a hundred. The fix had to happen at the foundation.&lt;/p&gt;

&lt;p&gt;So I went base-model shopping with a different question. Not "which base speaks a language close to mine" but "which base already produces the sound I keep losing".&lt;/p&gt;

&lt;p&gt;Everybody's first suggestion is Turkish, the big well-resourced relative. But Turkish has no /q/ at all, only one k, which is exactly how you get &lt;em&gt;kara&lt;/em&gt;. I verified that twice, because I did not trust my own ears the first time. Azerbaijani looks promising until you listen: its q leans towards /g/, then softens further into something breathy. The languages that keep the sound, with a dedicated letter of its own, are Kazakh, Uyghur and Bashkir.&lt;/p&gt;

&lt;p&gt;The multilingual base I ended up choosing had roughly 1500 hours of Kazakh, 400 of Uyghur and 250 of Bashkir in its training mix, against 125 hours of Turkish. Exactly upside down from what "pick the closest big language" would tell you.&lt;/p&gt;

&lt;p&gt;It still had no Crimean Tatar in it. I got around that at the writing-system level: our къ, гъ and нъ each map onto a single letter the model already knows (ҡ, ғ, ң), so you hand it Crimean Tatar text and it reads something familiar. One trick, two problems.&lt;/p&gt;

&lt;p&gt;The nice part is that this is verifiable &lt;em&gt;before&lt;/em&gt; you spend a single GPU-hour on training. Out of the box, with no fine-tuning at all, the new base pronounced our къ correctly 88–100% of the time. I was no longer teaching the model a new sound. I had stopped fighting it.&lt;/p&gt;

&lt;p&gt;I took the Kazakh and Bashkir variants all the way to the end, because I wanted the comparison rather than the argument, and they tied to the third decimal place. I shipped Bashkir: at a certain point in training the Kazakh one returned a few empty phrases and let the /q/ slide back towards k. Given equal numbers, I take the one that breaks less often.&lt;/p&gt;

&lt;p&gt;For a language with no data of its own, picking the base is a phonetics decision, not a taxonomy one. And you can smoke-test the prior in an afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three times the data, and the number would not move
&lt;/h2&gt;

&lt;p&gt;My favourite negative result of the project. The corpus kept growing: 5.9 hours, then 11.5, then 15.3. I tracked character error rate by synthesising speech and running it back through a recogniser, averaged over three runs each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;corpus&lt;/th&gt;
&lt;th&gt;CER (mean of 3)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;base, no Crimean Tatar at all&lt;/td&gt;
&lt;td&gt;0.173–0.198&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.9 h&lt;/td&gt;
&lt;td&gt;0.136&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11.5 h&lt;/td&gt;
&lt;td&gt;0.138&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15.3 h&lt;/td&gt;
&lt;td&gt;0.141&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two and a half times the data and the number goes slightly &lt;em&gt;worse&lt;/em&gt;. Meanwhile the run-to-run spread on one unchanged voice was wide enough to swallow that whole difference, so the honest reading is that all three runs are indistinguishable by this metric. And yet in blind listening, not knowing which sample was which, I picked the newer voice every time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Folkqgphiwee0k1v8c9vc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Folkqgphiwee0k1v8c9vc.png" alt="Corpus size against automatic quality metric" width="799" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The corpus grew two and a half times over. The automatic metric flatlined. Blind listening kept preferring the newer voice anyway.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The explanation matters more than the numbers. Intelligibility saturates early, around six hours. Prosody, breathing, the liveliness of a sentence keep improving well past the point where CER stops moving. The metric goes quiet exactly where the remaining quality lives, so anyone reading that table alone would have stopped collecting data, reporting the truth while making the wrong call.&lt;/p&gt;

&lt;p&gt;The cheaper form of the same lesson: one measurement is not a measurement. The same voice gave one number on the first run and a noticeably different one averaged over three. I have deleted several "wins" that turned out to be variance wearing a hat. Measure three times, and never give a single automatic metric the only vote.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug you can only hear if you click one sentence
&lt;/h2&gt;

&lt;p&gt;I was listening to a narrated chapter, clicked on sentence 195 to check something, and heard the wrong sentence. Not slightly wrong, a different sentence. The drift was beautifully linear:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;sentence&lt;/th&gt;
&lt;th&gt;timestamp offset&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;+10.7 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;98&lt;/td&gt;
&lt;td&gt;+21.8 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;147&lt;/td&gt;
&lt;td&gt;+33.0 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;195&lt;/td&gt;
&lt;td&gt;+43.9 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;My first theory was the fashionable one: the model falls apart over long text. Wrong, and worth checking rather than assuming. Speaker similarity to the opening held at 0.96–0.98 throughout, and the tempo never shifted. The audio was fine.&lt;/p&gt;

&lt;p&gt;The actual cause: two parts of my pipeline computed time independently, and one counted the pauses between phrases twice. Forty-three seconds is exactly the sum of those double-counted pauses across the chapter. Correct audio, wrong labels.&lt;/p&gt;

&lt;p&gt;I did not debug this by reading code. I debugged it with a knife: cut the audio at the old timestamps and at the new ones, push both through recognition, compare. New marks came back at CER 0.008, so the text matches. Old marks came back at 0.712, so those are other sentences entirely. On the final line the old timestamp had run past the end of the file, and the recogniser dutifully "heard" its own boilerplate captions in the silence.&lt;/p&gt;

&lt;p&gt;The part that should worry you: played straight through, the file sounds perfect. Every consumer of those timestamps, a word-highlighting reader or a training pipeline, would have inherited garbage from a file that passes any listening test you can run. Whole-file playback validates whole-file playback and nothing else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The exam the model had already seen
&lt;/h2&gt;

&lt;p&gt;The ASR side of the project produced numbers I liked:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;WER&lt;/th&gt;
&lt;th&gt;CER&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;the model I started from&lt;/td&gt;
&lt;td&gt;34.6%&lt;/td&gt;
&lt;td&gt;11.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+ fine-tuning (about 1.5 h on one GPU)&lt;/td&gt;
&lt;td&gt;20.1%&lt;/td&gt;
&lt;td&gt;9.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+ tuning how the model decodes its answer&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;17.0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkm003q1l3ulwzc94f61m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkm003q1l3ulwzc94f61m.png" alt="ASR word and character error rates before and after" width="799" height="491"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Left to right: starting model, after fine-tuning, after decoding changes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The third row involved no training at all, not a single weight touched, only a more careful decoding setup, and it moved WER by three points. The entire adapter I added to that model is 126 MB.&lt;/p&gt;

&lt;p&gt;Now the part that nearly ruined it. The same four audiobooks existed twice in my material. Cut differently, segmented differently, stored under unrelated filenames, zero overlap by name. For one book I had picked as an eval set, 96.9% of the segments had a twin sitting in the training data.&lt;/p&gt;

&lt;p&gt;If I had missed it, I would have been examining the model on questions it had already been handed the answers to. A lovely number, published, believed, with the next six months built on top.&lt;/p&gt;

&lt;p&gt;Filenames are not identity. I check for near-duplicates by content now, always, and I treat a suspiciously good eval score as a bug report. Same reflex later, when a synthesised voice read a whole book: I proved by measurement, not by reasoning, that the book's text never entered training. Zero word-sequence matches against a corpus of nearly one and a half million words. Otherwise it is not reading, it is reciting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs now
&lt;/h2&gt;

&lt;p&gt;A synthesised voice read an entire book, &lt;code&gt;Merdiven&lt;/code&gt; by Şamil Alâdin. Not a demo paragraph. All sixteen chapters, 15,444 words, one hour fifty-eight minutes of audio, word timings verified across 100% of the words, per-chapter CER median 0.022 (worst 0.027, best 0.015).&lt;/p&gt;

&lt;p&gt;The timings got a control that was required to fail: cut 30 words per chapter at the recorded marks and recognise them, 447 of 480 matched; shift the same fragments by 0.4 seconds and 4 of 480 match. That gap is what makes the check worth running.&lt;/p&gt;

&lt;p&gt;And the number I care about most: roughly three hours of machine time per two hours of finished audio, everything included. An audiobook in Crimean Tatar now costs one night of one home computer. Not a studio, not a year of waiting.&lt;/p&gt;

&lt;p&gt;Earlier work is public if you want a starting point: the &lt;a href="https://huggingface.co/datasets/servinosmanov/tts-crh-sevil-fixed" rel="noopener noreferrer"&gt;dataset&lt;/a&gt; and the &lt;a href="https://huggingface.co/servinosmanov/xtts-crh-sevil-v1" rel="noopener noreferrer"&gt;model&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the months actually went
&lt;/h2&gt;

&lt;p&gt;Training was hours. An hour and a half here, a few hours there. It is not the line item anybody thinks it is.&lt;/p&gt;

&lt;p&gt;The months went into collecting and aligning data, repairing the parts that broke without saying anything, proving the evaluation was honest, re-measuring, and listening with headphones, blind, one sentence at a time.&lt;/p&gt;

&lt;p&gt;That last one produced the finding I did not expect. Across the project the bugs split roughly half and half between instruments and a human ear. Instruments caught the drifting timestamps, which no amount of listening would ever have revealed. The ear caught breaths in wrong places, bad annotations, and this one:&lt;/p&gt;

&lt;p&gt;I heard &lt;em&gt;ниже&lt;/em&gt; where the book said &lt;code&gt;нидже&lt;/code&gt;. The cause took a minute to find. My letter-mapping rule, the same trick that gave me ҡ and ғ, was also collapsing дж into ж. The model had been handed the string "ниже" and pronounced it flawlessly. Perfect execution of a wrong input.&lt;/p&gt;

&lt;p&gt;The rule had erased a distinction the language genuinely has: дж in our own words like &lt;code&gt;джан&lt;/code&gt;, &lt;code&gt;оджа&lt;/code&gt;, &lt;code&gt;нидже&lt;/code&gt;, versus ж in loanwords. After that collapse nothing downstream could have said them differently. That chapter held fifty-five such words. I caught exactly one, the case that happened to land on another real word. The other fifty-four sounded "a bit off", and the ear slides right over "a bit off".&lt;/p&gt;

&lt;p&gt;Fixing it barely moved any metric. I fixed it anyway, because it is our language, not a leaderboard.&lt;/p&gt;

&lt;p&gt;Which is the most useful thing I can hand anyone doing this for their own language: your cheapest and strongest tool is one native speaker, fifteen minutes and headphones. It beats the automation, and it means you do not have to be a programmer to contribute. You need to hear your language well.&lt;/p&gt;




&lt;p&gt;First post in a series. Coming up: teaching a recogniser to hear Crimean Tatar; narrating a book chapter by chapter; running blind A/B tests so you stop fooling yourself; and the one where I set money on fire renting somebody else's GPUs and computed almost nothing.&lt;/p&gt;

&lt;p&gt;Voice samples and project page: &lt;a href="https://ai.ana-yurt.dev/blog/2026-09-kak-rodilas-ideya/" rel="noopener noreferrer"&gt;https://ai.ana-yurt.dev/blog/2026-09-kak-rodilas-ideya/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Two ways to help. If you're a Crimean Tatar speaker, the highest-value contribution is fifteen minutes with headphones — blind listening and proofreading beat any tool in my stack; write to &lt;a href="mailto:support@ana-yurt.com"&gt;support@ana-yurt.com&lt;/a&gt;. If you'd rather fuel the work directly, there's &lt;a href="https://ko-fi.com/anayurt" rel="noopener noreferrer"&gt;ko-fi.com/anayurt&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>lm</category>
      <category>tts</category>
      <category>programming</category>
    </item>
    <item>
      <title>My Journey Improving a TTS Model for the Crimean Tatar Language</title>
      <dc:creator>Servin Osmanov</dc:creator>
      <pubDate>Fri, 07 Nov 2025 19:42:08 +0000</pubDate>
      <link>https://dev.to/servin_osmanov/my-journey-improving-a-tts-model-for-the-crimean-tatar-language-53f7</link>
      <guid>https://dev.to/servin_osmanov/my-journey-improving-a-tts-model-for-the-crimean-tatar-language-53f7</guid>
      <description>&lt;p&gt;When you work with machine learning, success often hides behind hours of frustration, countless errors, and broken pipelines. This project — improving the &lt;strong&gt;Crimean Tatar TTS (Text-to-Speech)&lt;/strong&gt; model — was exactly that kind of journey. What started as a small experiment to fine-tune an existing model turned into a full-scale debugging adventure that taught me more about data integrity, audio processing, and patience than any tutorial could.&lt;/p&gt;

&lt;p&gt;In my previous article, &lt;a href="https://dev.to/servin_osmanov/why-language-tech-matters-developing-ai-tools-for-small-languages-583h"&gt;Why Language Tech Matters: Developing AI Tools for Small Languages&lt;/a&gt;, I explored how AI can empower low-resource languages. This piece continues that journey with a hands-on look at improving TTS models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4vpl5k2r345s9eueqho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4vpl5k2r345s9eueqho.png" alt="Sevil tts model improvement" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Starting Point: A Model That Worked — but Only Partially
&lt;/h2&gt;

&lt;p&gt;My goal was simple: improve the voice model “&lt;strong&gt;Sevil&lt;/strong&gt;” for the Crimean Tatar language. I had already worked with similar voices — “&lt;strong&gt;Arslan&lt;/strong&gt;” and “&lt;strong&gt;Abibullah&lt;/strong&gt;” — using Hugging Face datasets like &lt;code&gt;speech-uk/tts-crh-arslan&lt;/code&gt; and &lt;code&gt;speech-uk/tts-crh-abibullah&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first training attempts went well — &lt;strong&gt;loss around 0.283&lt;/strong&gt;, results acceptable. But something didn’t add up. The dataset had &lt;strong&gt;1,566 audio files&lt;/strong&gt;, yet the training logs showed only &lt;strong&gt;415 were being used&lt;/strong&gt; — about &lt;strong&gt;26.5%&lt;/strong&gt; of the total.&lt;br&gt;&lt;br&gt;
That meant &lt;strong&gt;almost three-quarters of my data was silently ignored&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At first, I thought it was a fluke. Then I realized it was a &lt;strong&gt;systemic problem&lt;/strong&gt; in the Hugging Face &lt;code&gt;datasets&lt;/code&gt; API when loading compressed audio from Parquet files.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Diagnosing the Problem
&lt;/h2&gt;

&lt;p&gt;When I loaded the dataset through &lt;code&gt;datasets.load_dataset()&lt;/code&gt;, most files threw errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: "Error while decoding audio"
Error: "Audio file appears to be empty"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That didn’t make sense — the audio bytes were clearly present in the Parquet files.&lt;br&gt;&lt;br&gt;
After checking manually with &lt;code&gt;pandas.read_parquet()&lt;/code&gt;, I confirmed the data was there. The problem wasn’t in the files — it was in how the decoder handled them.&lt;/p&gt;

&lt;p&gt;That’s when I realized: the &lt;strong&gt;datasets API couldn’t decode raw audio bytes correctly&lt;/strong&gt;. The data was fine, but the pipeline was broken.&lt;/p&gt;
&lt;h2&gt;
  
  
  Turning Bytes into Sound
&lt;/h2&gt;

&lt;p&gt;At this point, I tried everything.&lt;br&gt;&lt;br&gt;
I extracted the bytes manually, saved them as &lt;code&gt;.raw&lt;/code&gt; files, and tried to load them with &lt;code&gt;librosa&lt;/code&gt; and &lt;code&gt;soundfile&lt;/code&gt;. Nothing worked.&lt;br&gt;&lt;br&gt;
Without proper &lt;strong&gt;metadata&lt;/strong&gt; (sample rate, channels, encoding), the files were unreadable.&lt;/p&gt;

&lt;p&gt;Eventually, I discovered the solution: &lt;strong&gt;FFmpeg&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By using known dataset parameters —&lt;br&gt;&lt;br&gt;
&lt;code&gt;sample rate: 16000 Hz&lt;/code&gt;, &lt;code&gt;channels: mono&lt;/code&gt;, &lt;code&gt;format: PCM 16-bit little-endian&lt;/code&gt; —&lt;br&gt;&lt;br&gt;
I could convert all &lt;code&gt;.raw&lt;/code&gt; files into clean &lt;code&gt;.wav&lt;/code&gt; audio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-f&lt;/span&gt; s16le &lt;span class="nt"&gt;-ar&lt;/span&gt; 16000 &lt;span class="nt"&gt;-ac&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
       &lt;span class="nt"&gt;-i&lt;/span&gt; sevil_0000.raw &lt;span class="se"&gt;\&lt;/span&gt;
       sevil_0000.wav
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like that — &lt;strong&gt;1,566 files successfully converted&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
No corruption. No decoding errors. 100% validation success.&lt;/p&gt;

&lt;p&gt;It was the moment of breakthrough — the kind that makes you sit back, smile, and realize you’ve just solved a problem that haunted you for two days straight.&lt;/p&gt;
&lt;h2&gt;
  
  
  Training the Model — Again
&lt;/h2&gt;

&lt;p&gt;With clean audio finally ready, I retrained the Sevil model from scratch, this time using &lt;strong&gt;all 1,566 recordings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Training setup (based on my previous configs for “Arslan”):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;num_train_epochs = 500
batch_size = 4
learning_rate = 1e-4
fp16 = True
warmup_steps = 2000
save_steps = 2000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The progress was promising:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loss dropped from &lt;strong&gt;1.14 → 0.80 → 0.50 → 0.27&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The voice quality improved with every epoch
&lt;/li&gt;
&lt;li&gt;And then… it crashed at &lt;strong&gt;78%&lt;/strong&gt; completion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The culprit? A familiar one for SpeechT5 users —&lt;br&gt;&lt;br&gt;
&lt;code&gt;RuntimeError: torch.cat(): expected a non-empty list of Tensors&lt;/code&gt;&lt;br&gt;&lt;br&gt;
It turned out to be a bug in &lt;strong&gt;guided_attention_loss&lt;/strong&gt;, a component that sometimes fails with uneven sequence lengths.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fixing the Crash
&lt;/h2&gt;

&lt;p&gt;Instead of starting over, I resumed training from the last checkpoint (step 16,000) and simply &lt;strong&gt;disabled guided attention&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model.config.use_guided_attention_loss = False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one line saved the project.&lt;br&gt;&lt;br&gt;
Training resumed, completed &lt;strong&gt;98% of the full cycle&lt;/strong&gt;, and stabilized with a final &lt;strong&gt;loss of 0.267&lt;/strong&gt; — a small numerical improvement, but a big qualitative one.&lt;br&gt;&lt;br&gt;
The model became more consistent and robust across new data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Data Used&lt;/th&gt;
&lt;th&gt;Loss&lt;/th&gt;
&lt;th&gt;Success&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sevil v1&lt;/td&gt;
&lt;td&gt;415 files (26.5%)&lt;/td&gt;
&lt;td&gt;0.276&lt;/td&gt;
&lt;td&gt;47% test&lt;/td&gt;
&lt;td&gt;Trained on partial data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sevil v2&lt;/td&gt;
&lt;td&gt;1,566 files (100%)&lt;/td&gt;
&lt;td&gt;0.267&lt;/td&gt;
&lt;td&gt;100% test&lt;/td&gt;
&lt;td&gt;Fully trained, stable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The difference wasn’t just in metrics — it was in &lt;strong&gt;confidence&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Sevil v2 generalized better, produced smoother intonation, and maintained pronunciation consistency even on unseen words.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Never trust good metrics without checking data coverage.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
My “good” baseline was trained on just 26% of the data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;FFmpeg is a lifesaver.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It solved what specialized libraries couldn’t.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validate every single file.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Automation saved hours of manual checking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Guided attention loss is optional.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sometimes stability matters more than theoretical accuracy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Document everything.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
By keeping track of every attempt — successful or not — I could understand the full story, not just the happy ending.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Project Matters
&lt;/h2&gt;

&lt;p&gt;For me, this wasn’t just about fixing one dataset. It was about enabling a &lt;strong&gt;low-resource language&lt;/strong&gt; — Crimean Tatar — to have a better voice in the digital world.&lt;br&gt;&lt;br&gt;
Improving the Sevil model means clearer pronunciation, smoother prosody, and better accessibility for learners and native speakers alike.&lt;/p&gt;

&lt;p&gt;And for anyone working with custom TTS datasets:&lt;br&gt;&lt;br&gt;
Check your files, validate your data, and don’t give up when your model crashes at 78%.&lt;br&gt;&lt;br&gt;
That crash might be the best teacher you’ll ever have.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; &lt;em&gt;Servin Osmanov&lt;/em&gt;&lt;br&gt;&lt;br&gt;
Lead Fullstack Python / ReactJS Engineer&lt;br&gt;&lt;br&gt;
AI researcher and TTS developer for low-resource languages&lt;br&gt;&lt;br&gt;
Project: &lt;code&gt;servinosmanov/tts-crh-sevil-fixed&lt;/code&gt; on Hugging Face&lt;/p&gt;

</description>
      <category>ai</category>
      <category>huggingface</category>
      <category>programming</category>
      <category>nlp</category>
    </item>
    <item>
      <title>My Journey as a Judge at CBIT Hacktoberfest 2025 — Lessons from the Other Side of the Table</title>
      <dc:creator>Servin Osmanov</dc:creator>
      <pubDate>Thu, 30 Oct 2025 18:29:37 +0000</pubDate>
      <link>https://dev.to/servin_osmanov/my-journey-as-a-judge-at-cbit-hacktoberfest-2025-lessons-from-the-other-side-of-the-table-78e</link>
      <guid>https://dev.to/servin_osmanov/my-journey-as-a-judge-at-cbit-hacktoberfest-2025-lessons-from-the-other-side-of-the-table-78e</guid>
      <description>&lt;p&gt;When I first started attending hackathons, I was always the one coding, building, and pitching. This year, for the first time, I got to experience the other side — as a &lt;strong&gt;judge&lt;/strong&gt; at the &lt;a href="https://cbit-hacktoberfest25.devpost.com/?ref_feature=challenge&amp;amp;ref_medium=discover#prizes" rel="noopener noreferrer"&gt;CBIT Hacktoberfest Hackathon 2025&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was an incredible 24-hour online event organized by the &lt;strong&gt;CBIT Open Source Community&lt;/strong&gt;, celebrating open-source culture and collaboration as part of the global &lt;strong&gt;Hacktoberfest&lt;/strong&gt;. The event gathered hundreds of students from universities across the world — developers, designers, and dreamers ready to learn, code, and share.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Event Was About
&lt;/h2&gt;

&lt;p&gt;Hacktoberfest is all about &lt;strong&gt;celebrating open source&lt;/strong&gt;, and this hackathon perfectly captured that spirit. The CBIT edition — now in its 8th year — encouraged participants to collaborate on innovative solutions using modern technologies while contributing to the open-source ecosystem.&lt;/p&gt;

&lt;p&gt;Teams of &lt;strong&gt;3–5 members&lt;/strong&gt; worked virtually through &lt;strong&gt;Discord&lt;/strong&gt;, tackling real-world challenges in just 24 hours. Despite the distance and time zones, the sense of connection and creativity was palpable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Judging Framework
&lt;/h2&gt;

&lt;p&gt;Every project was evaluated based on a clear, balanced set of criteria (total: 50 points):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;Points&lt;/th&gt;
&lt;th&gt;What It Measured&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Innovation &amp;amp; Creativity&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Original ideas and new approaches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collaboration&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Teamwork, communication, and shared contribution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Technical soundness, scalability, and efficiency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Usability and user experience&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Presentation&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Clarity, storytelling, and delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As a judge, I was looking for that spark — projects that combined &lt;strong&gt;solid implementation with a clear purpose&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Saw and Learned
&lt;/h2&gt;

&lt;p&gt;Some projects were technically ambitious, pushing the boundaries of what’s possible in 24 hours. Others were beautifully simple, focusing on accessibility or social impact. A few used &lt;strong&gt;AI and automation&lt;/strong&gt; in creative ways that genuinely surprised me.&lt;/p&gt;

&lt;p&gt;But beyond the technology, what stood out was the &lt;strong&gt;teamwork&lt;/strong&gt;. Many participants were strangers before the event — yet they managed to code, design, and present together like long-time collaborators. That’s the magic of hackathons.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Judging Experience
&lt;/h2&gt;

&lt;p&gt;Our panel included engineers and leaders from &lt;strong&gt;Electronic Arts, JP Morgan Chase, Oracle, Deliveroo, ServiceNow, EY&lt;/strong&gt;, and more. Being part of such a diverse group gave every discussion depth. Each judge viewed “innovation” slightly differently — and that variety made our evaluations richer.&lt;/p&gt;

&lt;p&gt;I appreciated the effort teams put into their presentations. Even short demos told full stories — from the problem statement to the final prototype. That’s where creativity met clarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Innovation isn’t always about technology.&lt;/strong&gt; Sometimes it’s about empathy — understanding who you’re helping and why.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Good presentation matters.&lt;/strong&gt; The best projects told their stories with confidence and focus.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community is everything.&lt;/strong&gt; Open-source hackathons like this show how technology connects us beyond borders.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As a developer, I’ve always believed in continuous learning. Judging this event reaffirmed that growth happens in many forms — whether you’re writing code or evaluating it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Hackathons Matter More Than Ever
&lt;/h2&gt;

&lt;p&gt;In a world where remote collaboration is the new normal, hackathons remain one of the most human ways to innovate. They combine &lt;strong&gt;competition, creativity, and community&lt;/strong&gt; into one shared experience. For students and professionals alike, they’re the perfect place to experiment and grow.&lt;/p&gt;

&lt;p&gt;I’m grateful to have played a small role in this journey — to witness ideas take shape, to learn from participants, and to see firsthand how open source continues to inspire a new generation of builders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; &lt;br&gt;
&lt;em&gt;Servin Osmanov&lt;/em&gt;&lt;br&gt;&lt;br&gt;
Lead Software Engineer @ Anvaya Solutions Inc.&lt;br&gt;&lt;br&gt;
Judge at &lt;a href="https://cbit-hacktoberfest25.devpost.com/?ref_feature=challenge&amp;amp;ref_medium=discover#prizes" rel="noopener noreferrer"&gt;CBIT Hacktoberfest Hackathon 2025&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>Why Language Tech Matters: Developing AI Tools for Small Languages</title>
      <dc:creator>Servin Osmanov</dc:creator>
      <pubDate>Sat, 25 Oct 2025 15:45:27 +0000</pubDate>
      <link>https://dev.to/servin_osmanov/why-language-tech-matters-developing-ai-tools-for-small-languages-583h</link>
      <guid>https://dev.to/servin_osmanov/why-language-tech-matters-developing-ai-tools-for-small-languages-583h</guid>
      <description>&lt;p&gt;In a world where artificial intelligence is transforming how we communicate, the survival of small languages depends not just on cultural passion — but on technology.&lt;br&gt;&lt;br&gt;
While English, Chinese, or Spanish dominate the digital space, thousands of smaller languages remain digitally invisible. Without online presence, data, or digital tools, these languages risk extinction in the 21st century.  &lt;/p&gt;

&lt;p&gt;As a software engineer and cultural advocate, I’ve spent years developing digital tools for the &lt;strong&gt;Crimean Tatar&lt;/strong&gt; language — a Turkic minority language spoken by less than 300,000 people worldwide. Through this work, I’ve learned that the intersection of &lt;strong&gt;AI and linguistics&lt;/strong&gt; isn’t just a research topic; it’s a lifeline for cultural identity.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Challenge: The Technology Gap for Small Languages&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Mainstream AI models—from GPT-based chatbots to translation engines—are trained primarily on high-resource languages. This creates a serious imbalance: while global communication becomes easier for some, others are left behind.&lt;/p&gt;

&lt;p&gt;For small linguistic communities, the lack of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;digital corpora,&lt;/li&gt;
&lt;li&gt;standardized spelling systems,&lt;/li&gt;
&lt;li&gt;and high-quality training datasets
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;makes it nearly impossible to integrate their languages into modern tools like voice assistants, translation services, or educational apps.&lt;/p&gt;

&lt;p&gt;When a language isn’t “machine-readable,” it risks becoming irrelevant in the digital world — even if it’s still spoken at home.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Our Journey: Building Tools for the Crimean Tatar Language&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In 2018, our team launched a series of educational and linguistic tools under the &lt;strong&gt;Qırımtatar Lugatı&lt;/strong&gt; (Crimean Tatar Dictionary) project:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://play.google.com/store/apps/details?id=com.anaurt.lugat" rel="noopener noreferrer"&gt;Android app on Google Play&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apps.apple.com/us/app/q%C4%B1r%C4%B1mtatar-lu%C4%9Fat%C4%B1/id1457493656" rel="noopener noreferrer"&gt;iOS app on the App Store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our mission was to give people an accessible and modern way to learn, use, and preserve the Crimean Tatar language.  &lt;/p&gt;

&lt;p&gt;The apps quickly grew into more than just dictionaries — they became &lt;strong&gt;living platforms&lt;/strong&gt; connecting speakers, learners, and educators. Yet, users wanted more: context-based search, on-the-fly translation, and natural voice pronunciation.&lt;br&gt;&lt;br&gt;
This inspired us to integrate &lt;strong&gt;artificial intelligence&lt;/strong&gt; to make our tools more flexible and intelligent.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Next Step: Bringing AI to Minority Languages&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are now integrating &lt;strong&gt;AI and machine learning&lt;/strong&gt; into the Crimean Tatar dictionary project to expand its capabilities:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;strong&gt;AI-assisted translation:&lt;/strong&gt; dynamic, real-time translation between Crimean Tatar, Turkish, English, and Ukrainian.
&lt;/li&gt;
&lt;li&gt;🔊 &lt;strong&gt;Speech recognition and synthesis:&lt;/strong&gt; allowing users to hear natural pronunciation and practice correct intonation.
&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Adaptive learning:&lt;/strong&gt; using AI to personalize vocabulary lessons based on user behavior and progress.
&lt;/li&gt;
&lt;li&gt;🪶 &lt;strong&gt;Data-driven NLP foundation:&lt;/strong&gt; building scalable open datasets that will support future chatbots, voice assistants, and translation systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To achieve this, we’ve adopted and fine-tuned &lt;strong&gt;open-source speech synthesis models&lt;/strong&gt; such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://huggingface.co/facebook/mms-tts-crh" rel="noopener noreferrer"&gt;facebook/mms-tts-crh&lt;/a&gt;&lt;/strong&gt; — part of Meta’s &lt;em&gt;Massively Multilingual Speech&lt;/em&gt; project, providing a solid baseline for Crimean Tatar TTS.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://huggingface.co/spaces/robinhad/qirimtatar-tts" rel="noopener noreferrer"&gt;robinhad/qirimtatar-tts&lt;/a&gt;&lt;/strong&gt; — a community-driven model that helps us generate high-quality speech for educational and cultural content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By leveraging these models, we’re building an &lt;strong&gt;AI-powered TTS system&lt;/strong&gt; that brings Crimean Tatar audio resources to learners, teachers, and content creators for the first time.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why This Matters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Language is more than communication — it’s collective memory.&lt;br&gt;&lt;br&gt;
When a language disappears, so does a unique worldview and cultural identity.  &lt;/p&gt;

&lt;p&gt;AI gives us a chance to reverse that process. With the right tools, small languages can become visible online, connect their communities, and survive in the digital era.&lt;/p&gt;

&lt;p&gt;Projects like &lt;strong&gt;Qırımtatar Lugatı&lt;/strong&gt; show that you don’t need a giant corporation to make an impact.&lt;br&gt;&lt;br&gt;
A small, passionate team with the right technical vision can give a digital voice — literally — to those who’ve been silent for too long.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How Developers and Researchers Can Help&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you’re a developer, linguist, or AI researcher, here are a few ways to make a difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contribute to &lt;strong&gt;open-source datasets&lt;/strong&gt; for small or low-resource languages.
&lt;/li&gt;
&lt;li&gt;Support &lt;strong&gt;multilingual NLP and TTS&lt;/strong&gt; initiatives on Hugging Face or GitHub.
&lt;/li&gt;
&lt;li&gt;Collaborate with communities and educators who are digitizing endangered languages.
&lt;/li&gt;
&lt;li&gt;Help localize educational and cultural apps into underrepresented languages.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every dataset, every model, and every contribution brings us closer to a more linguistically inclusive AI ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Looking Ahead&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Our roadmap for 2025 includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full integration of &lt;strong&gt;AI-powered translation&lt;/strong&gt; within the Qırımtatar Lugatı apps.
&lt;/li&gt;
&lt;li&gt;Implementation of &lt;strong&gt;voice features&lt;/strong&gt; using our fine-tuned TTS models.
&lt;/li&gt;
&lt;li&gt;Launching an &lt;strong&gt;open API&lt;/strong&gt; for developers who want to build tools for Crimean Tatar or similar minority languages.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technology alone won’t preserve culture — but it can &lt;strong&gt;amplify&lt;/strong&gt; it.&lt;br&gt;&lt;br&gt;
For small languages like Crimean Tatar, &lt;strong&gt;AI isn’t just a tool — it’s hope.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Servin Osmanov&lt;/em&gt; is a Senior Full-Stack Engineer and founder of the &lt;a href="https://qirim.online/" rel="noopener noreferrer"&gt;&lt;strong&gt;Qırım.Online&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://ana-yurt.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Ana-Yurt.Com&lt;/strong&gt;&lt;/a&gt; project — an initiative focused on preserving Crimean Tatar culture and language through modern technology.&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/servin-osmanov/" rel="noopener noreferrer"&gt;linkedin.com/in/servin-osmanov&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/MrSerWin" rel="noopener noreferrer"&gt;github.com/MrSerWin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>learning</category>
      <category>programming</category>
      <category>whisper</category>
    </item>
  </channel>
</rss>
