<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Uhem's blog]]></title><description><![CDATA[Building, playing, and shooting. This is a collection of notes on software development, music production, and photography—focusing on the technical side of the ]]></description><link>https://blog.uempxl.com</link><image><url>https://cdn.hashnode.com/uploads/logos/69e8d3c95d1c107105561608/f59cba45-c912-4923-bdf9-a3ba8f4247d5.svg</url><title>Uhem&apos;s blog</title><link>https://blog.uempxl.com</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 22 Apr 2026 17:47:28 GMT</lastBuildDate><atom:link href="https://blog.uempxl.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Using Google TTL to make Nepali Speech]]></title><description><![CDATA[Project Overview

Project Name: Nepali TTS Studio

Tech Stack: HTML5, Vanilla JavaScript, Tailwind CSS, Google Gemini API (gemini-2.5-flash-preview-tts), Web Audio API.

Platform: Web (Client-Side), h]]></description><link>https://blog.uempxl.com/using-google-ttl-to-make-nepali-speech</link><guid isPermaLink="true">https://blog.uempxl.com/using-google-ttl-to-make-nepali-speech</guid><dc:creator><![CDATA[Uhenraj Jarga Magar]]></dc:creator><pubDate>Wed, 22 Apr 2026 14:27:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69e8d3c95d1c107105561608/70c8b9f8-3aa7-4464-84aa-16bfcab5bb21.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>Project Overview</strong></h3>
<ul>
<li><p><strong>Project Name:</strong> Nepali TTS Studio</p>
</li>
<li><p><strong>Tech Stack:</strong> HTML5, Vanilla JavaScript, Tailwind CSS, Google Gemini API (<code>gemini-2.5-flash-preview-tts</code>), Web Audio API.</p>
</li>
<li><p><strong>Platform:</strong> Web (Client-Side), hosted on GitHub Pages.</p>
</li>
<li><p><strong>Live Demo:</strong> <a href="https://ficcc.github.io/nepali-tts/">https://ficcc.github.io/nepali-tts/</a></p>
</li>
</ul>
<h3><strong>The Problem: Accessibility and Language Support</strong></h3>
<p>Text-to-Speech (TTS) technology has advanced rapidly, but high-quality, natural-sounding voice generation often remains gated behind complex backend setups, paid subscriptions, or focuses primarily on English. Finding lightweight, accessible tools that natively support languages like Nepali is challenging.</p>
<p>The goal was to build an application that could take Nepali script and convert it into high-fidelity audio without requiring the user to install heavy dependencies or rely on a developer managing an expensive backend server.</p>
<h3><strong>The Solution: A Client-Side Architecture</strong></h3>
<p>I developed <strong>Nepali TTS Studio</strong>, a strictly client-side web application. By leveraging Google’s Gemini API directly from the browser, the application offloads the heavy lifting of audio generation to Google's infrastructure while keeping the deployment architecture as simple as possible—just static HTML, JavaScript, and CSS.</p>
<h4><strong>Key Features:</strong></h4>
<ul>
<li><p><strong>Bring-Your-Own-Key (BYOK):</strong> To keep the app free and serverless without exposing private API keys, the UI securely prompts the user for their own Gemini API key.</p>
</li>
<li><p><strong>Granular Voice Control:</strong> Users can select between multiple Gemini voice profiles (Kore, Aoede, Zephyr, etc.) and adjust the speaking speed.</p>
</li>
<li><p><strong>Local Export:</strong> The app doesn't just play the audio; it allows users to download the generated speech as a standard <code>.wav</code> file for external use.</p>
</li>
</ul>
<h3><strong>Technical Implementation</strong></h3>
<h4><strong>1. Integrating the Gemini 2.5 Flash TTS API</strong></h4>
<p>The core of the application relies on sending a highly specific prompt to the <code>gemini-2.5-flash-preview-tts</code> model. To ensure the model doesn't respond with conversational English or introductory text, the payload enforces strict parameters:</p>
<pre><code class="language-javascript">const payload = {
  contents: [{
    parts: [{
      text: `Read the following text strictly in Nepali language. Speak \({selectedSpeed}. Do not add any conversational remarks... Text to read: \){textToSpeak}`
    }]
  }],
  generationConfig: {
    responseModalities: ["AUDIO"],
    speechConfig: {
      voiceConfig: { prebuiltVoiceConfig: { voiceName: selectedVoice } }
    }
  }
};
</code></pre>
<h4><strong>2. Handling the Audio Output (Base64 to WAV)</strong></h4>
<p>One of the primary technical challenges was handling the data returned by the Gemini API. The API returns the audio as a Base64 encoded string, which isn't immediately playable in a standard HTML <code>&lt;audio&gt;</code> tag or easily downloadable as a standard file format.</p>
<p>To solve this, I implemented a custom JavaScript function to decode the Base64 string into a <code>Uint8Array</code> of raw PCM data, and then manually constructed the WAV file headers (RIFF chunk, fmt sub-chunk, and data sub-chunk). This allowed the app to generate a valid <code>Blob</code> of type <code>audio/wav</code>, which is then mapped to a <code>Blob URL</code> for playback and downloading.</p>
<h4><strong>3. UI and State Management</strong></h4>
<p>Using Tailwind CSS via CDN allowed for rapid UI prototyping without a build step. The interface handles various asynchronous states—managing loading spinners during the API fetch, disabling buttons to prevent duplicate requests, and gracefully catching network errors using an exponential backoff strategy for the fetch requests.</p>
<h3><strong>Challenges &amp; Takeaways</strong></h3>
<ul>
<li><p><strong>Prompt Engineering for Audio:</strong> Generative AI models naturally want to be conversational. Forcing the model to act strictly as a raw TTS engine required precise prompt instructions to strip away unwanted conversational filler.</p>
</li>
<li><p><strong>Stateless Security:</strong> Keeping the application serverless meant finding a safe way to handle API keys. The "Bring Your Own Key" approach solved the security issue but required adding clear UX instructions so non-technical users could easily navigate Google AI Studio to get their own credentials.</p>
</li>
</ul>
<h3><strong>Future Scope</strong></h3>
<p>While this web version serves as a lightweight, highly accessible tool that can run on any device, this architecture serves as a strong foundation for native development. The next phase involves wrapping this core logic into a desktop application using a framework like Tauri, creating a more integrated native experience while maintaining the same high-quality audio output.</p>
]]></content:encoded></item></channel></rss>