Jon Ashcroft

I made a ‘Now Playing’ screen with Spotify, Raspberry Pi, and ES6

7th June, 2018

Two things that I’ve wanted to do for a while was to have a cool Raspberry Pi project and to play with the Spotify API. So why not combine them both? I’m pretty sure this has been done 1000 times before, but sometimes it’s fun to build things from scratch, y’know?

This post will be a brief outlining of the process (with a link to it’s GitHub at the bottom).

Things used:

Hardware

Buying the screen was by far the most difficult part of this project simply because there’s such a mixed bag of reviews and products out there. The Pi community seems to mostly favour screens below 3.5 inches, so solid reviews for any (touch) screens above 5 inches were far and few between. I think I ended up scouring through threads on /r/raspberry_pi before landing on the Waveshare screen.

The screen didn’t immediately work with the Pi, which is normal. I had to connect a spare 22′ monitor and edit /boot/config.txt to allow the Waveshare screen to both display and respond to touch events (instructions are on the Waveshare link above).

So far, the screen has held up well. The colour and clarity is great for its price range and touch is fairly responsive, though does take some time to calibrate. Would definitely recommend!

I’m running this on a Raspberry Pi with Raspbian installed. Nothing really worth mentioning here!

Building the app

This was actually really fun to make for two reasons:

Spotify API

The API for Spotify is genuinely a pleasure to use, it supplies a surprising amount of endpoints. The endpoint that I’m using to capture Spotify’s state is user-read-currently-playing.

I opted against using one of the many wrappers that Spotify recommend because I wanted to learn the process from start to finish (even though it would have been quicker to use a wrapper). Unsurprisingly, the most difficult part was the OAuth flow.

Another fun issue I faced was making it as real-time as possible. The API includes an is_playing parameter which returns either true or false – so on initial load, the app grabs the data from Spotify with fetch and stores the unique track ID in localStorage. Then setInterval is used to fetch data every 3.8 seconds, where the track ID from Spotify is compared to the locally stored track ID, and the page is only refreshed if they’re different.

To be honest, I’m not overly thrilled with polling the server every 3.8 seconds, but without WebSockets, this is the cleanest solution I came up with. Maybe down the line I’ll venture into WebSockets, but for now I’ll just keep on eye on the rate limiting.

ES6

So this project was really my first exposure to an ES6 project, which is another reason why I didn’t want to use a wrapper. I actually originally wrote the whole thing in ES5, and then rewrote it entirely in ES6. I’ll be the first to say that the code isn’t perfect, but as a whole, I’m very proud of it for being my first full ES6 driven project.

Front end

The Raspberry Pi can be a powerful device, but I became very aware of its hardware limitations. Originally, I had captured a gradient of colours from the artwork and animated them using CSS in a water-like state. When the track would change, as would the gradient – but that was pretty laggy. Luckily, there’s the useful node-vibrant package (also used in the footer below) – which will grab a dominant colour and apply it as the background.

Connecting the two

At this point, I realised I had to connect the monitor and photo frame. The frame took ages to find, because there wouldn’t be an off-the-shelf photo frame that would perfectly fit the 16:9 monitor. I specifically wanted a frame that included a border so that the edges of the monitor would be hidden from sight. As is, the frame slightly crops the monitor, but I don’t think it’s too much of a sacrifice.

Now, arts & crafts is totally not my thing, so the monitor is literally taped to the back of the frame. It’s really, really not pretty, but hey – nobody is gonna be looking at the back of this thing.

Something I totally didn’t take into consideration is that the depth of a Pi mounted to a screen, mounted to a photo frame is bigger than I expected.. so any expectations of hanging this on the wall went out of the window – luckily, the idea of buying a novelty easel came into my head – I’m actually happier with that aesthetic than if it was on the wall.

I really wanted this to be a ‘set it and forget it’ scenario – and it is. all I have to do is power up the Pi and Raspbian will immediately open Chromium in kiosk mode. I was able to do this by SSHing into the Pi and editing the startup configuration file:

sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart

Entering some settings to auto-boot to Chromium….

@xset s off # disable the screensaver
@xset -dpms # disable energy saving features
@xset s noblank # ensure screen doesn't go blank
@chromium-browser --kiosk https://*YOUR-URL-HERE* # open up chromium to specific web page

The neat thing about Chromium is that you can boot it with flags, --kiosk will boot Chromium without the address bar. It turns out that there are a shit load of flags that I want to play with (remote debugging caught my eye).

I just have turn on the Pi, press the ‘Connect with Spotify’ button, and away we go!

To conclude

Overall, I am very happy with how this turned out. I’m happy with the code, the frame I found was near perfect – and this was just a fun little project to that I enjoyed doing. Things just seemed to work out well and now I have this nice little digital photo frame visualising the music around me. I do definitely want to explore the Spotify API some more and see what more data I can dive into.

The one thing I do really like about this setup is that if I ever get bored of having ‘Now Playing’, I can just build something new to display on this screen…

Use it:
https://jonashcroft.co.uk/nowify

GitHub:
https://github.com/jonashcroft/Nowify