DEV Community

VoiceDeveloper
VoiceDeveloper

Posted on

How to Build a Pronunciation Guide App with AI Voice

Why a Pronunciation Guide App?

If you’ve ever tried to learn a new language, you know how frustrating it can be to hear a word in a textbook and have no clue how it actually sounds. A pronunciation guide app solves that problem by turning any piece of text into a clear, natural‑sounding voice—ideally one that matches the learner’s target accent. With today’s AI‑powered text‑to‑speech (TTS) services, building such an app is easier than ever.

In this article you’ll get a step‑by‑step walkthrough of a minimal but fully functional pronunciation guide built with Python, a tiny Node.js server for the UI, and ElevenLabs for the voice generation. By the end you’ll have:

  • A REST endpoint that receives a word or phrase and returns an audio file.
  • A front‑end page where users can type text, select a voice, and play the result.
  • A quick demo of voice cloning so you can give the app a custom narrator.

Let’s dive in!

1. Pick the Right TTS Provider

There are a handful of solid TTS APIs out there (Google Cloud, Amazon Polly, Azure Speech). For a pronunciation guide you need:

  • High‑quality, natural sounding voices – learners should hear subtle intonation.
  • Fast response time – the app feels snappy when a user presses “Play”.
  • Voice cloning – optional but fun for personalizing the guide.

ElevenLabs checks all those boxes. Their API delivers studio‑grade audio in under a second and includes a straightforward voice‑cloning endpoint. You can sign up for free and start generating audio right away using this affiliate link: https://try.elevenlabs.io/kr07zfuqn1bp.

2. Set Up the Backend (Python + FastAPI)

FastAPI makes it trivial to expose a small HTTP API. First, install the dependencies:

# Create a virtualenv (optional but recommended)
python -m venv .venv
source .venv/bin/activate

# Install FastAPI and the HTTP client
pip install fastapi uvicorn httpx python-multipart
Enter fullscreen mode Exit fullscreen mode

2.1. Create main.py

# main.py
import os
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import StreamingResponse
import httpx

app = FastAPI()

ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
ELEVENLABS_TTS_URL = "https://api.elevenlabs.io/v1/text-to-speech"

def synthesize(text: str, voice_id: str = "EXAVITQu4vr4xnGd") -> bytes:
    """Call ElevenLabs TTS and return raw MP3 bytes."""
    headers = {
        "xi-api-key": ELEVENLABS_API_KEY,
        "Content-Type": "application/json"
    }
    payload = {
        "text": text,
        "voice_settings": {
            "stability": 0.75,
            "similarity_boost": 0.75
        }
    }
    url = f"{ELEVENLABS_TTS_URL}/{voice_id}"
    response = httpx.post(url, json=payload, headers=headers, timeout=30.0)
    if response.status_code != 200:
        raise HTTPException(status_code=502, detail="TTS service error")
    return response.content

@app.post("/pronounce")
async def pronounce(text: str, voice_id: str = "EXAVITQu4vr4xnGd"):
    """Return an MP3 stream for the supplied text."""
    audio_bytes = synthesize(text, voice_id)
    return StreamingResponse(
        iter([audio_bytes]),
        media_type="audio/mpeg",
        headers={"Content-Disposition": f'attachment; filename="{text}.mp3"'}
    )
Enter fullscreen mode Exit fullscreen mode

What’s happening?

  1. synthesize() builds the request body that ElevenLabs expects.
  2. We send a POST request to https://api.elevenlabs.io/v1/text-to-speech/{voice_id}.
  3. The API returns raw MP3 data, which we stream back to the client.

Tip: Store your ElevenLabs API key in an environment variable (ELEVENLABS_API_KEY). Never hard‑code secrets.

Run the server:

export ELEVENLABS_API_KEY=YOUR_API_KEY_HERE
uvicorn main:app --reload
Enter fullscreen mode Exit fullscreen mode

You now have a /pronounce endpoint that takes text (and optionally a voice_id) and returns an audio file.

3. Front‑End Quick‑Start (Node.js + Express + Vanilla JS)

