- ποΈ ESP32 Real-Time Audio Transcriber
ποΈ ESP32 Real-Time Audio Transcriber
A real-time speech-to-text system that captures audio from an ESP32 + INMP441 microphone, streams it to a cloud-hosted FastAPI server, transcribes it via Deepgram Nova-3, and generates conversational AI responses using Google Gemini 2.5 Flash β all viewable in a sleek live web dashboard.
πΈ Product Images
ESP32 + INMP441 assembly housed in a custom 3D printed case
π₯ Demo Video
βΆ Watch the product demo video
β¨ Features
- Real-time transcription β Live interim + final transcripts powered by Deepgram Nova-3
- AI conversation β Press Q or click Ask Gemini to get a conversational response from Gemini 2.5 Flash with multi-turn context
- WiFi captive portal β No hardcoded credentials; configure WiFi via phone/laptop on first boot
- One-click deploy β Server deploys to Railway with zero configuration
- Live status dashboard β Monitor WebSocket, Deepgram, ESP32, and Gemini connection states in real time
- Debug panel β Built-in debug log overlay for troubleshooting
ποΈ Architecture
βββββββββββββββ WSS (binary audio) ββββββββββββββββββββ WSS βββββββββββββ
β ESP32 + β βββββββββββββββββββββββββββββββΆ β FastAPI Server β βββββββββββββββΆ β Deepgram β
β INMP441 β β (Railway) β βββββββββββββββ β Nova-3 β
βββββββββββββββ β β transcripts βββββββββββββ
β β
β β REST βββββββββββββ
βββββββββββββββ WSS (text events) β β βββββββββββββββΆ β Gemini β
β Browser β βββββββββββββββββββββββββββββββ β β βββββββββββββββ β 2.5 Flashβ
β Dashboard β βββββββββββββββββββββββββββββββΆ ββββββββββββββββββββ AI response βββββββββββββ
βββββββββββββββ "PROCESS" / "CLEAR"
π Project Structure
audio_transcriber/
βββ server.py # FastAPI server (transcription + LLM + web UI)
βββ esp32_firmware/
β βββ esp32_firmware.ino # Arduino sketch for ESP32 + INMP441
βββ requirements.txt # Python dependencies
βββ Procfile # Railway process definition
βββ runtime.txt # Python version for Railway
βββ .gitignore # Ignored files (venv, cache, etc.)
βββ README.md # This file
π§ Hardware Requirements
| Component | Description |
|---|---|
| ESP32 Dev Board | Any ESP32-WROOM-32 based board |
| INMP441 | I2S MEMS microphone module |
| Jumper wires | 5 connections (see wiring below) |
| USB cable | For flashing and serial monitor |
Wiring Diagram
| ESP32 Pin | INMP441 Pin | Function |
|---|---|---|
GPIO 26 |
SCK |
Bit Clock |
GPIO 32 |
WS |
Word Select (LRCLK) |
GPIO 33 |
SD |
Serial Data Out |
3.3V |
VDD |
Power |
GND |
GND + L/R |
Ground (L/R β GND for left channel) |
π Getting Started
1. Deploy the Server to Railway
- Push this repository to GitHub
- Go to railway.app β New Project β Deploy from GitHub Repo
- Railway auto-detects the
Procfileandruntime.txtβ no extra config needed - Note your deployed URL (e.g.
audio-transcriber.up.railway.app)
2. Flash the ESP32 Firmware
- Open
esp32_firmware/esp32_firmware.inoin Arduino IDE - Install the required libraries via Library Manager:
WiFiManagerby tzapu (β₯ 2.0)WebSocketsby Markus Sattler (β₯ 2.4)
- Update
SERVER_HOSTin the sketch if your Railway URL differs:const char* SERVER_HOST = "your-app-name.up.railway.app"; - Select board: ESP32 Dev Module
- Flash and open the Serial Monitor at 115200 baud
3. Connect to WiFi
- On first boot, the ESP32 creates a WiFi AP named
Transcriber-Setup - Connect to it from your phone or laptop
- Select your home WiFi network and enter the password
- The ESP32 saves the credentials and auto-connects on subsequent boots
π‘ Reset WiFi: Hold the BOOT button (GPIO 0) while powering on to clear saved credentials.
4. View the Dashboard
Open your Railway URL in a browser:
https://audio-transcriber.up.railway.app
You'll see live transcription appear as the ESP32 streams audio.
π§ Using Gemini AI
Once transcription lines appear:
- Press Q on your keyboard or click the ⬑ Ask Gemini button
- Gemini reads the buffered transcript and responds in a casual, conversational tone
- The conversation supports multi-turn context β keep talking and asking
- Click Reset Chat to clear the conversation history
βοΈ Configuration
Server Environment
| Variable | Default | Description |
|---|---|---|
PORT |
8000 |
HTTP port (auto-set by Railway) |
API Keys
API keys are currently embedded in server.py. For production, move them to environment variables:
DEEPGRAM_API_KEY = os.environ.get("DEEPGRAM_API_KEY")
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
ESP32 Firmware
| Constant | Default | Description |
|---|---|---|
SERVER_HOST |
audio-transcriber.up.railway.app |
Railway domain |
SERVER_PORT |
443 |
HTTPS/WSS port |
WS_PATH |
/ws/audio |
WebSocket endpoint |
SAMPLE_RATE |
16000 |
Audio sample rate (Hz) |
I2S_READ_LEN |
256 |
Samples per I2S read cycle |
π οΈ Local Development
# Clone the repo
git clone https://github.com/<your-username>/audio_transcriber.git
cd audio_transcriber
# Create a virtual environment
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows
# Install dependencies
pip install -r requirements.txt
# Run the server locally
python server.py
# β Server starts at http://localhost:8000
Update
SERVER_HOSTin the ESP32 sketch to your local IP for local testing.
π¦ Dependencies
Python (Server)
| Package | Purpose |
|---|---|
fastapi |
Async web framework & WebSocket handling |
uvicorn |
ASGI server |
websockets |
Async WebSocket client for Deepgram |
langchain-google-genai |
LangChain integration for Gemini |
Arduino (ESP32)
| Library | Purpose |
|---|---|
WiFiManager |
Captive portal for WiFi provisioning |
WebSockets |
WebSocket client with SSL support |
π API Endpoints
| Endpoint | Type | Description |
|---|---|---|
GET / |
HTTP | Serves the live transcription dashboard |
WS /ws |
WebSocket | Browser β Server (transcripts + LLM events) |
WS /ws/audio |
WebSocket | ESP32 β Server (raw 16-bit PCM audio) |
Browser WebSocket Messages
| Direction | Message | Description |
|---|---|---|
| Browser β Server | PROCESS |
Trigger Gemini on buffered transcript |
| Browser β Server | CLEAR_HISTORY |
Reset conversation history |
| Server β Browser | __FINAL__:<text> |
Final transcript line |
| Server β Browser | __INTERIM__:<text> |
Interim (partial) transcript |
| Server β Browser | __LLM_START__ |
Gemini processing started |
| Server β Browser | __LLM_TOKEN__:<text> |
Gemini response text |
| Server β Browser | __LLM_DONE__ |
Gemini processing complete |
| Server β Browser | __LLM_ERROR__:<msg> |
Gemini error message |
| Server β Browser | __STATUS__:<state> |
Connection state change |
π€ Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
π License
This project is open source and available under the MIT License.
Built with β€οΈ using ESP32 Β· FastAPI Β· Deepgram Β· Gemini