My son and I built an NFC-based music player so he can play the music he wants, develop his own musical taste but most of all so that he and I could have something fun to build together.
Kind of like a modern day record player, but infinitely more extensible, and with each album costing 1/100th the price of a vinyl record.
Here it is in action (music starts 9 seconds into the video, set your volume to low):
And here’s how we built it:
- Amazon Echo Dot, $20: For the price, this is a surprisingly hackable, portable speaker. I would have prefered something without any microphones at all, but I mostly trust the hardware mute switch.
- Case, $20: Beautiful retro-style case for the Raspberry Pi. The top compartment is made to house a fan, but this is where I put the NFC module instead. The folks who make this at C4 Labs were super nice. We broke a piece when we started building the box and they sent a replacement part right away.
- Raspberry Pi, $35: I chose to go with a Raspberry Pi because they’re cheap, have good compatible NFC modules, lots of case options on Etsy and easy to develop on.
- NFC Module, $5: I can’t believe this thing is just $5. Works great. Lots of good tutorials on connecting this to a Raspberry Pi.
- NFC Cards, $29: I got 100 cards at $0.29 each.
In total, this adds up to $109, but in my case I already had a Raspberry Pi and an Echo Dot lying around that I could repurpose for this, so it cost me closer to $55.
I’m already an Apple Music subscriber, so using that as the music source was the cheapest solution, although this setup would work with any music service that works with Amazon Echo: Spotify, Amazon Music, TuneIn, CloudPlayer, Deezer, iHeartRadio.
In the exploration phase for this project, I wanted to buy DRM-free music, wire a speaker directly to the Raspberry Pi and play it locally. However, that would have meant that adding music later would be a much more tedious task. Plus it’s hard to find DRM-free music these days, and when you do find what you want it ends up being pricey. Especially compared to the convenience and cost of today’s streaming options.
I also explored using HomePods as the speakers (see addendum below).
The biggest downside to the current streaming approach is that there’s a 5-10 second delay after tapping a card and music starting.
I assembled this with my son over a few days in May 2020, and then finished the setup in September 2021. The actual hardware assembly probably only took a combined total of 3 hours though.
Disclaimer: This code is rough, it’s suitable for a toy project. I’m sharing it in case it’s useful for others getting started with a similar, project. I’m not claiming this is beautiful quality code.
Echo Dot Remote Control
I use the alexa-remote-control shell script to control the Echo Dot. When it’s up and running, it couldn’t be easier:
1 2 3 4
I use MFRC522-python to interface with the NFC module.
The Python script that reads cards and plays music looks like this:
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
You’ll notice that there are special cards for pausing, setting a high volume and setting a low volume. The rest of the cards map to music.
The main thing I’d like to improve at some point is to avoid hardcoding a mapping of the card UIDs to music and instead program it using the companion iPhone app by writing a payload to the card. The iOS side I know how to do pretty quickly, but I’d have to spend more time to figure out how to do it on the MFRC522 reader side of things.
There’s an API server that can be used to control the music box using the companion iPhone app.
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
Of course I made an iPhone app using SwiftUI & Composable Architecture.
This helps me quickly adjust the volume, play/pause and play specific music. If my kid falls alseep to music, I can stop it without having to walk into his room.
Siri intents work too, so I can play/pause music by speaking to Siri without having to launch the app.
Hopefully this post is helpful to someone interested in building something similar. I’ve posted enough code and details to get you started, but I won’t be open sourcing the whole project because I’m just not willing to field support questions or feature requests. I’m happy to answer questions about my experience building this, but I’m sorry I can’t help you figure out why something’s not working if you go build something similar.
Addendum: HomePod Attempt
At one point I wanted to use a stereo pair of HomePods for this project, but all my attempts to reverse engineer a way to play music on them from a Raspberry Pi were fruitless. I tried sniffing the network traffic via Charles Proxy while playing music from the iOS Music app or even the Shortcuts app and wasn’t able to crack it. I did end up getting it working using forked-daap but this set the HomePods in a weird state. I don’t remember all the details because I gave up on that approach for two reasons: the first is that I couldn’t get it to work well and the second is that I wanted to keep the HomePods in our living room while the music box was meant to be in my son’s bedroom.