Wouldn’t if be great if all you had to do to add a song to your Spotify is smack a big red button when you hear a song you like? Then you can listen to it again later!
Motivation
It happens all too often when I have people over that there is a song playing on Spotify that I really like. In that moment it would be nice (and probably a lot of fun) to be able to smack a button on the table which instantly saves that song to a playlist. I have also been looking for an opportunity to write some backend Javascript in NodeJS and dockerize a NodeJS application server. This project presents the perfect opportunity to try these things out.
Requirements
Hardware
- Small box (~10cm by 10cm) with large (>60mm emergency buzzer button)
- (probably) Small OLED screen to display song name and artist
- (possibly) Battery operated
- (optional) LED Matrix display for showing the currently playing song name and artist
Software
Backend
- NodeJS backend serivce written in Express1
- Communicate with Spotify API to fetch song information
- Keep track of “buzzed” songs by adding them to a playlist.
- Respond to “button pressed” events by adding currently playing song to a playlist.
- Send a websocket or MQTT message2 at the beginning of a new song to update the LED display.
Button Firmware
- Send a simple “button pressed” API request to Express backend
- provide visual feedback to show button press has been registered
- Open a websocket or MQTT connection to backend and listen for song change messages and update the LED display when a message is received.
Backend Features
I got a little carried away with the backend and came up with a web interface with the following features (in development):
Unfortunately, I developed this with the assumption that the Spotify API would allow adding new songs to the play queue. This is not possible yet but the feature seems to be in development. {: .info }
Auto DJ
Specify one or more playlists on your Spotify account and Auto DJ will add a song from those playlist every couple of songs. This is useful for adding the occasional “sing along” songs to the mix. Just create a playlist with sing-along songs and Auto DJ will automatically insert those songs into the mix at bearable intervals without duplicates!
Party Mode
Enter other Spotify usernames and let your friends add a playlist of their own to the mix! The server keeps track of played songs to ensure there are no duplicates. Keeps everyone happy whilst minimizing the amount of time spent selecting music. Plus, if you hear a song you like smack that button and it is added to a public playlist accessible to everyone.
Normal Distribution Player
Kind of like intelligent shuffle. The randomness of this shuffle mode is based on a normal distribution. We start by sorting the playlist by new to old songs. You can then specify the mean and variance of the normal distribution curve. For example, if you want to hear predominantly songs that you recently discovered then you would place the mean nearer to 100%. Say there are 100 songs in your playlist sorted from old to new. Using the normal distrution as input, we can generate a series of numbers clustered around the mean of, say, 80 percent. The next song played is determined by the output of the normal distribution. Say the output is 75, in this case we play a song in position 75/100. Any played songs are removed from the list. So the next song played will be X% along a scale of 1 to 99, where X is the next number generated by the normal distribution. The benefit of the normal distribution is that you won’t be bombarded with all the latest songs (making you despise them after a while). The normal distribution will add in the occasional “olderish” song into the mix, while playing mostly new material.
How well this will work in practise will be discovered later.
Implementation
Some photos and a video showing the prototype:
Some photos of the NodeMCU breadboard prototype with 1 led and a small red button.
Maker:0x4c,Date:2017-10-1,Ver:4,Lens:Kan03,Act:Lar01,E-ve
The video above shows the following steps:
- Red button is pressed
- Arduino makes GET web request to
/recents/save
to save the currenlty playing song. - Server handled GET request, retrieves currently playing song, saves it to playlist.
- Server returns song info and custom message back to client. (The custom messages are inside jokes among my friends)
- The request returns song information as well as a random message.
- Arduino prints those to serial console (prototype does not include OLED screen) and flashes LED to indicate success.
- The banger button is pressed again for the same song (whether thats by accident or deliberately).
- The server returns 304 (HTTP status code for “no change/duplicate”) along with song information and a message to display. The song is not logged again as it has already been marked a “banger” (a great song).
Here is the Arduino console output:
Connecting to ***
..............
WiFi connected
IP address:
10.1.1.69
Attempting MQTT connection...connected
making GET request
Status code: 200
{"status":200,"message":"Whatta tune."}
Whatta tune.
Mi Gente
J Balvin
Attempting MQTT connection...connected
making GET request
Status code: 200
{"status":304,"message":"Duplicate, but we'll let it slide."}
Duplicate, but we'll let it slide.
Mi Gente
J Balvin
Attempting MQTT connection...connected
Installation
The NodeJS backend is mostly completed and you can install it by cloning the repository or starting the Docker container. Access it by going to localhost:3000
. You need to authenticate with your Spotify account first by clicking on the Login menu option.
docker run -d -p 3000:3000 danobot/spotify-button
Footnotes
Express for no particular reason other than it seems popular and lightweight. I had a look at some API route examples and it seems to be just what I am looking for. ↩
Depends if I can be bothered implementing a websocket. An MQTT implementation would probably be simpler because the nature of the protocol implies pushing data messages into the network and then forgetting about them. It is not mission critical that the receiver acknowledges the receipt of new data. A websocket allows two way communication through a dedicated connection between the browser and server. ↩