Before this, I had already made the ESP32-S3 play three test tones through a MAX98357A and a 4Ω/3W speaker. But those three tones only proved that the wiring and basic audio output worked; the device still could not receive new content to speak.
This time, I can type a new sentence into a browser on my computer, click Send, and hear it through the speaker—without changing or reflashing the ESP32 firmware.
Chocolate got into a fight with a tomato—and won. Why? Because it was a chocolate bar. (In Chinese, “棒” means both “bar” and “great.”)
This is a piece of text I actually used for testing.
This time I built a dynamic pipeline, not just a fixed recording
If an MP3 clip is embedded in the firmware, every content change requires recompiling and reflashing. The browser-based approach separates the device program from the content it speaks: the ESP32 firmware continues to handle networking, task retrieval, and playback, while the web page accepts text that can change at any time.
| Stage | Responsibility | Result this time |
|---|---|---|
| Web page | Enter text and create a playback request | Submission verified |
| Mac local service | Call TTS, save MP3, create task | Audio generated |
| LAN task interface | Let the device claim tasks and report status | Task lifecycle completed |
| ESP32-S3 | Download MP3, verify, decode, and output audio | Processed 5 tasks consecutively |
| MAX98357A and speaker | Convert I²S digital audio into an output that can drive a speaker | Spoken output heard in person |
Espressif’s Arduino-ESP32 I²S documentation states that I²S uses bit clock, word select, and data lines to transmit PCM audio; in this project, these correspond to BCLK→GPIO16, LRC→GPIO17, DIN→GPIO18. After the ESP32 decodes the MP3, it sends the audio to the MAX98357A through these three signal lines.
What the device actually does after a web page click
-
The web page submits the entered text to the local FastAPI service.
-
The service calls the TTS provider in use at the time to generate an MP3 and saves the audio as a task the device can claim.
-
The ESP32-S3 polls the service over Wi-Fi and claims queued tasks.
-
The device downloads the MP3 and places the audio into PSRAM.
-
The firmware decodes the MP3 and writes the PCM data to I²S.
-
The MAX98357A drives the speaker, and the device reports
downloaded,playing, andcompletedin sequence.
All five tasks originally queued in the server database eventually reached completed, and each task had downloaded, playing, and completed events. The ESP32 serial console printed playback complete for each task, and I confirmed that the speaker played the speech clips consecutively. The number five is the measured count from this end-to-end task lifecycle. The available records do not prove that the joke above was one of those five tasks, so I have kept the two pieces of evidence separate.
Why this step is more important than playing a fixed MP3
For me, its most direct significance is that I can control what the ESP32 says from the web page, without having to reflash the code every time I change a sentence.
This also opens up the next step. If microphone input can later pass through speech recognition and AI generation, the reply can be handed to this playback pipeline to form a real voice conversation. The browser is not the final interaction method, but it independently proves how dynamic content can reach the speaker.
Current conclusion
This test moved the ESP32 from playing fixed content stored in firmware to receiving dynamic text from a browser and speaking it through a local prototype. Hardware output, network tasks, and real sound now form an end-to-end loop. The next step is to let the device hear what I say and connect that input path to the playback pipeline.