The ESP32 is an incredibly versatile microcontroller, and so long as you have the wires and the hardware to connect it to, you can do practically anything with it. I built an LED matrix display with an ESP32 and a Waveshare 64x32 panel a few weeks ago, and now I've turned it into a device that can show what is playing at any given time.
There's a twist, though: I'm not just pulling a "now playing" sensor from Spotify, I'm identifying the track that I'm currently playing on my record player. This uses a combination of a microphone placed on my speaker, Shazam, and an MQTT server to publish results to for displaying on the screen. The end result is an easy way for anyone in my home to see what song is currently playing on my record player, without needing to ask.
Setting up Shazam
There's a great Python library for this

Before getting into the hardware side of things, we need a way to identify the tracks that are currently playing. There's a reverse-engineered Shazam API called "Shazamio" that we can use for this, as it uses the same official endpoints that the official apps use to identify a playing track. We can invoke this in Python, pulling audio from our microphone, and forward this to an MQTT server.
I once used the Shazamio library a long time ago, so I was able to repurpose my old code for a lot of this, reporting the data to an MQTT broker instead. I use MQTT for a lot of my self-hosted services, including for Zigbee2MQTT, so it was trivial to point it to my broker for reporting track data. I send basically everything, and a sample report to my MQTT server looks like this:
{
"event": "now_playing",
"timestamp_utc": "2025-08-20T15:54:18.424651+00:00",
"track": {
"title": "Ocean Breathes Salty",
"artist": "Modest Mouse",
"album": "Good News for People Who Love Bad News",
"released": "2004",
"url": "https://www.shazam.com/track/40298344/ocean-breathes-salty",
"cover": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/f9/02/da/f902dad6-7a7e-203a-5648-78e67d42b515/mzi.fcuuybmm.jpg/400x400cc.jpg",
"key": "40298344",
"isrc": "USSM10315495"
},
"track_id": "40298344",
"source": "microphone/shazam"
With this, we could even process the cover art if we wanted to dynamically pick colors for text. It's trivial to pull that data from the Shazam API response, meaning we can easily identify a track and then submit the data for showing on a display beside the record player.

Privacy is something that I put a lot of thought into when developing this, but there aren't many alternatives. The best I could come up with was putting the microphone right on the speaker, as the audio being so loud relative to the microphone's placement will drown out anything else in the room. I have a theoretical solution to safeguard this as much as possible when it comes to privacy and safeguarding against rate limiting, though it's not in place yet.
Currently, I poll every ten seconds for the currently playing track. When it comes to a record player, you could pull the length of the song and then not start polling again until it's nearly over. You won't be skipping songs anyway, so we can just wait out the length of the song between polls, meaning a minimal amount of audio data gets sent while still managing robust music identification.
There is a problem with this, though, and it's why I didn't implement it. Shazam won't be perfect when it comes to identifying the music that's playing, and it sometimes makes mistakes. See the text below, taken from the above screenshot:
[info] Published: Modest Mouse — Satin In A Coffin
[info] Published: Helicalin — Self-Resonance (Version 2)
[info] Published: Modest Mouse — Satin In A Coffin
If Shazam identifies the wrong song, that means it won't get an accurate reading of whatever song is playing. I could theoretically hook up a button to the ESP32 to force a song re-check if I know it's wrong by communicating with the MQTT broker, but that also introduces additional complexity. In that scenario, the listener service I've developed could then poll the MQTT broker for that message, and if it exists, recheck the song. It's a bit overengineered, but it's the nature of trying to read data like this from an analog data source.
Right now, the best solution that I have is a check every ten seconds, but I'll put some time into thinking of better ways to do it. For now, it works, so let's move on to our ESP32.
Setting up our ESP32 and finishing the project
Pulling from MQTT is easy

We've talked at length about the ESP32 and the Waveshare display already, but the short version of the story is that the ESP32's Direct Memory Access (DMA) capabilities allow it to work perfectly with our display. You won't be chaining many of them together, but for a single one, it's perfect. I chose to develop this in ESPHome, using the external component wrapper for the HUB75 DMA library.
From here, it works just like you'd expect when it comes to ESPHome. Declare an MQTT connection in ESPHome, pull from the expected topic, and save it to a text sensor for later usage. We start this using the following:
mqtt:
broker: 192.168.1.x
on_json_message:
- topic: media/now_playing
Thanks to the MQTT function in ESPHome, we can just save the text to a text sensor whenever a new message is sent to the topic that we're monitoring. Turning it from a text sensor into usable information isn't so straightforward, as we need to split or scroll the text based on the width of the display and the length of the text. I've written the code to handle the text splitting and scrolling logic. If you need to, you can change the variables for a longer (or shorter) panel without needing to modify any of the underlying logic. It should be pretty modular, and you can check it out on GitHub.

That's it, though! Once the code is compiled and flashed to your ESP32, you can set everything up, run your identification server, and submit identified tracks to the MQTT server so that the ESP32 can display them on the Waveshare screen. Your guests can now see a digital representation of the currently playing track on your record player, despite the analog nature of vinyl, and without any invasive modification of the player required, either.
A word of caution for deploying software to the ESP32. I highly recommend flashing the ESP32 close to your access point, or without being wired up to the Waveshare display, first. This is because the display seems to cause interference in wireless connectivity with the ESP32. It'll work fine for reading from an MQTT server, but wireless updates using ESPHome are incredibly slow in a lot of situations.
0 comments:
Ikutan Komentar