Localizing a podcast, translating a recorded meeting, or dubbing a lecture used to require three different services stitched together. The Telnyx AI Inference API exposes STT, chat completions, and TTS on the same private backbone, which means a single Flask app can run the whole pipeline.
The Telnyx code example is:
https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-content-translator-python
It is a Python Flask app you can clone and run in a few minutes. No phone number, no webhook tunnel, no background job runner.
You POST an audio file plus a target language. The app calls Telnyx STT to transcribe the audio in the source language, calls AI Inference to translate the transcript with a TTS-friendly system prompt, and calls Telnyx TTS to render the translated text into audio. Long transcripts are chunked at sentence boundaries so the TTS model never gets an input larger than it supports, and the chunks are concatenated into one mp3.
The response includes the job id, both transcripts, and a URL you can curl to download the dubbed audio.
It is small enough to demo live, but it covers the parts that often get cut from an audio translation demo:
The design choice I care most about is per-stage error handling. If the TTS call fails on chunk 3 of 8, the app returns 200 partial
with the transcripts still intact, rather than throwing away the STT and translation work.
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/ai-content-translator-python
cp .env.example .env
pip install -r requirements.txt
python app.py
Translate a Spanish clip into English:
curl -X POST http://localhost:5000/translate \
-F audio=@spanish-sample.mp3 \
-F source=es \
-F target=en
Download the dubbed audio:
curl -OJ http://localhost:5000/translate/<job_id>/audio
Read the full transcripts:
curl http://localhost:5000/translate/<job_id> | python3 -m json.tool
I would keep the demo short:
/languages
endpoint to call out the supported set.target=en
and walk through the response shape (job_id, transcript previews, audio_url).GET /translate/<job_id>
for the full transcripts.source=auto
to show language detection.That gives viewers the full loop without getting lost in implementation details.
The demo keeps translation jobs in memory for one hour. Production would replace the in-memory jobs
dict with object storage (S3, GCS) for the audio blobs and a database (Postgres) for the metadata, run STT / translate / TTS in a queue, return 202 Accepted
for long jobs, add API key auth, and cap upload size and audio length up front.