The UI is intentionally simple: an input box, a voice selector, and a “Play” button.

3.1. Install Express

mkdir ui && cd ui
npm init -y
npm install express cors
Enter fullscreen mode Exit fullscreen mode

3.2. Create server.js

// server.js
const express = require('express');
const cors = require('cors');
const path = require('path');

const app = express();
app.use(cors());
app.use(express.static('public'));

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.listen(3001, () => console.log('UI server listening on http://localhost:3001'));
Enter fullscreen mode Exit fullscreen mode

3.3. Build public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Pronunciation Guide</title>
  <style>
    body { font-family: sans-serif; margin: 2rem; }
    input, select { padding: .5rem; margin-right: .5rem; }
    button { padding: .5rem 1rem; }
  </style>
</head>
<body>
  <h1>Pronunciation Guide</h1>
  <input id="text" placeholder="Enter word or phrase" size="40">
  <select id="voice">
    <option value="EXAVITQu4vr4xnGd">Rachel (US English)</option>
    <option value="TxGEqnHWrfWFTfGW9XjX">Domi (French)</option>
    <!-- Add more voice IDs from ElevenLabs dashboard -->
  </select>
  <button id="play">Play</button>
  <audio id="player" controls style="display:none;"></audio>

  <script>
    const playBtn = document.getElementById('play');
    const player = document.getElementById('player');

    playBtn.addEventListener('click', async () => {
      const text = document.getElementById('text').value.trim();
      const voice = document.getElementById('voice').value;
      if (!text) return alert('Please type something!');

      const resp = await fetch(`http://localhost:8000/pronounce?text=${encodeURIComponent(text)}&voice_id=${voice}`);
      if (!resp.ok) return alert('Error from TTS service');

      const blob = await resp.blob();
      player.src = URL.createObjectURL(blob);
      player.style.display = 'block';
      player.play();
    });
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Run the UI server:

node server.js
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:3001, type a word, pick a voice, and hit Play. The browser streams the MP3 generated by your FastAPI backend.

4. Adding Voice Cloning (Optional but Cool)

ElevenLabs lets you upload a short audio sample (≈10‑30 seconds) and create a custom voice ID. Here’s a quick curl snippet to upload a sample:

curl -X POST "https://api.elevenlabs.io/v1/voices/add" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  -F "name=MyCustomNarrator" \
  -F "files=@/path/to/sample.wav"
Enter fullscreen mode Exit fullscreen mode

The response includes a voice_id. Swap that ID into the <select> element in index.html and you’ve got a personalized narrator for your language learners.

Pro tip: Use a clean recording (no background noise) and a neutral speaking style for the best cloning results.

5. Deploying Quickly

Both the Python API and the Node UI are lightweight, so you can host them on any platform that supports Docker, Vercel, or Render.

A minimal Dockerfile for the FastAPI service:

# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
ENV PORT=8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Enter fullscreen mode Exit fullscreen mode

Push the image to your registry, spin up a container, and point the UI’s fetch URL to the new host. The same idea applies to the Express UI – a one‑liner node server.js works on most PaaS providers.

6. What to Tweak Next?

  • Cache audio – Store generated MP3s in Redis or a CDN so repeated requests for the same word are instant.
  • Add phonetic hints – Show IPA transcription alongside the audio.
  • Support multiple languages – ElevenLabs offers a growing catalog of voices; just expose a language selector.
  • Rate‑limit – Protect your API key from abuse by limiting requests per IP.

7. Wrap‑Up

You now have a functional pronunciation guide that leverages cutting‑edge AI voice technology. The core pieces—FastAPI for the backend, ElevenLabs for the TTS, and a tiny Express front‑end—are all open source and easy to extend.

Ready to give your learners crystal‑clear pronunciation? Grab your ElevenLabs API key, spin up the code, and start experimenting with voice cloning. The more you play with the parameters (stability, similarity_boost), the more you’ll discover how to fine‑tune the listening experience.

Try ElevenLabs today and bring natural‑sounding AI voices to your app: https://try.elevenlabs.io/kr07zfuqn1bp. Happy coding!

Top comments (0)