cd /news/ai-tools/build-a-real-time-voice-translation-… · home › topics › ai-tools › article
[ARTICLE · art-151691] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=↑ positive

Build a Real-Time Voice Translation App

A developer published a walkthrough for building a real-time voice translation app that chains speech-to-text, machine translation, and text-to-speech services, using ElevenLabs for voice synthesis. The guide pairs a JavaScript MediaRecorder frontend with a Python FastAPI backend that streams 250ms audio chunks over WebSocket, targeting roughly two seconds of end-to-end latency.

by read4 min views5 publishedOct 17, 2026

Getting Started with a Real‑Time Voice Translation App

Building a real‑time voice translation app feels like science‑fiction, but with today’s cloud APIs it’s a very achievable side‑project. In this article we’ll walk through the whole stack: capturing audio, transcribing it, translating the text, and finally turning the translated text back into speech. We’ll keep the example language‑agnostic (Python on the backend, JavaScript on the frontend) and we’ll lean on a few battle‑tested services. The star of the show is ElevenLabs for its high‑quality text‑to‑speech (TTS) and voice‑cloning capabilities. You can start experimenting right away with their free tier at https://try.elevenlabs.io/kr07zfuqn1bp.

If you’re building a language‑learning app, a travel chatbot, or a customer‑support tool, latency is everything. A 2‑second delay feels natural; a 5‑second lag is noticeable. That means we need:

The rest of this guide assumes you already have an API key for a STT provider (Google Cloud Speech‑to‑Text, Azure Speech, or Whisper on your own server) and a translation service (Google Translate, DeepL, or Microsoft Translator). We’ll plug in ElevenLabs for the TTS step.

+----------------+      +-------------------+      +-----------------+
|  Browser (JS)  | <--->|  Node.js/Flask API| <--->|  ElevenLabs TTS |
+----------------+      +-------------------+      +-----------------+
        ^                        ^                          ^
        |                        |                          |
        |  WebSocket (audio)     |  REST (transcribe/translate)
        |                        |                          |
        |                        |                          |
  Mic input  <---  STT API  <---  Translation API  <---  TTS Engine

Below is a minimal JavaScript snippet that records mic input and streams it to a server using WebSocket. We’re using the MediaRecorder API for simplicity.

const socket = new WebSocket('wss://your-server.com/stream');
const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });

mediaRecorder.ondataavailable = (e) => {
  // Send each chunk as binary data
  socket.send(e.data);
};

socket.addEventListener('message', (event) => {
  // event.data is the TTS audio blob from ElevenLabs
  const audio = new Audio(URL.createObjectURL(event.data));
  audio.play();
});

mediaRecorder.start(250); // send 250ms chunks

What to watch for

MediaRecorder. For older browsers you may need a polyfill or a server‑side WebRTC solution. We’ll use Python + FastAPI for the backend because of its async support and excellent typing. The core flow is:

from fastapi import FastAPI, WebSocket
import aiohttp
import asyncio
import json

app = FastAPI()

STT_ENDPOINT = "https://api.speech-to-text.com/v1/recognize"
TRANSLATE_ENDPOINT = "https://api.translate.com/v1/translate"
ELEVENLABS_API = "https://api.elevenlabs.io/v1/text-to-speech"

ELEVENLABS_API_KEY = "YOUR_ELEVENLABS_KEY"

async def transcribe_audio(audio_bytes: bytes) -> str:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            STT_ENDPOINT,
            headers={"Authorization": f"Bearer {STT_ENDPOINT}"},
            data=audio_bytes,
        ) as resp:
            result = await resp.json()
            return result["text"]

async def translate_text(text: str, target_lang: str = "es") -> str:
    async with aiohttp.ClientSession() as session:
        payload = {"q": text, "target": target_lang}
        async with session.post(
            TRANSLATE_ENDPOINT,
            json=payload,
            headers={"Authorization": f"Bearer {TRANSLATE_ENDPOINT}"},
        ) as resp:
            result = await resp.json()
            return result["translatedText"]

async def synthesize_speech(text: str) -> bytes:
    async with aiohttp.ClientSession() as session:
        payload = {
            "text": text,
            "voice_settings": {"pitch": 0, "speed": 1}
        }
        async with session.post(
            ELEVENLABS_API,
            json=payload,
            headers={
                "xi-api-key": ELEVENLABS_API_KEY,
                "Content-Type": "application/json",
            },
        ) as resp:
            return await resp.content.read()

@app.websocket("/stream")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    buffer = bytearray()
    while True:
        data = await websocket.receive_bytes()
        buffer.extend(data)

        if len(buffer) > 300_000:  # roughly 3 s of 96 kHz audio
            text = await transcribe_audio(buffer)
            translated = await translate_text(text, target_lang="de")
            audio = await synthesize_speech(translated)
            await websocket.send_bytes(audio)
            buffer.clear()

ElevenLabs offers:

Tip: The free tier gives you a generous amount of usage per month. If you’re building a prototype, you’ll be fine. When you go live, just swap the API key in the ELEVENLABS_API_KEY variable.

Step What to do Notes
1 Deploy the FastAPI app to a platform that supports WebSockets (e.g., Fly.io, Render, Railway). Make sure you set CORS_ALLOW_ORIGIN to your domain.
2 Secure your API keys. Store them in environment variables or a secrets manager. Don’t hard‑code them in the repo.
3 Enable HTTPS on the front‑end. Browsers block microphone access on insecure origins. Let’s Encrypt is free.
4 Test latency. Use chrome://inspect orwebsocket.org to measure round‑trip time. Aim for < 500 ms end‑to‑end.
5 Optimize VAD. If you notice unnecessary STT calls, add a simple VAD library like webrtcvad . Reduces costs and latency.

target_lang parameter. With a handful of lines of code and a few paid services, you can turn a microphone into a real‑time, multilingual chatbot. The key is to keep the data path tight: mic → STT → translation → TTS → speaker. ElevenLabs makes the last hop the smoothest, delivering natural‑sounding voices that feel like a real person.

Ready to bring your voice translation idea to life? Sign up for ElevenLabs today and unlock high‑quality TTS and voice‑cloning for your app.

Try ElevenLabs now: https://try.elevenlabs.io/kr07zfuqn1bp

Happy coding!

── more in #ai-tools 4 stories · sorted by recency
── more on @elevenlabs 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/build-a-real-time-vo…] indexed:0 read:4min 2026-10-17 · —