An interactive demo app for exploring Deepgram's real-time speech-to-text API. Supports live microphone streaming, audio file streaming, and batch transcription — with a full params panel so you can experiment with every Deepgram option without writing code.
Live demo: deepgram-python-stt.fly.dev
- Mic streaming — Real-time transcription from your browser microphone using Deepgram's WebSocket API
- File streaming — Upload an audio file and stream it to Deepgram in real-time, with transcript synced to playback
- Batch transcription — Submit a file or URL for single-shot transcription via the REST API
- TTS Test mode — Type any text, generate speech via Deepgram TTS, and transcribe it back through the STT pipeline. Ideal for testing redaction, formatting, and model behavior without a microphone
- Live params panel — Toggle every major Deepgram option (model, language, smart format, VAD, endpointing, redaction, keyterms, and more) and see the URL update instantly
- Import / Export — Paste a Deepgram WebSocket URL or JSON object to import settings; copy the current URL to share a configuration
- API responses tab — Every WebSocket event (interim, final, metadata) logged with expandable JSON
- Error display — Stream errors surfaced directly in the UI with a red badge in the responses tab
The TTS Test tab lets you verify STT behavior end-to-end without a microphone. Type any text, choose a TTS voice, and click Speak & Transcribe — the app generates audio via Deepgram's TTS API and feeds it directly through the STT pipeline using your current param settings.
After each run, a TTS Comparison panel shows:
| Row | Description |
|---|---|
| Sent | The original input text |
| Transcribed | What the STT returned |
| Difference | Word-level diff — deletions in |
This is especially useful for testing redaction (does the PII actually get replaced?), smart formatting (are numbers and punctuation correct?), and model comparisons.
The TTS→STT pipeline is also exposed as a REST endpoint for automated testing:
curl -s -X POST "https://deepgram-python-stt.fly.dev/api/tts-transcribe" \
-H "Content-Type: application/json" \
-d @- << 'EOF'
{
"text": "My credit card is 4111 1111 1111 1111 and my SSN is 123-45-6789.",
"tts_model": "aura-2-asteria-en",
"stt_params": {
"model": "nova-3",
"redact": ["credit_card", "ssn"],
"smart_format": true
}
}
EOFResponse is the full Deepgram STT JSON object.
| Layer | Technology |
|---|---|
| Backend | FastAPI + python-socketio (async) + uvicorn |
| Deepgram | deepgram-sdk v6.x (async WebSocket API) |
| Frontend | Alpine.js (no build step) |
| Deployment | Fly.io |
| Tests | pytest + asyncio + UvicornTestServer + socketio.AsyncClient |
- Python 3.12+
- uv (recommended) or pip
- A Deepgram API key
git clone https://github.com/Jacob-Lasky/deepgram-python-stt
cd deepgram-python-stt
cp sample.env .env
# Edit .env and add your DEEPGRAM_API_KEY
uv run uvicorn app:app --host 0.0.0.0 --port 8080Open http://localhost:8080.
docker build -t deepgram-stt .
docker run -p 8080:8080 -e DEEPGRAM_API_KEY=your_key_here deepgram-sttCopy sample.env to .env:
DEEPGRAM_API_KEY=your_key_hereAll values below are verified to work with the Deepgram streaming API:
| Value | Description |
|---|---|
pci |
Credit card numbers, expiration dates, CVV |
ssn |
Social security numbers |
credit_card |
Credit card numbers (granular) |
account_number |
Bank account numbers |
routing_number |
ABA routing numbers |
passport_number |
Passport numbers |
driver_license |
Driver's license numbers |
numerical_pii |
Numerical PII (granular) |
numbers |
Series of 3+ consecutive numerals |
aggressive_numbers |
All numerals |
phi |
Protected health information |
name |
Person names |
dob |
Dates of birth |
username |
Usernames |
uv run pytest tests/ -v30 tests, 1 skipped. Tests use a real UvicornTestServer + socketio.AsyncClient — no mocking of the SocketIO layer.
Non-obvious things discovered during the Flask/gevent → FastAPI async migration:
gevent.monkey.patch_all()must be the very first edit — it corrupts the asyncio event loop at import time even if called before importssocketio.ASGIAppmust wrap FastAPI — pointing uvicorn atfastapi_appdirectly causes SocketIO 404sAsyncServerhas notest_client()— tests require a realUvicornTestServer+socketio.AsyncClientfixture- SDK callbacks must be
async defwith**kwargs— sync callbacks or missing**kwargssilently never fire - Audio
timeslicemust be 250ms — 1000ms chunks cause the last word before Stop to be dropped stream_startedmust emit immediately on WS connect, not afterMetadata— Metadata timing is non-deterministic and can block the frontend for 10+ seconds- Deepgram boolean params must be lowercase strings (
"true"/"false"), not Python bools
fly launch --name your-app-name # first time only
fly secrets set DEEPGRAM_API_KEY=your_key_here
fly deployThe fly.toml and Dockerfile are already configured for uvicorn on port 8080.
MIT — see LICENSE

