Project progressBuild log

Type Text in a Browser, Hear It from an ESP32 Speaker: Testing a Local TTS Playback Pipeline

I moved the ESP32-S3 from playing audio embedded in firmware to speaking text entered dynamically in a browser. This article documents the working path from the web UI through local TTS and a task queue to the ESP32, MAX98357A, and speaker—and clearly marks the voice-input work that remains.

This log belongs to the project: ESP32-S3 AI Voice Conversation Prototype

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.

StageResponsibilityResult this time
Web pageEnter text and create a playback requestSubmission verified
Mac local serviceCall TTS, save MP3, create taskAudio generated
LAN task interfaceLet the device claim tasks and report statusTask lifecycle completed
ESP32-S3Download MP3, verify, decode, and output audioProcessed 5 tasks consecutively
MAX98357A and speakerConvert I²S digital audio into an output that can drive a speakerSpoken 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

  1. The web page submits the entered text to the local FastAPI service.

  2. 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.

  3. The ESP32-S3 polls the service over Wi-Fi and claims queued tasks.

  4. The device downloads the MP3 and places the audio into PSRAM.

  5. The firmware decodes the MP3 and writes the PCM data to I²S.

  6. The MAX98357A drives the speaker, and the device reports downloaded, playing, and completed in 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.

CONTINUE READING

More build notes connected by the same project, parts, or problem-solving path.