<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>VerbaIDE blog: on-device dictation and translation</title>
    <link>https://verbaide.com/blog/</link>
    <description>Notes from the team behind VerbaIDE: what we built, what we measured, and what we removed, and why.</description>
    <language>en-us</language>
    <lastBuildDate>Tue, 13 Oct 2026 12:00:00 GMT</lastBuildDate>
    <atom:link href="https://verbaide.com/blog/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Smart Keyboard: how it decides to change a word</title>
      <link>https://verbaide.com/blog/smart-keyboard/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/smart-keyboard/</guid>
      <pubDate>Tue, 13 Oct 2026 12:00:00 GMT</pubDate>
      <description>Smart Keyboard fixes the wrong layout and simple typos on your Mac. How it decides, how we measured it, and what we turned off because it hurt.</description>
      <content:encoded><![CDATA[<p>You type a sentence, look up, and see «ghbdtn» instead of «привет». The layout was still English. You delete the word, switch the layout and type it again. People who write in two or three languages do this many times a day. VerbaIDE can now do it for you. The feature is called Smart Keyboard.</p>
<h2 id="what-it-does">What it does</h2>
<p>When a word ends — with a space, a comma or a full stop — Smart Keyboard looks at it. If it was typed in the wrong layout, the word is replaced and the system layout switches, so the next word comes out right. «ghbdtn» becomes «привет», «руддщ» becomes «hello», and a Ukrainian «тыльки» typed on the Russian layout becomes «тільки». It also fixes simple typos in the right layout: «првиет» becomes «привет», «квказ» becomes «Кавказ». And both at once: «ghdbtn» becomes «привет».</p>
<p>If a fix is wrong, press ⇧ twice. The word and the layout come back, and that word is never fixed again. Press ⇧ twice once more and the fix returns.</p>
<h2 id="the-rule-we-set-first">The rule we set first</h2>
<p>A missed fix costs you one retype. A wrong fix costs more: you have to notice it, and sometimes you notice only after the message is sent. So before writing any code we set a limit: at most one wrong replacement per 10,000 correctly typed words. Every decision below was measured against it.</p>
<h2 id="how-it-decides">How it decides</h2>
<p>Everything happens on your Mac. Smart Keyboard looks at three things.</p>
<p><strong>The macOS spell checker</strong> — the same dictionary that underlines words in red. It answers «is this a word?». We ship no dictionaries of our own.</p>
<p><strong>Tables of three-letter runs.</strong> For each language we counted which runs of three letters occur at the start, in the middle and at the end of words, and how often. «ghb» at the start of an English word almost never happens; «при» at the start of a Russian word is everywhere. We counted on public-domain sentences from the Common Voice project. The app carries only the tables, 22–43 KB per language, not the sentences.</p>
<p><strong>Lists of frequent words</strong> from the same sentences: the 300 most frequent short words of each language, and a longer frequency list for choosing between typo fixes.</p>
<p>Short words needed their own rule. The spell checker accepts almost any single letter and many pairs, like «cd» or «bc», so for one and two letters we trust only the frequent-word lists. A lone Latin letter typed on the English layout is never fixed by itself: in our test that would have turned «E», «C», «J» and «R» into Cyrillic letters 52 to 65 times per 10,000 words. Such a letter is fixed only together with the word next to it.</p>
<p>Russian and Ukrainian are a separate story. Their layouts differ in only a few keys: «ы» and «і», «э» and «є», «ъ» and «ї». The dictionaries decide, but the Russian one in macOS has gaps: it may not know «продавцы» while the Ukrainian one knows «продавці». So a dictionary answer is not enough on its own: the letter tables have to agree too. Words that exist in both languages, like «ты» and «ті», are decided by the words around them, and it takes two such words. With one, a mixed Ukrainian and Russian text got 15 wrong replacements per 10,000 words.</p>
<p>For a typo, the candidates are the spell checker’s suggestions plus the words one slip away from what you typed: one letter wrong, missing or extra, or two letters swapped. Our own variants count only if they are in the frequency list. The most frequent candidate wins, and only if it looks more like the language than what you typed.</p>
<h2 id="how-we-measured">How we measured</h2>
<p>We kept part of the Common Voice sentences aside and built nothing from them: 111,373 correctly typed words in English, Russian and Ukrainian, plus the same words typed in the wrong layout. The test types them key by key and asks the real macOS spell checker.</p>
<ul>
<li><strong>Wrong layout.</strong> Of words five letters and longer, 99.2% were fixed (Ukrainian: 96.4%). Short words are harder: of two-letter words, 65–78%.</li>
<li><strong>Wrong replacements.</strong> 10 of the 111,373 correct words, 0.9 per 10,000. All ten were words the test had misspelled on purpose. Correctly spelled words were never touched.</li>
<li><strong>English inside Russian and Ukrainian.</strong> «Slack», «PR», «API», «GitHub», «to», «is» and 16 more words inserted into Russian and Ukrainian sentences: 18,400 insertions, none replaced.</li>
<li><strong>Typos.</strong> On correct text: 4 wrong replacements in 50,562 English words, 3 in 39,664 Russian words, 1 in 15,760 Ukrainian words. Fixed: about 83% of English typos, 66% of Russian and 40% of Ukrainian.</li>
</ul>
<p>Then we checked the typo rule on text it had never been tuned on: the app’s own interface strings, the phrases of our dictation test set and our own Russian working notes. English and Ukrainian: no wrong replacements. Russian: one in 22,756 words — «нодах» became «годах».</p>
<h2 id="what-we-turned-off-because-it-hurt">What we turned off because it hurt</h2>
<p><strong>The judge for typos.</strong> VerbaIDE has a small local model, our fine-tuned Qwen3-1.7B, which already checks dictionary terms in dictation. We let it look at a typo fix again once the next word was typed. It changed the word for the worse more often than for the better: in Russian it spoiled 67 words and saved 23, in English 58 and 53, in Ukrainian 8 and 2. Before that, when it chose between several typo candidates, it picked a wrong word in 23–29% of questions. Both are off.</p>
<p>The same model stayed on for wrong-layout words where the letter tables are undecided. There it raised the share of fixed long words from 97.7% to 99.2% (Ukrainian from 90.6% to 96.4%), at the cost of four more wrong replacements on 111,373 words, all on words misspelled on purpose. 95 of its 100 answers come within 34 milliseconds.</p>
<p><strong>A lone «э» becoming «є».</strong> On the Russian layout «э» sits on the key that types a quote mark in English. An English sentence that started with a quote on the wrong layout got «Є» instead of the quote 20 times in the test. Off.</p>
<p><strong>The bold typo setting.</strong> It fixed 92% of Russian typos, but changed 8.8 correct Russian words per 10,000, and 71 words of the Russian text we had kept aside for checking. We took the stricter one: 66% fixed, under one wrong replacement per 10,000.</p>
<h2 id="what-stays-on-your-mac">What stays on your Mac</h2>
<p>All of it. Keys are processed on your Mac. Layout correction processes the actual field text before the cursor in memory, back to the sentence start, up to 16,384 UTF-16 units; the snapshot is then forgotten. The last correction is kept for undo. Nothing you type is saved, written to the log or sent anywhere. Smart Keyboard uses Accessibility permission to listen to keys and type corrections, skips password fields and excluded apps, and pauses corrections while VerbaIDE is dictating.</p>
<p>Smart Keyboard is a paid feature, part of the plan and of the 30-day trial. What it fixes, what it leaves alone and what it will not catch is on the <a href="/for/layout/">Smart Keyboard page</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The trial is now a month, not two weeks</title>
      <link>https://verbaide.com/blog/trial-is-a-month/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/trial-is-a-month/</guid>
      <pubDate>Sat, 10 Oct 2026 12:00:00 GMT</pubDate>
      <description>From October 10 the trial after you sign up in the app lasts 30 days instead of 14. What it opens and how to get it.</description>
      <content:encoded><![CDATA[<p>From today, the trial after you sign up in the app lasts 30 days. It used to be 14.</p>
<h2 id="why-we-changed-it">Why we changed it</h2>
<p>In two weeks, many people never get to test translation and meeting recording on real work. That takes several calls, a long document and an ordinary working week, not a few test phrases. A month is enough for that.</p>
<h2 id="what-the-trial-opens">What the trial opens</h2>
<ul>
<li>translation;</li>
<li>style presets;</li>
<li>live subtitles;</li>
<li>translation under the cursor;</li>
<li>meeting recording.</li>
</ul>
<p>Dictation is not part of the trial, because it is already free forever, whether you hold the key or tap it to start the secretary. When the month ends, the paid features lock and dictation stays.</p>
<h2 id="how-to-get-it">How to get it</h2>
<p>Sign up in the first-run setup. The trial starts by itself: you do not have to ask for it, and no card is needed.</p>
<h2 id="if-you-are-already-on-the-trial">If you are already on the trial</h2>
<p>Nothing changes for you: your trial keeps its original length. The 30 days apply to everyone who signs up from today.</p>
<p>For what is free and what a plan opens, see <a href="/docs/account-and-plans/">account and plans</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A smaller judge for your dictionary terms</title>
      <link>https://verbaide.com/blog/term-judge-finetune/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/term-judge-finetune/</guid>
      <pubDate>Wed, 07 Oct 2026 12:00:00 GMT</pubDate>
      <description>We trained a small model to decide when a dictionary term replaces what the recognizer heard. It nearly matched one twice its size, three times faster.</description>
      <content:encoded><![CDATA[<p>Speech recognizers write unusual words the way they sound. Say “Redis” in a Russian sentence and you may get “редис”. VerbaIDE has dictionaries of terms for this: a list of names and how they tend to be misheard. This week we trained a small model to make the final call, and it turned out nearly as good as one more than twice its size.</p>
<h2 id="what-the-judge-does">What the judge does</h2>
<p>When the recognized text contains something that looks like a term from your dictionary, the app has to decide: is that really the term, or an ordinary word? “Redis” and a Russian word that sounds the same are different things, and a blind replacement breaks sentences that were right.</p>
<p>So the app asks a small language model, the judge. It reads the phrase and the candidate term and answers yes or no. We learned earlier that asking about every candidate is safer than trusting a hand-made list of risky ones. The catch is time: the question is asked while you wait for your text.</p>
<h2 id="what-we-measured">What we measured</h2>
<p>Four voices read a set of test phrases that contain terms. For each model we counted two things: phrases the judge fixed (the term went in where it belonged) and phrases it broke (a right word was replaced). The score is fixed minus broken. “+63” means 63 more phrases got better than got worse.</p>
<ul>
<li>The 4-billion-parameter model: 70 fixed, 5 broken, +65.</li>
<li>Our fine-tuned 1.7-billion model: 68 fixed, 5 broken, +63.</li>
<li>The same 1.7-billion model before our training: 77 fixed, 23 broken, +54. It answered “yes” to almost everything.</li>
<li>A fine-tuned 0.6-billion model: +58.</li>
</ul>
<p>All five breakages of the fine-tuned model came from one disputed phrase, a trap we left in on purpose. We kept the trap words out of the training, so this measures words the model has not seen. On a held-out list of 25 unseen terms, the share of correct “no” answers went from 20% to 96%.</p>
<p>On speed, one question takes about 0.07 seconds on the 1.7-billion model against about 0.20 on the 4-billion one. The file is 1.7 GB against 3.3 GB. That is why we like it.</p>
<p>For the training we generated example phrases where the right answer is known from how they were built. The “+63” is a measurement on our own test set, not a promise for your speech.</p>
<h2 id="where-it-stands">Where it stands</h2>
<p>It is not the default. The app can now point the judge at its own model through a hidden setting, separate from the style model. We turned it on on one of our own Macs on October 7. We have not measured it on live dictation yet. Until we do, everyone else keeps the current setup, and we will say so here when that changes.</p>
<p>More about the models is on the page <a href="/docs/languages-and-models/">languages and models</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Report a bad dictation: the one time audio leaves your Mac</title>
      <link>https://verbaide.com/blog/report-a-bad-dictation/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/report-a-bad-dictation/</guid>
      <pubDate>Sat, 03 Oct 2026 12:00:00 GMT</pubDate>
      <description>Control-Option-Command-B lets you send a badly recognized dictation to us. Exactly what you switch on, what is sent, and how long we keep it.</description>
      <content:encoded><![CDATA[<p>Speech recognition and translation in VerbaIDE run on your Mac, and your speech never goes to us. That makes it hard for us to learn when recognition fails. So we added one exception. You can send us a single bad dictation, but only if you choose to, step by step.</p>
<h2 id="what-you-switch-on-and-press">What you switch on and press</h2>
<p>First, you turn on a checkbox in the app: “Help improve speech recognition”. It sits next to the statistics consent, is separate from it, and is off by default. Sending statistics does not turn it on, and it does not send anything by itself.</p>
<p>Second, after that, you press Control-Option-Command-B. A window opens. You see one of your last three dictations, you can play it back, and you see its text and, for a dictation with translation, the translation. You can also write a line about what went wrong. This is optional.</p>
<p>Third, you press “Send”. Nothing leaves the Mac before that.</p>
<h2 id="what-happens-before-and-after">What happens before and after</h2>
<p>Until you press Send, the audio of your last three dictations lives only in memory. It is not written to disk, and it is forgotten when you quit the app.</p>
<p>Without the checkbox, the menu item is hidden, the shortcut does nothing and sending is blocked. If you switch the checkbox off later, the window closes and the temporary audio is erased.</p>
<p>When you press Send, the app sends this: the recording of that one dictation, the recognized text, the translation if there is one, your problem description, your email if you typed one, the versions of the app and macOS, and an anonymous installation number. The number is a fingerprint of the installation key, not your account. We use it only to limit how many reports one installation can send. The report goes to api.verbaide.com. It needs no sign-in and no consent to statistics.</p>
<h2 id="how-long-we-keep-it">How long we keep it</h2>
<p>Our privacy page says it plainly: we keep a report until we delete it by hand. There is no automatic deletion yet. If you want your report deleted sooner, write to <a href="mailto:contact@verbaide.com">contact@verbaide.com</a>.</p>
<h2 id="why-we-ask-for-this">Why we ask for this</h2>
<p>When a recognizer fails, the sound is the only reliable evidence. A text description cannot say whether the word was mumbled, the microphone was quiet or the model made a mistake. With the recording we can reproduce the case, and fix it for everyone who says the same thing. It is the only place where audio leaves your Mac, and it happens only when you press the button.</p>
<p>The full list of network requests is on the page <a href="/docs/what-leaves-your-mac/">what leaves your Mac</a>, and our promise on speech is on the <a href="/privacy-first/">privacy-first page</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Hold or tap: one dictation key, two ways to talk</title>
      <link>https://verbaide.com/blog/hold-or-tap/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/hold-or-tap/</guid>
      <pubDate>Fri, 02 Oct 2026 12:00:00 GMT</pubDate>
      <description>Hold the dictation key for one phrase, tap it for the continuous secretary. One key, nothing extra in the menu, and the secretary is now free.</description>
      <content:encoded><![CDATA[<p>Until now dictation had two separate parts: a key you hold, and the secretary, which listens continuously. The secretary had its own key, its own menu item and its own tab in Settings. We merged them. There is one dictation key, and how you press it decides what happens.</p>
<h2 id="how-it-works">How it works</h2>
<p>Hold the key and talk. When you let go, the whole text lands in the field at once. This is the instant way. It can restyle the text with a style preset, and there is no time limit.</p>
<p>Tap the key briefly and the secretary starts. Talk as long as you like. The text appears in the field piece by piece as you speak, and a second tap stops it. If translation is on, each piece is translated as it goes. The secretary does not restyle the text.</p>
<p>The line between the two is half a second. A press shorter than that is a tap. A press longer than that is a hold. You do not choose a mode beforehand, you just press the key the way the moment calls for.</p>
<h2 id="why-we-did-it">Why we did it</h2>
<p>Two keys for one job made people stop and think which one to use. A phrase for a chat message wants the hold. A long thought, a letter or a stream of notes wants the tap. That is a difference in how you press, not a different feature, so it should not be a different place in the app.</p>
<p>The secretary used to be a limited feature, with time limits of 60 seconds and 15 minutes. Both limits are gone, and the secretary is now free, like the rest of dictation. The separate key, the menu item, the Settings tab, the history view and the battery indicator are removed.</p>
<h2 id="long-holds-are-styled-in-parts">Long holds are styled in parts</h2>
<p>A related change for the instant way. When you hold the key for a long time and a style preset is on, the text used to go to the style model in one piece. A long text is hard for a small local model. Now the app cuts a long dictation into parts and styles each part with its own budget. If styling one part fails, only that part stays as you said it, and the rest is still styled. Spacing between the parts is kept.</p>
<h2 id="what-to-do-after-updating">What to do after updating</h2>
<p>Nothing. Your dictation key stays where it was. Hold it for a phrase, tap it for the secretary. The details are on the <a href="/docs/hotkeys/">hotkeys page</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Who is speaking: speaker labels in meeting recordings</title>
      <link>https://verbaide.com/blog/who-is-speaking/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/who-is-speaking/</guid>
      <pubDate>Tue, 29 Sep 2026 12:00:00 GMT</pubDate>
      <description>Meeting transcripts now number the voices with Nemotron 3 Diarization. How we checked it by ear, what the numbers mean, and what stays off the network.</description>
      <content:encoded><![CDATA[<p>A meeting transcript is hard to read when every line looks the same. We now mark who is speaking: the other people in the call become Speaker 1, Speaker 2 and so on. This is still marked experimental in the app.</p>
<h2 id="why-we-changed-the-method">Why we changed the method</h2>
<p>Our first attempt cut the call audio into pieces and compared voice prints. On a real recording it failed. The microphone and the other participants arrive mixed in one channel, and the voices of different people landed in the same group. Names are not a way out either: a name picked up from the text often goes to the wrong person.</p>
<p>The new method is a model called Nemotron 3 Diarization, made by NVIDIA. “Diarization” means sorting a recording into who spoke when. It handles up to eight voices in one meeting. Its training data does not include Russian or Ukrainian, so we checked it ourselves.</p>
<h2 id="how-we-checked-it">How we checked it</h2>
<p>We took one real meeting recording, about 72 minutes with four people. We cut 60 short pieces of about two and a half seconds from random places and listened to each one. In 51 of them we could say with confidence who was speaking, and we kept those 51.</p>
<p>For each piece we looked at which number the program gave it. The new model put all 51 with the right person: 51 of 51, and it used exactly four numbers for four people. The previous approach got 27 of 51, about 53%, and spread the voices over seven numbers, each a mix of people.</p>
<p>Read this with care. It is one meeting, a short list of pieces, checked by one person, in the spoken languages of that call. On whole transcript lines, which are longer than our pieces and sometimes hold two speakers, the new model agreed with our ear on 47 of 51. We did not test other recordings yet.</p>
<h2 id="what-stays-on-your-mac">What stays on your Mac</h2>
<p>The model is a download of about 100 MB from huggingface.co. It downloads only when you press the button in the Downloads tab. The meeting itself never touches the network: the labelling runs on your Mac after the recording.</p>
<p>The app does not remember voices. The numbers exist only inside one meeting, and nobody is identified by them. Speaker 2 in today’s call has no link to Speaker 2 in tomorrow’s. There is no voice profile to store, so there is nothing to leak.</p>
<p>More on what goes out and when is on the page <a href="/docs/what-leaves-your-mac/">what leaves your Mac</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Dictation got worse? Check the microphone first</title>
      <link>https://verbaide.com/blog/quiet-microphone/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/quiet-microphone/</guid>
      <pubDate>Fri, 25 Sep 2026 12:00:00 GMT</pubDate>
      <description>A Bluetooth headset left the microphone at 27% volume and dictation started mishearing words. Now the panel warns you, and here is what to check.</description>
      <content:encoded><![CDATA[<p>This week one of us noticed that dictation was making many more mistakes and the level bar on the panel looked lazy. We went through our recent changes looking for the cause. The cause was not in the code at all.</p>
<h2 id="what-we-found">What we found</h2>
<p>The Mac’s default input had stayed on a Bluetooth headset, with the input volume at 27%. We measured the loudness of the recorded phrases. Speech came in at about minus 48 decibels. On a normal microphone the same measure sits between minus 20 and minus 35. That is a very quiet recording, and the recognizer has little to work with.</p>
<p>It took a minute to see this in the recordings. Going through the changes would have taken an hour.</p>
<p>A second thing showed up the same day. After pressing the dictation key, the panel appeared, then there was silence, and only then the start sound. Our log said the app began recording 0.1 seconds after the key press, so the app was not slow. The headset was. When a Bluetooth headset opens its microphone, it switches from the music mode to the headset mode, and that takes a moment. The headset mode also has lower sound quality than music playback.</p>
<h2 id="what-the-app-does-now">What the app does now</h2>
<p>Each dictation now measures how loud the first second and a half of your speech is. If it is too quiet, the panel says so for six seconds: which microphone is listening and what its input volume is. Recording goes on, we do not stop you.</p>
<p>We chose the threshold on about fifteen hundred of our own recorded pieces. The warning catches about three quarters of the quiet hour we had, and fires by mistake on under one percent of normal speech. It is a rule of thumb, not a guarantee.</p>
<h2 id="what-you-can-check-yourself">What you can check yourself</h2>
<p>If dictation suddenly gets worse, look at the microphone before anything else.</p>
<ul>
<li>Open System Settings, then Sound, then Input. Speak and watch the level meter. If it barely moves, raise the input volume.</li>
<li>Look at which device is selected. After you connect a headset, macOS may switch the input to it without asking.</li>
<li>If you use a Bluetooth headset, expect a short pause when the microphone opens and a lower sound quality while it is on. Dictating with the Mac’s built-in microphone avoids both.</li>
</ul>
<p>More hints are on the <a href="/docs/troubleshooting/">troubleshooting page</a>.</p>
<p>Today: the app also lets you pick a separate microphone for dictation in Settings.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A new recognition model never installs without asking</title>
      <link>https://verbaide.com/blog/model-updates-ask-first/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/model-updates-ask-first/</guid>
      <pubDate>Thu, 24 Sep 2026 12:00:00 GMT</pubDate>
      <description>Until now the app downloaded new recognition models silently. From today it asks first: Update or Not now. Here is exactly when and how often.</description>
      <content:encoded><![CDATA[<p>Until now, when we published a better recognition model, the app downloaded it on its own: about 600 MB, with no warning. We promised a confirmation window when we built that. From today it exists.</p>
<h2 id="what-the-app-does-now">What the app does now</h2>
<p>When a new model is available, the app shows a window with two buttons: Update and Not now. The window says how big the download is and that the app keeps working on the current model until you update. You do not need to answer quickly, and nothing stops working while you think.</p>
<p>We made some choices on purpose:</p>
<ul>
<li>The window never appears while you are working. It waits if you are dictating, running the secretary or showing live subtitles.</li>
<li>It comes up about five seconds after launch, or when you open the Recognition section in Settings, under Components.</li>
<li>It appears at most once per launch.</li>
<li>After you press Not now, the app waits a week before asking again.</li>
<li>After the second Not now, it never asks again about that version. If we publish a newer one, the count starts from zero.</li>
</ul>
<p>The buttons have no keyboard shortcuts. During testing, a stray Enter pressed in another window a moment earlier agreed to a 600 MB download by accident. Now you have to click.</p>
<h2 id="what-you-can-always-do-yourself">What you can always do yourself</h2>
<p>The “Update model” button stays in Settings, in Components under Recognition. If you pressed Not now twice and changed your mind, the button is still there. If you press Update and quit the app halfway, the download continues at the next launch without asking again.</p>
<h2 id="the-one-exception">The one exception</h2>
<p>The very first model installs without asking. Without a recognition model there is nothing to dictate with, even in the free mode, so asking would only get in the way. This applies only when no model is installed at all.</p>
<h2 id="does-it-send-anything-new">Does it send anything new?</h2>
<p>No. The question uses the same pointer to the current model that the app already read, at most once a day. The app does not send anything about you. Your answers are stored in the app’s settings on your Mac, so clearing the model cache does not bring the question back.</p>
<p>For the full list of what the app sends and when, see <a href="/docs/what-leaves-your-mac/">what leaves your Mac</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>We fine-tuned the recognizer on our own recordings</title>
      <link>https://verbaide.com/blog/finetuning-parakeet/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/finetuning-parakeet/</guid>
      <pubDate>Sun, 20 Sep 2026 12:00:00 GMT</pubDate>
      <description>What we changed in Parakeet, which recipe won, which ideas did not help, and why we measure only on voices the model has never heard.</description>
      <content:encoded><![CDATA[<p>The recognizer in the app is Parakeet from NVIDIA. It is good out of the box, but it makes mistakes on exactly the things we dictate: product names, English words inside Russian speech, numbers. So we trained it a bit more on recordings we made ourselves. This is what we learned.</p>
<h2 id="what-we-did">What we did</h2>
<p>Fine-tuning means taking the finished model and continuing its training on new material. We did it on a Mac, with no rented graphics cards. The model has about 627 million parameters, and one pass over roughly 80 minutes of audio takes about 12 minutes.</p>
<p>The recordings are ours: a few people read hundreds of phrases aloud, including phrases built to trip the model. Examples are “сафари-парк”, which the model likes to write as “Safari Park”, and sentences full of numbers.</p>
<h2 id="which-recipe-won">Which recipe won</h2>
<p>We compared variants on two people the model had never heard, 100 new phrases each. Mistakes per hundred words, lower is better:</p>
<table>
<thead>
<tr>
<th>Variant</th>
<th>Mistakes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Parakeet as NVIDIA ships it</td>
<td>40.1</td>
</tr>
<tr>
<td>Our previous version</td>
<td>22.4</td>
</tr>
<tr>
<td>Mixed with the base model at 0.4</td>
<td>25.0</td>
</tr>
<tr>
<td>Mixed with the base model at 0.6</td>
<td>22.8</td>
</tr>
<tr>
<td>No mixing</td>
<td>19.5</td>
</tr>
<tr>
<td>Distorted audio, mixed at 0.6</td>
<td>21.7</td>
</tr>
<tr>
<td>Distorted audio, no mixing</td>
<td>18.2</td>
</tr>
</tbody>
</table>
<p>The last row is the winner: 4.2 points better than the previous version.</p>
<p>Two ideas deserve a plain explanation. “Distorted audio” means that while training, we add room echo and other damage to the recordings, so the model learns to cope with real rooms. “Mixing” means averaging the tuned model with the original, to keep it from forgetting what it knew. We used mixing at 0.6 for a while, and it turned out to hurt. It had been chosen on one voice and a first set of phrases that had few tricky cases. Once we added a second set with twice as many traps and numbers, the mixing only took away the gain.</p>
<h2 id="what-did-not-help">What did not help</h2>
<p>More data of the same kind. Three versions trained on more and more of it scored the same, within noise. New phrases from the same people did not help either, nor did stronger distortions, which were worse than mild ones. What helps is new voices and the right recipe.</p>
<h2 id="how-we-measure">How we measure</h2>
<p>Only on voices the model never heard, and on phrases it never saw. If a voice was in the training, the number looks about a third better than it will be for a real person. So we train a separate model without each test voice and measure on that.</p>
<p>The tuned model is served from cdn.verbaide.com, and the app picks it up from there. Today: since 24 September the app asks before installing a new version. See <a href="/docs/languages-and-models/">languages and models</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Style prompts: examples beat rules</title>
      <link>https://verbaide.com/blog/style-prompts-examples-beat-rules/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/style-prompts-examples-beat-rules/</guid>
      <pubDate>Thu, 17 Sep 2026 12:00:00 GMT</pubDate>
      <description>How we tune the instructions behind style presets. Adding &apos;don&apos;t do X&apos; made results worse. Showing an input and the right output made them better.</description>
      <content:encoded><![CDATA[<p>A style preset rewrites your dictated text in a chosen tone, for example more formal. A language model does the rewriting, and it follows a written instruction. Tuning that instruction taught us one thing we did not expect: telling the model what not to do makes it worse.</p>
<h2 id="what-goes-wrong">What goes wrong</h2>
<p>The model sometimes does something annoying. It opens with “Sure, here’s a casual rewrite:”. It copies your text word for word. It starts a reply with “Hey”. The natural fix is to add a line to the instruction: do not open with an introduction, do not say “Hey”.</p>
<p>We tried that, and measured it four times on three presets, on real dictation. Every time the added prohibitions made the result worse:</p>
<ul>
<li>A rule against the “Sure, here’s…” opening pushed the score below where we started.</li>
<li>Five attempts in a row to forbid the greeting “Hey” all failed.</li>
<li>A rule with no example dropped the number of clean cases from 19 to 7.</li>
</ul>
<p>Our guess is that the model clings to the exact words it was told to avoid, instead of avoiding them.</p>
<h2 id="what-works-instead">What works instead</h2>
<p>A ready-made pair: an input phrase, and the output we want. Two such examples gave twelve more fixed phrases and only one that got worse.</p>
<p>Not every example helps. Examples we invented from our heads gave a small gain. The gain was large when we took the specific phrases where the model failed on the previous run and wrote the right answer for each one. So the loop is: run the test, pick the phrases that failed, turn them into examples, run again.</p>
<p>One more thing to know. The two worst habits, the introduction and the word-for-word copy, show up only on long texts with several thoughts in them. On short one-sentence phrases they hardly appear at all. A test made of short phrases would tell you everything is fine.</p>
<h2 id="how-we-score-it">How we score it</h2>
<p>We keep a fixed set of phrases, split in two halves. We tune on one half. The other half stays closed until the end, as an exam, so that we do not fit the prompt to the phrases we look at.</p>
<p>Each output goes through simple checks that need no model: did the numbers survive, did a question stay a question, did foreign characters appear. Then a second language model acts as a judge and answers five fixed questions about each result. Changing the judge changes all the numbers, so a candidate and its baseline are always scored by the same one.</p>
<p>With this method we shortened the instruction for the business tone from 1,699 to 1,490 tokens, and the judge’s score went from 264 to 271 out of 282. A shorter prompt, scored higher, with no new prohibitions.</p>
]]></content:encoded>
    </item>
    <item>
      <title>We tried cleaning the audio first. It did not help</title>
      <link>https://verbaide.com/blog/audio-cleanup-does-not-help/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/audio-cleanup-does-not-help/</guid>
      <pubDate>Tue, 15 Sep 2026 12:00:00 GMT</pubDate>
      <description>We tested volume normalization, noise suppression and filters before recognition. Two made results worse, the rest changed nothing. Here is why.</description>
      <content:encoded><![CDATA[<p>It sounds obvious: remove the noise, even out the volume, and the recognizer will hear better. We tested that on our own recordings. The result was the opposite of what we expected.</p>
<h2 id="what-we-tried">What we tried</h2>
<p>We took recordings from four voices, 1,434 phrases in total, and ran each phrase through thirteen variants of processing before recognition. Then we compared the number of mistakes with the untouched recording.</p>
<ul>
<li>Volume normalization, which brings every recording to the same level. It made things worse: about two points more mistakes per hundred words. One English phrase after another came out written in Cyrillic letters.</li>
<li>Noise suppression with RNNoise. On a voice that was already clean, it made things worse.</li>
<li>Noise suppression with GTCRN. It only shuffled the mistakes around: some went away, others appeared, and Russian got slightly worse.</li>
<li>A high-pass filter at 90 Hz, which cuts low rumble. No change at all.</li>
</ul>
<h2 id="why-it-does-not-work">Why it does not work</h2>
<p>Cleaning the sound does not simply give the recognizer a better recording. It changes the sound, and the recognizer reacts to that change in ways we did not expect.</p>
<p>The volume result surprised us most. The recognizer decides which language it is hearing, and the loudness of the sound pushes that decision. Louder audio pulls it towards Russian, so an English phrase starts to appear in Cyrillic. Quieter audio lets it go back to the language of the phrase. A small push at the input flipped the alphabet in about 150 of 1,434 phrases.</p>
<p>We also looked for one ideal volume level and did not find it. Boosting the sound hurt, and each voice had its own best level, more than 15 dB apart from the others.</p>
<h2 id="what-did-help-a-little">What did help a little</h2>
<p>Only one thing gave a steady gain: making the sound three decibels quieter. That removed about half a point of mistakes per hundred words, and no voice got worse. Much quieter audio (6 dB and below) brought a new problem: Russian began to slide into Ukrainian spelling.</p>
<p>The gain is small, so we shipped it only as an experiment. In the dictation settings there is a switch, “Improve recognition (experimental)”, and it is off by default. It does not touch live subtitles.</p>
<p>So we do not put a noise filter in front of the recognizer. If we want better results on Russian and Ukrainian, we will look at how the model chooses the language, not at the sound.</p>
]]></content:encoded>
    </item>
    <item>
      <title>We measured cloud recognizers and stayed local</title>
      <link>https://verbaide.com/blog/cloud-recognizers-measured/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/cloud-recognizers-measured/</guid>
      <pubDate>Tue, 15 Sep 2026 12:00:00 GMT</pubDate>
      <description>OpenAI&apos;s recognizer made 3 to 4 points fewer word errors than ours on read-aloud phrases. We still decided against a cloud option. Here is why.</description>
      <content:encoded><![CDATA[<p>Two big cloud services now offer speech recognition that lists Russian and Ukrainian: OpenAI’s GPT-Transcribe and Google’s Gemini 3.5 Transcribe. We wanted to know how much better they are than the model that runs on your Mac. So we measured.</p>
<h2 id="the-test">The test</h2>
<p>We used our own set of phrases, read aloud by four people: 380 phrases per voice, 294 of them for Ukrainian. The services got the audio files with no hints and no term lists, and we compared the result with Parakeet, our on-device model, under the same conditions. We counted the share of words that came out wrong, ignoring punctuation. This test is the one case where recordings were sent to those services. The app itself does not do this.</p>
<p>Share of wrong words, all voices together:</p>
<ul>
<li>Russian: Parakeet 13.5%, Gemini 10.0%, GPT-Transcribe 9.8%</li>
<li>Ukrainian: Parakeet 18.0%, Gemini 20.5%, GPT-Transcribe 14.6%</li>
<li>English: Parakeet 13.7%, Gemini 13.1%, GPT-Transcribe 10.6%</li>
</ul>
<h2 id="what-we-saw">What we saw</h2>
<p>GPT-Transcribe was 3 to 4 points better in every language, and the gap was clear, not a fluke of the sample. Gemini was close to Parakeet in Russian and English. In Ukrainian, with no language hint, it was worse than Parakeet: it finished short phrases in Russian. It also writes numbers as digits.</p>
<p>One thing did not improve. On phrases with English terms inside Russian speech, the cloud services still got 17 to 26% of words wrong against Parakeet’s 32%. “Антропик”, “докер” and “мигрейт” came out in Cyrillic from all of them. So a term dictionary would still be needed on top of any cloud recognizer.</p>
<h2 id="why-we-said-no">Why we said no</h2>
<p>A cloud tier would have cost us real money for each minute of speech, a server to hand out access tokens, two outside integrations to keep working. The larger cost is the promise itself. Today speech never leaves your Mac, and that sentence is short and true. Three or four points of accuracy are not worth giving it up.</p>
<p>There is a caution about the numbers, too. Our phrases were read from a sheet, not spoken freely. We have been burned by this before: an earlier model looked 1 to 2 points better on read-aloud phrases and then did worse on live dictation, with “uh” in the text and sentences cut in half. We removed it. A gain on a test sheet does not always carry over to real speech.</p>
<h2 id="what-we-do-instead">What we do instead</h2>
<p>We try to win those 3 to 4 points on the device: other local models, measured right away on real dictation recordings, processing the audio before recognition, and further training Parakeet on our own recordings. We will report what works. If you want to see exactly what leaves your Mac today, it is listed on <a href="/docs/what-leaves-your-mac/">what leaves your Mac</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Why we removed a recognizer that scored better</title>
      <link>https://verbaide.com/blog/why-we-removed-gigaam/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/why-we-removed-gigaam/</guid>
      <pubDate>Tue, 15 Sep 2026 12:00:00 GMT</pubDate>
      <description>A Russian recognizer looked better on test phrases, but on live speech it wrote filler sounds and cut sentences. We removed it and learned a lesson.</description>
      <content:encoded><![CDATA[<p>For a while the app had a second Russian recognizer, GigaAM. It re-checked every Russian piece of dictation after the main recognizer, Parakeet. On paper it was better. In real use it was worse, so we removed it completely.</p>
<h2 id="what-the-numbers-said">What the numbers said</h2>
<p>We keep a fixed set of test phrases that people read aloud, and we count the mistakes the recognizer makes on them. On that set GigaAM gave one to two points fewer mistakes per hundred words than Parakeet alone. That is a clear win, and it is why we added it.</p>
<h2 id="what-live-speech-showed">What live speech showed</h2>
<p>A test set of read phrases is tidy. People read a sentence from a sheet, speak evenly and do not stumble. Real dictation is not like that. You think while you talk, you pause, you restart.</p>
<p>We looked at the text GigaAM produced from our own everyday dictation, 557 re-checked pieces in a single day. It was bad in four ways:</p>
<ul>
<li>it wrote “э-э” and “и-и-и” into the text, the hesitation sounds that nobody wants on the page;</li>
<li>it cut sentences with a full stop and a capital letter in the middle of a phrase;</li>
<li>it dropped the last word where one piece of audio met the next;</li>
<li>in four pieces out of ten it changed only the punctuation, and made it worse.</li>
</ul>
<p>None of this showed on the test set, because the test set has no hesitations and no half-finished sentences.</p>
<h2 id="what-we-decided">What we decided</h2>
<p>We could have tried to patch the check so that the test set caught these problems. We chose not to. The person who dictates every day saw the problem in the text, and that is the test that counts. We removed GigaAM from the app, from the settings and from the list of components. We also took the model files off our download server. The app deletes any leftover copy from the Mac at launch.</p>
<p>The lesson is simple. A number from read phrases does not carry over to spontaneous speech. If a new candidate for Russian appears, we will test it on real dictation first and on read phrases second. Parakeet remains our recognizer for Russian.</p>
<p>If you want to know what we use today and how the models are installed, see <a href="/docs/languages-and-models/">languages and models</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Term dictionaries, and the hint we hid</title>
      <link>https://verbaide.com/blog/term-dictionary-hint-hidden/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/term-dictionary-hint-hidden/</guid>
      <pubDate>Sat, 05 Sep 2026 12:00:00 GMT</pubDate>
      <description>We tested three ways to get English terms right in Russian speech. The obvious one broke three times more phrases than it fixed, so we hid it.</description>
      <content:encoded><![CDATA[<p>When you say “pull request” in a Russian sentence, the recognizer writes “пул реквест”. It writes “Антропик” for Anthropic and “Гитхаб экшн” for GitHub Actions. We spent a stretch of work on fixing that, and the result is not the one we expected.</p>
<h2 id="three-ways-to-fix-terms">Three ways to fix terms</h2>
<p>The recognizer works on sound, so the first idea was to tell it which terms to listen for. We keep a small second model, 98 MB, that listens for the terms in the audio and rewrites the text where it hears one. We call this the hint. The second idea is a plain replacement list applied to the finished text, with no model. The third is a judge: a small language model that reads the sentence and decides whether a term really belongs in it.</p>
<p>We tested all three on four voices and 1,434 phrases, about 57 settings in total. For each way we counted phrases it fixed and phrases it broke.</p>
<ul>
<li>The hint: fixed 86, broke 253. It also took 2.26 seconds per phrase against 0.33 seconds without it.</li>
<li>The replacement list alone: fixed 69, broke 16, instantly.</li>
<li>The judge: fixed 79, broke 10. It costs almost no time, because the model only wakes up when a term candidate actually appears in the text.</li>
</ul>
<p>The hint broke three times more than it fixed. Its typical failure is a similar-sounding word: “посмотрел” turning into “Postgres”. We tried trimming the term list to remove risky words and got the same three-to-one ratio. So we turned the hint off and hid its switch in settings. The code stays, with a comment saying why it is off.</p>
<h2 id="what-the-judge-does-now">What the judge does now</h2>
<p>The judge used to ask the model only about variants we had marked as risky. We tested asking about every candidate instead. The net gain was the same, but it broke 6 phrases instead of 10, and it removes a hand-written list that could drift out of date. Now the judge asks about every candidate. Size matters here: a 1.7-billion-parameter model broke 24 phrases against 10 for a 4-billion one, with the same shift in word errors. Counting only errors per word would not have shown that.</p>
<h2 id="term-lists-for-everyone">Term lists for everyone</h2>
<p>The built-in lists for programmers, designers and managers are open to everyone: you can pick them, edit them and make your own. We found a public list of 165 developer terms under the MIT licence, and nothing at all for designers or managers, so those lists we wrote ourselves. We also found no ready-made data on how a Russian speaker pronounces English terms, so that half is our own work too.</p>
<h2 id="what-not-to-trust-in-these-numbers">What not to trust in these numbers</h2>
<p>Our test set has few terms: the 259 replacements touch only 16 to 28 phrases out of 380. The seconds measure processing a file, not the delay you feel in live dictation. One voice was an outlier, with a 28% word error rate against 7.5 to 12% for the others. We have not yet measured live-dictation delay with the judge asking about everything. Read the numbers as direction, not as a promise.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Why we built our own translator</title>
      <link>https://verbaide.com/blog/our-own-translation-engine/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/our-own-translation-engine/</guid>
      <pubDate>Thu, 13 Aug 2026 12:00:00 GMT</pubDate>
      <description>Apple&apos;s translation service crashed on Ukrainian in macOS 26, so we moved translation to our own models that run on your Mac.</description>
      <content:encoded><![CDATA[<p>On macOS 26, translating anything to or from Ukrainian through Apple’s built-in translation crashed the system translation service. This week we stopped depending on it: the app now translates with its own models, on your Mac.</p>
<h2 id="what-broke">What broke</h2>
<p>We traced it on August 12. On macOS 26 (we checked 26.5.2) any translation with Ukrainian on one side makes the system service, translationd, abort. macOS then refuses to restart it for up to 20 minutes. During that time no language pair translates, in any app on the machine, Russian and English included. You can trigger it without our app at all: select text, right-click, choose Translate.</p>
<p>The same translation works on macOS Sequoia 15, so it is a regression in macOS 26, not one unlucky Mac. It also reproduced on another person’s Mac. We checked the usual suspects: the Ukrainian model files are intact, and clearing caches, rebooting and switching the translation strategy changed nothing. We sent a report to Apple, but Ukrainian is central to what this app does, so we could not wait.</p>
<p>The worst part is the side effect. Ukrainian already did not work, but one Ukrainian attempt also switched off Russian and English for twenty minutes.</p>
<h2 id="what-we-did-instead">What we did instead</h2>
<p>We added our own translator. It uses open translation models, run by an engine that sits inside the app. The first version covers English, Russian and Ukrainian, and the storage is ready for ten languages.</p>
<p>Dictionaries are downloaded per direction, only for the languages you pick, from cdn.verbaide.com. One direction ships inside the app, so translation works from the first launch: Russian and Ukrainian to English. Every other direction, including English back to Russian and Ukrainian, downloads on request.</p>
<p>Some pairs have no direct model. Ukrainian to Russian is one of them. For those we go through English, and only when no direct route exists, because every extra hop can damage the meaning.</p>
<h2 id="what-we-measured">What we measured</h2>
<p>We tried a smaller, lighter model class first. Out of 20 test translations it spoiled 8, and six of those dropped whole sentences. From “Привет, как дела? Сегодня хорошая погода, и я хочу пойти на прогулку” only “як справи? і я хочу піти на прогулянку” was left. That is lost text, not a trade between speed and quality, so we rejected it. The larger class dropped no sentences.</p>
<p>On this Mac our translator took 153 ms per phrase against 176 ms for Apple’s. That is one machine, not a benchmark of everything, but it means the switch costs nothing in speed.</p>
<p>Apple’s translator stays in the app as a fallback for the languages where it works. Ukrainian never goes through it. Details on languages and downloads are in <a href="/docs/languages-and-models/">languages and models</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The app gets a name: VerbaIDE</title>
      <link>https://verbaide.com/blog/new-name-verbaide/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/new-name-verbaide/</guid>
      <pubDate>Sun, 09 Aug 2026 12:00:00 GMT</pubDate>
      <description>Why we call the app VerbaIDE, what the name says to different readers, and why the logo is a willow branch and not a tree.</description>
      <content:encoded><![CDATA[<p>Until this week our app had only a working name, the kind you put on a folder and hope to replace. On August 7 we bought the domain verbaide.com, and on August 9 we renamed the whole app to match: the menu, the About tab, the permission prompts, the app bundle and the files we ship.</p>
<h2 id="why-verba-and-ide">Why “Verba” and “IDE”</h2>
<p>“Verba” reads as “verbal” or “words” to almost anyone, so an international user sees an ordinary tech name. “IDE” is borrowed from developer tools. The people we build for already live in tools of that kind: developers, founders, people in support and operations who type all day. We want the app to feel like a tool for text, not a toy.</p>
<p>Our tagline is “The IDE for human language.” You write code in an IDE. You write letters, tickets and messages in human language, and you can do it faster by speaking.</p>
<p>“IDE” has a second reading, too: Intelligent Dictation &amp; Expression. We keep that phrase for places where the abbreviation has to be spelled out.</p>
<h2 id="a-second-meaning-for-ukrainian-readers">A second meaning for Ukrainian readers</h2>
<p>In Ukrainian, “верба” is a willow, and the willow is a national symbol. We did not pick the name for that reason alone, but once we noticed it, we kept it on purpose. A reader abroad sees a neat technical name. A Ukrainian reader sees one more layer in it. The app is built by people from Ukraine, and many of the people who will use it speak Russian or Ukrainian while working in English.</p>
<h2 id="why-the-logo-is-a-branch">Why the logo is a branch</h2>
<p>We looked at a literal willow tree first and dropped it. A tree reads as an eco brand or a cosmetics brand, and it would not suit a tool for writing. We agreed on an abstract willow branch instead: a thin stem with a few leaves. The first sketches played with leaves shaped like speech bubbles, and with a letter V built from two thin branches. The shape has to survive being very small, because it also sits in the menu bar, where it is drawn as an outline when idle and filled while a session is running.</p>
<h2 id="what-the-rename-touched">What the rename touched</h2>
<p>A rename is more than a new title. macOS ties the permissions you grant (microphone, speech recognition, recording other apps’ audio) to the identity of the app, so changing the identity has a cost. We wanted to pay it once and early, before many people had installed the app. That is why the change was done in one pass instead of piece by piece.</p>
<p>The app does the same things as before: it types what you say into any text field, shows live subtitles with translation, and translates text under the cursor, with recognition and translation running on your Mac. You can read how that works in <a href="/docs/what-leaves-your-mac/">what leaves your Mac</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The app and the site in English, Ukrainian and Russian</title>
      <link>https://verbaide.com/blog/interface-in-three-languages/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/interface-in-three-languages/</guid>
      <pubDate>Sat, 08 Aug 2026 12:00:00 GMT</pubDate>
      <description>The app now speaks three languages, picks one from your system, and switches without a restart. The site picks Ukrainian by the visitor&apos;s country.</description>
      <content:encoded><![CDATA[<p>Until today the app’s interface was in Russian only, while the site already spoke three languages. Someone who came from the Ukrainian page, downloaded the app and opened it saw Russian. Now the app and the site both work in English, Ukrainian and Russian.</p>
<h2 id="in-the-app">In the app</h2>
<p>The app takes the first of these three languages from your macOS language list. If none of them is there, it uses English. In Settings you can choose a language yourself, and it applies at once, without a restart.</p>
<p>Where we store the choice matters. It goes to the same place that the system’s own per-app language setting (System Settings, General, Language and Region, Applications) writes to. So the two switches cannot disagree, and the choice survives a restart with no extra code. “Follow the system” is simply the absence of a saved choice.</p>
<p>Switching at once turned out to be the harder half. The usual way to load strings in a Mac app reads the language at launch and never changes it. We load the strings through our own object that can swap the language while the app runs. A missing string falls back to English, and then to the key itself, so a gap shows up as a visible oddity instead of blank space.</p>
<p>The menu was the first trap. Windows redraw themselves, but a menu holds finished text. The app lives in the menu bar, so forgetting this would mean the language changed everywhere except the place you use most. The second trap came after: several places had stored a finished sentence, not the thing to translate. A permission test result, the status message on the dictation panel, the loading label of the pinned translation window. Each had to remember the reason for the message, so a language switch could reach it. Old history entries had the Russian words for “dictation” and “secretary” written inside them, so they stayed Russian after a switch. They are now mapped to language-neutral labels.</p>
<p>Two things we left alone on purpose. The words you can say aloud for punctuation are recognition data, not interface, so they were not translated with the interface. And the interface language and the speech language are different things: you can dictate in Ukrainian on an English Mac. One does not change the other.</p>
<p>The texts of the system’s permission requests have their own files, because macOS draws those windows itself. After a manual language change, the new language appears there from the next launch.</p>
<h2 id="on-the-site">On the site</h2>
<p>Each language now has its own address: the root for English, /ru/ for Russian, /uk/ for Ukrainian. The text is in the page itself, not swapped by a script after loading, so search engines can read each language separately.</p>
<p>At first the root address picked the language from the browser. But a visitor in Ukraine with a Russian or English browser would have stayed on the English page, and we wanted the Ukrainian version to open first for visitors in Ukraine. So the site now looks at the visitor’s country as well. Once you click the language switcher, your choice wins on every later visit.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Style presets without the cloud: what we measured</title>
      <link>https://verbaide.com/blog/style-presets-on-device/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/style-presets-on-device/</guid>
      <pubDate>Fri, 07 Aug 2026 12:00:00 GMT</pubDate>
      <description>Apple&apos;s on-device model rewrites dictation in a chosen tone. It does not know Russian, so text goes through English: the direct path worked 0 times in 30.</description>
      <content:encoded><![CDATA[<p>You dictate a rough thought, and the app can rewrite it in a chosen tone before it lands in the field: neutral, friendly or professional. The rewriting is done by the language model that Apple builds into macOS 26. No text leaves the Mac. Before building it, we measured whether it works for Russian.</p>
<h2 id="the-spike">The spike</h2>
<p>Before building anything we ran a throwaway experiment. We wrote ten realistic business phrases in Russian: a short chat reply, a polite refusal, a request to a colleague, a few with English terms inside. We pushed them through the model in different tones, including deliberately extreme ones such as a pirate or a melodrama, so that differences were easy to see.</p>
<p>There was an obvious catch. The model supports 23 languages, and Russian is not one of them. A model can still produce a smooth text from a language it does not know, by guessing from familiar word pieces, and by eye a good guess is hard to tell from real understanding. So we agreed to treat a suspiciously smooth result as a reason for doubt, not as proof of quality.</p>
<p>The verdict from the live run was that the quality is usable, free and works offline. The model also has a hard limit: 4,096 tokens for the instructions, the input and the answer together.</p>
<h2 id="0-out-of-30">0 out of 30</h2>
<p>The key question was the direct path: Russian text in, Russian text in another tone out. We counted it honestly, with a log that records which path produced each result. Ten phrases in three tones made 30 attempts. The direct path worked 0 times. All 30 went to the fallback, and the fallback never failed.</p>
<p>The fallback goes through English. The Russian text is translated into English with Apple’s translation, the English is rewritten in the chosen tone, and the result is translated back. The chain ends in plain safety: if any step fails or the needed language pack is missing, you get your original text, never a half result. On the key that does not translate, English text is never pasted by mistake.</p>
<p>We still left the direct attempt in the code. Russian is expected in the next generation of the model, which comes with macOS 27. When it arrives, the direct path starts working without a change on our side. Until then it costs a fraction of a second per failed attempt, and we accepted that.</p>
<h2 id="what-went-wrong-in-live-testing">What went wrong in live testing</h2>
<p>The friendly tone sometimes answered the text instead of rewriting it: a greeting, a comment nobody asked for, an offer to help. It was worst on short phrases. We added an explicit instruction that the model rewrites and does not reply, and then put it into every tone, because the failure was not tied to one tone. Another trap: when the model hits its length limit, it stops without an error and returns a cut-off text as if it were fine. We check whether the answer ends like a sentence, and fall back if it does not.</p>
<p>Escape cancels styling at any moment. On August 7 the dictation panel also got a style switcher, and the instructions for each tone can be edited.</p>
<p>Today: styles run on a small model that the app downloads on your request, so Apple’s model is no longer required.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Dictation into any field, and the secretary</title>
      <link>https://verbaide.com/blog/dictation-and-secretary/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/dictation-and-secretary/</guid>
      <pubDate>Wed, 05 Aug 2026 12:00:00 GMT</pubDate>
      <description>How dictation by hotkey and the long-session secretary mode work, and why the lack of punctuation in Apple&apos;s Russian recognition was a real problem.</description>
      <content:encoded><![CDATA[<p>Until this week the app listened to other people’s speech. Now it also listens to yours. You speak Russian, and the text lands where your cursor is, either as spoken or translated into English. Getting there took three steps.</p>
<h2 id="step-1-russian-and-english-at-once-august-3">Step 1: Russian and English at once (August 3)</h2>
<p>The first job was listening to mixed English and Russian speech for the live subtitles. Apple’s English recognizer has no Russian at all. We checked the list of languages it supports on a Mac: 30 of them, and Russian is not among them. Russian lives in a different recognizer from the same framework, built for dictation. So we run both at the same time on the same sound, and for each phrase we pick the one that is more confident about what it heard. A Russian phrase is kept as it is and not translated; an English one is translated into Russian. A single phrase gets one language: the recognizer cannot switch language in the middle, so a foreign word inside a sentence is written down by ear in the winning language.</p>
<p>The Russian recognizer has a flaw we measured the same day: it puts no punctuation, even when asked. A sentence arrives as one line without full stops. That is bad for reading, and worse for translation: a request “перепроверь” came out as “I’ll double-check”, a promise instead of a request. So dictation does not use it: Russian dictation runs on a separate model, Parakeet, which puts punctuation in by itself. The recognizer pair above serves the live subtitles.</p>
<h2 id="step-2-dictation-by-hotkey-august-4">Step 2: dictation by hotkey (August 4)</h2>
<p>Two key combinations. Option-Space puts what you said into the field under the cursor as it was said. Option-Control-Space translates it into English first. The text is pasted as one piece when you finish. The paste has guards: if something is selected in the field, or a password field is active, it does not blindly overwrite anything. Spoken punctuation works too: say the name of a mark and you get the mark.</p>
<h2 id="step-3-the-secretary-august-5">Step 3: the secretary (August 5)</h2>
<p>The third combination, Option-Command-Space, starts a long session. You talk for as long as you need, with pauses and distractions, and each recognized piece is pasted straight into the field where you began. You can switch to another app meanwhile; the text keeps going to the original place.</p>
<p>That promise needs care. Before every paste the app checks that the target application is still running, that the focus is still in the same field (not another field of the same app, such as a search box), that nothing is selected there, and that the system is not in password entry. If the focus moved, the piece waits and the panel says so, rather than pasting somewhere else. The session ends with the same key, with a cross on the panel, or after 15 minutes.</p>
<p>We deliberately did not capture the Escape key for the whole session. Capturing it would stop Escape from working in every other app while you dictate, and a session lasts minutes. The cross on the panel ends it instead.</p>
<p>One bug found on August 5: pasting silently failed in chat apps built on Electron when the keyboard layout was not Latin. We now switch to a Latin layout for the instant of the paste.</p>
<p>Today: both ways are now one dictation. Hold a key for a phrase, or tap it briefly for the secretary, and both are free.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Why we skipped Apple&apos;s dictation for Russian</title>
      <link>https://verbaide.com/blog/why-parakeet/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/why-parakeet/</guid>
      <pubDate>Mon, 03 Aug 2026 12:00:00 GMT</pubDate>
      <description>Apple&apos;s Russian dictation puts no punctuation in the text. That breaks translation and reading, so we chose the Parakeet model for Russian.</description>
      <content:encoded><![CDATA[<p>macOS can recognize Russian speech, but the text it returns has no commas, no periods, no question marks. Today we connected a different recognizer for Russian, a model called Parakeet, and here is why.</p>
<h2 id="what-apple-gives-for-russian">What Apple gives for Russian</h2>
<p>Apple has two speech engines. The newer one, SpeechAnalyzer, is what we use for English. For Russian, Apple offers only the older dictation engine, and it does not put punctuation in. You get one long run of words.</p>
<p>Take a spoken phrase like: “Привет как дела сегодня хорошая погода я хочу пойти на прогулку”. Nothing marks where one sentence ends and the next starts. You can read it, but slowly, and you have to fix it by hand before you send it anywhere.</p>
<h2 id="why-punctuation-matters-for-us">Why punctuation matters for us</h2>
<p>It matters twice. First, reading: text without punctuation is tiring, and a dictation tool that makes you add every comma gives back the time it saved. Second, translation. Our app can translate what you dictate, and a translator needs to see where sentences end. If it gets one endless run of words, it guesses, and it guesses wrong in ways you will not notice unless you read both languages.</p>
<p>So an engine that leaves punctuation out was not good enough for the main scenario, speaking Russian and getting clean text, or clean English.</p>
<h2 id="what-we-chose">What we chose</h2>
<p>Parakeet TDT v3 is a speech recognition model from NVIDIA. It has 0.6 billion parameters, supports Russian among other European languages, and writes punctuation and capital letters itself. We run it on the Mac through a library called FluidAudio, which packages the model for the Apple chip. The model is downloaded the first time the app needs it, from huggingface.co. The speech itself stays on your Mac.</p>
<p>It is a real cost. A recognizer from outside the system means a download and a dependency we have to maintain, and Apple’s engine would have been the simpler path. We took it because the alternative was text that fails at the first sentence break.</p>
<h2 id="what-we-do-not-claim">What we do not claim</h2>
<p>We have not compared it against every recognizer on the market. We compared it with the one macOS offers for Russian, and in that comparison the missing punctuation decided the question. How accurate it is on your voice and your vocabulary is something we will keep measuring, and we will report what we find.</p>
<p>Today: the app downloads our own further-trained version of Parakeet, and the setup is described in <a href="/docs/languages-and-models/">languages and models</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Translating the text under your mouse pointer</title>
      <link>https://verbaide.com/blog/translate-under-the-cursor/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/translate-under-the-cursor/</guid>
      <pubDate>Thu, 30 Jul 2026 12:00:00 GMT</pubDate>
      <description>Hold two keys, point at English text in any app, and get a translation and a dictionary entry next to the pointer. How it reads the text and keeps formatting.</description>
      <content:encoded><![CDATA[<p>Subtitles cover speech. Most English we meet is written, though: a page, a chat, a code review. Today the app learned to translate the sentence under your mouse pointer, in any application.</p>
<h2 id="how-it-works">How it works</h2>
<p>You hold a key combination and point at English text. By default the combination is Option and Command. A small panel appears next to the pointer with three blocks: the original in small type, the Russian translation under it, and a dictionary entry for the word under the pointer. We look the word up in English, not in its translation, because a definition of the English word is more useful. The system dictionary reduces the word to its base form, so “caching” finds “cache”.</p>
<p>If you have already selected a phrase and the pointer is inside the selection, the app translates the whole selection instead of one sentence. Only inside: an old selection somewhere else in the text would otherwise override whatever you point at later, and you would not understand why the wrong text was translated. A very long selection is cut at 600 characters at a word boundary, because translating a whole document you selected with Command-A is slow and pointless.</p>
<p>The mode is off by default. It needs the Accessibility permission, and we do not ask for a permission from someone who has not asked about the feature.</p>
<h2 id="reading-text-without-watching-the-screen">Reading text without watching the screen</h2>
<p>The obvious way to read text under a pointer is to recognize the screen picture. That would put the purple screen-recording indicator in the menu bar permanently. We first checked what the system’s accessibility interface returns. In the browser, the code editor and the chat app we tried, it gives the sentence exactly at the pointer position. So no screen recording was needed.</p>
<p>Browsers were the hard part. For a selection that spans a heading and a paragraph, the accessibility interface returns one flat string, and the heading sticks to the next line. Our first fix read the fonts of the selection and built the structure from font sizes. It worked, but it was a workaround. A better source turned out to be the clipboard: browsers put the full rich text there. So the app sends Command-C to the active app, reads the formatted copy, and puts your previous clipboard content back. It compares the copy with what accessibility returned, so it never shows a text from another window. Headings, lists and bold text survive.</p>
<p>The translator does not keep markers like “##” or list dashes. We take them off, translate the text, and put them back. If the translator returns a different number of lines, we show its answer as it is.</p>
<h2 id="the-pinned-window">The pinned window</h2>
<p>A pin in the corner of the panel turns it into a normal window. It stays, you can resize it, select text with the mouse, and look up a selected word. Each block has its own buttons for smaller and larger type, and the size is remembered. A speaker button reads the block aloud. We choose the voice by alphabet, not by the system’s language detector: it called the word “масштаб” Ukrainian, and there is no Ukrainian voice on the Mac, so the speech would have silently failed. A text with at least one Cyrillic letter is read with the Russian voice.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The first build: live subtitles with translation</title>
      <link>https://verbaide.com/blog/first-build-live-subtitles/</link>
      <guid isPermaLink="true">https://verbaide.com/blog/first-build-live-subtitles/</guid>
      <pubDate>Wed, 29 Jul 2026 12:00:00 GMT</pubDate>
      <description>In one day we built a menu-bar app that listens to a chosen app or microphone, writes English subtitles and translates them into Russian on the Mac.</description>
      <content:encoded><![CDATA[<p>Today the first version of our app started working. You pick an application that is playing sound, or a microphone. The app recognizes the English speech and shows it in a small window, with a Russian translation under each line. Everything happens on the Mac.</p>
<h2 id="what-it-does">What it does</h2>
<p>The app lives in the menu bar. The menu lists the applications you can listen to and the microphones. Applications that are silent right now stay in the list too: a video call has not started yet, a browser tab is paused, but you need to pick them in advance. The ones that are playing sound go first.</p>
<p>The subtitles appear in a window that stays above all other windows. You drag it by the background and resize it by the corner. It remembers its place and size. In the window you can show English only, Russian only, or both, with the English line on top. Fonts, colors and background transparency are set in a separate settings window.</p>
<p>When you press Stop, the whole session is saved. The “Recent transcriptions” window lists the last 50 sessions, and you can copy any of them as text. A session where nobody said anything is not saved.</p>
<h2 id="two-decisions">Two decisions</h2>
<p><strong>How to catch the sound of one app.</strong> The usual way is the screen-capture framework. We did not take it: it asks for the screen-recording permission and keeps a recording indicator in the menu bar for as long as it works. Instead we use the system’s way of tapping one process’s audio. It has its own permission and no screen indicator. Browsers and chat apps play sound from several helper processes, so we group them by the application they belong to and listen to all of them at once.</p>
<p><strong>Do not wait for the end of a phrase.</strong> People speak a sentence for four to eight seconds, and a screen that is empty all that time feels broken. So we show the text as it grows. Apple’s recognizer, run in its fast mode, gives new text about once a second; without that mode it came about every 3.8 seconds. The last words still flicker and get corrected, but this is better than waiting.</p>
<p>Translation arrives later than recognition, and that caused the one tricky bug class. Text comes in bursts, and the first update of a burst is often a scrap like “So”. We wait 150 milliseconds and translate the latest update. Every update has a number, and a translation of older text is thrown away, so a late answer never overwrites a newer line.</p>
<h2 id="what-is-in-the-box">What is in the box</h2>
<p>The same day we added an app icon and an installer: a disk image with a short guide inside, and a ready recipe for installing through Homebrew. For now the app needs macOS 26, because it uses Apple’s newer speech recognition. It asks for three permissions: audio of other apps, microphone, and speech recognition.</p>
<p>This version understands English only and translates only into Russian. The next step is the text under your mouse pointer.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
