File size: 9,272 Bytes
0dc7ce9
 
 
 
 
 
 
 
 
 
 
 
 
8b80b7f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
---
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

<p align="center">
  <img src="product-media/product-image-1.jpeg" alt="Product Image 1" width="400"/>
  &nbsp;&nbsp;
  <img src="product-media/product-image-2.jpeg" alt="Product Image 2" width="400"/>
</p>

<p align="center"><em>ESP32 + INMP441 assembly housed in a custom 3D printed case</em></p>

### πŸŽ₯ 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/<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_HOST` in 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

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

---

## πŸ“„ License

This project is open source and available under the [MIT License](LICENSE).

---

<p align="center">
  Built with ❀️ using ESP32 · FastAPI · Deepgram · Gemini
</p>