Listen Along at Scale Up With Atlas Application Services
Rate this article
Here at Scale Up, we value music a lot. We have a Google Home speaker at our office that gets a lot of use. Music gets us going and helps us express ourselves individually as well as an organization. With how important music is in our lives, an idea came to our minds: We wanted to share what we like to listen to. We made a Scale Up Spotify playlist that we share on our website and listen to quite often, but we wanted to take it one step further. We wanted a way for others to be able to see what we're currently listening to in the office, and to host that, we turned to Atlas Application Services.
Sources of music and ways to connect to the speaker are varied. Some people listen on YouTube, others on Spotify, some like to connect via a Cast feature that Google Home provides, and others just use Bluetooth connection to play the tunes. We sometimes use the voice features of Google Home and politely ask the speaker to put some music on.
All of this means that there's no easily available "one source of truth" for what's currently playing on the speaker. We could try to somehow connect to Spotify or Google Home's APIs to see what's being cast, but that doesn’t cover all the aforementioned cases—connecting via Bluetooth or streaming from YouTube. The only real source of truth is what our ears can actually hear.
That's what we ultimately landed on—trying to figure out what song is playing by actually listening to soundwaves coming out of the speaker. Thankfully, there are a lot of public APIs that can recognize songs based on a short audio sample. We decided to pick one that's pretty accurate when it comes to Polish music. In the end, it’s a big part of what we're listening to.
All of this has to run somewhere. The first thing that came to mind was to build this "listening device" by getting a Raspberry Pi with a microphone, but after going through my "old tech drawer"—let's face it, all of us techies have one—I found an old Nexus 5. After playing with some custom ROMs, I managed to run node.js applications there. If you think about it, it really is a perfect device for this use case. It has more than enough computing power, a built-in microphone, and a screen just in case you need to do a quick debug. I ended up writing a small program that takes a short audio sample every couple of minutes between 7:00 am and 5:00 pm and uses the API mentioned above to recognize the song.
The piece of information about what we're currently listening to is a good starting point, but in order to embed it on our website, we need to store it somewhere first. Here's where MongoDB's and Mongo Atlas' powers come into play. Setting up a cloud database was very easy. It took me less than five minutes. The free tier is more than enough for prototyping and simple use cases like this one, and if you end up needing more, you can always switch to a higher tier. I connected my application to a MongoDB Atlas instance using the MongoDB Node Driver.
Now that we have information about what's currently playing captured and safely stored in the MongoDB Atlas instance, there's only one piece of the puzzle missing: a way to retrieve the latest song from the database. Usually, this would require a separate application that we would have to develop, manage in the cloud, or provide a bare metal to run on, but here's the kicker: MongoDB has a way to do this easily with MongoDB Application Services. Application Services allows writing custom HTTP endpoints to retrieve or manipulate database data.
To create an endpoint like that, log in to your MongoDB Atlas Account. After creating a project, go to App Services at the top and then Create a New App. Name your app, click on Create App Service, and then on the left, you’ll see the HTTP Endpoints entry. After clicking Add Endpoint, select all the relevant settings.
The fetchsong function is a small JavaScript function that returns the latest song if the latest song had been played in the last 15 minutes and connected it to an HTTPS endpoint. Here it is in full glory:
1 exports = async function (request, response) { 2 const filter = {date: {$gt: new Date(new Date().getTime() - 15 * 60000)}}; 3 const projection = {artist: 1, title: 1, _id: 0}; 4 5 const songsCollection = context.services.get("mongodb-atlas") 6 .db("scaleup") 7 .collection("songs"); 8 const docs = await songsCollection 9 .find(filter, projection) 10 .sort({date: -1}) 11 .limit(1).toArray(); 12 13 const [latestSong] = docs; 14 response.setBody(latestSong); 15 };
And voilà! After embedding a JavaScript snippet on our website to read song data here’s the final outcome:
To see the results for yourself, visit https://scaleup.com.pl/en/#music. If you don't see anything, don’t worry—we work in the Central European Time Zone, so the office might be currently empty. :) Also, if you need to hire IT specialists here in Poland, don't hesitate to drop us a message. ;)
Huge thanks to John Page for being an inspiration to play with MongoDB's products and to write this article. The source code for the whole project is available on GitHub. :)