Integrating Edge-TTS with FastAPI for a Real-time AI Voice Assistant
pyttsx3. It basically hooks into the Microsoft Edge browser's online TTS service, giving you high-quality neural voices for free without needing an API key.I've been using Cursor to scaffold this integration into a FastAPI backend, and the biggest hurdle isn't the code—it's managing the asynchronous nature of the TTS stream so the frontend doesn't hang.
Here is the core implementation I'm using. The trick is to use edge_tts.Communicate and stream the audio chunks directly to the client using FastAPI's StreamingResponse.
import edge_tts
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import asyncio
app = FastAPI()
VOICE = "en-US-AvaNeural"
async def generate_tts_stream(text: str):
communicate = edge_tts.Communicate(text, VOICE)
async for chunk in communicate.stream():
if chunk["type"] == "audio":
yield chunk["data"]
@app.get("/tts")
async def tts_endpoint(text: str):
return StreamingResponse(
generate_tts_stream(text),
media_type="audio/mpeg"
)When I first wrote this, I noticed a significant lag between the request and the audio starting. I used Claude 3.5 Sonnet to optimize the pipeline, and we found that the bottleneck was often the LLM generation speed before hitting the TTS. If you're building a "real-time" assistant, you cannot wait for the full LLM response to finish. You need to implement a sentence-splitter on the LLM stream.
My current productivity workflow for this:
Chunking the LLM output: I use a regex pattern to split the LLM's streaming text by punctuation (., !, ?, \n). As soon as a full sentence is formed, it's pushed to the Edge-TTS queue.
Frontend Buffering: On the React side, I use a queue of audio blobs. This prevents the "stutter" effect where the AI pauses between sentences because the next audio chunk hasn't arrived yet.
Cursor Config Tip: I've added the Edge-TTS documentation and the FastAPI StreamingResponse docs to my Cursor .cursorrules file. This stops the AI from suggesting outdated write methods or trying to save the audio to a temporary .mp3 file on disk, which is a massive performance killer in production.
One major "gotcha" to watch out for: Edge-TTS is an unofficial wrapper. While it's incredibly stable, Microsoft can technically change the endpoint. If you see the service suddenly fail, the first thing to do is update the edge-tts package via pip.
Performance gains I've seen:
Latency: By streaming chunks instead of saving files, I dropped the "time to first sound" from 2.5 seconds to about 600ms.
Resource Usage: Memory overhead is negligible because we aren't storing audio files on the server; it's a pure pass-through stream.
Cost: $0. Comparing this to OpenAI's TTS API, the cost savings for a high-traffic prototype are massive.
If you're deploying this in a Docker container, make sure your base image has the necessary dependencies for asyncio and aiohttp, as Edge-TTS relies heavily on them for the websocket connection to Microsoft's servers.
All Replies (0)
No replies yet — be the first!
