--- license: mit tags: - esp32 - audio - speech-to-text - real-time - deepgram - gemini - fastapi - iot --- # ποΈ 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](product-media/product-demo.mp4) --- ## β¨ 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](https://railway.app) 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 1. Push this repository to GitHub 2. Go to [railway.app](https://railway.app) β **New Project** β **Deploy from GitHub Repo** 3. Railway auto-detects the `Procfile` and `runtime.txt` β no extra config needed 4. Note your deployed URL (e.g. `audio-transcriber.up.railway.app`) ### 2. Flash the ESP32 Firmware 1. Open `esp32_firmware/esp32_firmware.ino` in **Arduino IDE** 2. Install the required libraries via **Library Manager**: - `WiFiManager` by tzapu (β₯ 2.0) - `WebSockets` by Markus Sattler (β₯ 2.4) 3. Update `SERVER_HOST` in the sketch if your Railway URL differs: ```cpp const char* SERVER_HOST = "your-app-name.up.railway.app"; ``` 4. Select board: **ESP32 Dev Module** 5. Flash and open the Serial Monitor at **115200 baud** ### 3. Connect to WiFi 1. On first boot, the ESP32 creates a WiFi AP named **`Transcriber-Setup`** 2. Connect to it from your phone or laptop 3. Select your home WiFi network and enter the password 4. 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: 1. Press **Q** on your keyboard or click the **⬑ Ask Gemini** button 2. Gemini reads the buffered transcript and responds in a casual, conversational tone 3. The conversation supports **multi-turn context** β keep talking and asking 4. 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: ```python 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 ```bash # Clone the repo git clone https://github.com/Built with β€οΈ using ESP32 Β· FastAPI Β· Deepgram Β· Gemini