<?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: Nick Otmazgin</title>
    <description>The latest articles on DEV Community by Nick Otmazgin (@nickotmazgin).</description>
    <link>https://dev.to/nickotmazgin</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%2F4161504%2F92ad1bdc-17b1-4f9f-a866-dcc8749405ca.jpg</url>
      <title>DEV Community: Nick Otmazgin</title>
      <link>https://dev.to/nickotmazgin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nickotmazgin"/>
    <language>en</language>
    <item>
      <title>Adding offline HD voices to a Windows text-to-speech app (Piper + Kokoro, verified downloads)</title>
      <dc:creator>Nick Otmazgin</dc:creator>
      <pubDate>Sun, 04 Oct 2026 12:10:41 +0000</pubDate>
      <link>https://dev.to/nickotmazgin/adding-offline-hd-voices-to-a-windows-text-to-speech-app-piper-kokoro-verified-downloads-1k9j</link>
      <guid>https://dev.to/nickotmazgin/adding-offline-hd-voices-to-a-windows-text-to-speech-app-piper-kokoro-verified-downloads-1k9j</guid>
      <description>&lt;p&gt;FluentVoice Pro is a small open-source tray app for Windows 11 and 10 that reads selected or copied text aloud. Until version 1.5, every natural-sounding voice came from Microsoft's online voices. They sound great, but they need the internet, and some people don't want their text to leave the PC at all.&lt;/p&gt;

&lt;p&gt;So in v1.5.0 I added &lt;strong&gt;offline HD voices&lt;/strong&gt; that run entirely on the user's computer. Here's how it works, and what I learned along the way.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/onsD0E8ivHk" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Two engines: Piper and Kokoro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Piper&lt;/strong&gt; (via &lt;code&gt;piper-tts&lt;/code&gt;): fast, small models (60-115 MB each) and lots of languages. The app ships a catalogue of 29 voices in 15 languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kokoro&lt;/strong&gt; (via &lt;code&gt;sherpa-onnx&lt;/code&gt;): one 350 MB pack with very natural voices for English, Spanish, French, Italian, Portuguese and Hindi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing is bundled with the app: a voice is downloaded only when the user picks it in &lt;strong&gt;Settings &amp;gt; Voice Providers&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downloads you can trust
&lt;/h2&gt;

&lt;p&gt;Downloading model files from the internet is exactly where a desktop app can get hurt, so every file is treated as untrusted until proven otherwise:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Allow-listed hosts only:&lt;/strong&gt; Hugging Face (the official Piper voice library) and the official sherpa-onnx release on GitHub. Any other host, including redirects, is refused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pinned SHA-256 and size&lt;/strong&gt; for every single file in the catalogue. A file that doesn't match is deleted and never loaded, and it is checked again the first time it's used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe archive extraction:&lt;/strong&gt; the Kokoro pack is a &lt;code&gt;.tar.bz2&lt;/code&gt;, and extraction rejects absolute paths, &lt;code&gt;..&lt;/code&gt; traversal and links.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Licences, voice by voice
&lt;/h2&gt;

&lt;p&gt;"Open model" doesn't mean "free to use however you like". Each voice's training data has its own licence, so the app shows a badge next to every voice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free to use:&lt;/strong&gt; public domain, CC0, CC BY, CC BY-SA, Apache-2.0&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personal use only:&lt;/strong&gt; for example non-commercial recordings; the app asks for confirmation before downloading these&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voices trained on research-only data were left out, and so were Kokoro voices named after other companies' voices. The full table is generated from the catalogue into &lt;code&gt;docs/VOICE_LICENSES.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy mode and fallback
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;Offline only&lt;/strong&gt; switched on, no text is ever sent to an online voice: each language is read by a downloaded offline voice or a built-in Windows voice. And when the online voice is simply unreachable, reading continues with an offline voice &lt;strong&gt;in the same language&lt;/strong&gt;. Before, a Hebrew text would fall back to an English Windows voice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Download (portable EXE, no Python needed): &lt;a href="https://github.com/nickotmazgin/fluentvoice-pro/releases/latest" rel="noopener noreferrer"&gt;https://github.com/nickotmazgin/fluentvoice-pro/releases/latest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Or with Scoop: &lt;code&gt;scoop bucket add nickotmazgin https://github.com/nickotmazgin/scoop-bucket&lt;/code&gt; then &lt;code&gt;scoop install nickotmazgin/fluentvoicepro&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Source code (MIT): &lt;a href="https://github.com/nickotmazgin/fluentvoice-pro" rel="noopener noreferrer"&gt;https://github.com/nickotmazgin/fluentvoice-pro&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On AlternativeTo: &lt;a href="https://alternativeto.net/software/fluentvoice-pro/about/" rel="noopener noreferrer"&gt;https://alternativeto.net/software/fluentvoice-pro/about/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback, bug reports and voice suggestions are very welcome in GitHub Discussions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was drafted by an AI assistant (Claude) from the project's code and docs, at my request, and published by me.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>windows</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
