Hi everyone! I hope all of you enjoyed the holiday season and had fun during your break.

I wanted to write a small essay to describe the research I did since we last saw each other and the next steps I wanted to take with the project.

The Goal

We want to build a user-based service that allows any one user to share their music, live, with everyone else who wants to listen in.

We plan to do this by using the Spotify API and various other Web technologies to provide a cohesive, cross platform solution. We would eventually monetize this service and use it as an income generator for the club.

Variations of such an idea have already been suggested in the Spotify community forums:

With thousands of people upvoting these suggestions, it seems that the market wants something like NowPlaying.

The Name

We will call this service NowPlaying. Personally I still don't think it's a good fit for us, but while it's in development the name isn't that important. What is important is to have a name that adequately reflects the primary adjectives we want to associate with our service:

If anyone has any better suggestions for a name, I'm open to hearing them.

The Spotify APIs

There's actually a bunch of them. I've compiled a list of the ones we would care about the most. Some are in beta, meaning they'll be changing around and it may not be a great idea to base a product on top of them until they've left beta stage.

...And that brings us to the latest addition to the lineup: App Remote SDK.

Earlier this year, we released beta versions of the App Remote SDK for iOS and Android. Unlike our previous playback SDKs, the Android and iOS SDK now allow you to “remote control” playback in the Spotify app. As a result, you can control playback for all users (not just Premium) and provide offline playback.

Also as of this release, the iOS SDK is out of beta. This means that we consider it to be stable, and able to be used confidently in your integrations.

The Android SDK remains in beta, and we will provide updates on this blog.

Note that these [Android and iOS] streaming SDKs are not actively maintained and no additional work on these are planned. We therefore urge you to work with the new SDKs going forward.

This is a big deal. With the old mobile SDKs gone, App Remote is what we'll have to use if we ever want to deliver native apps.

Which API For Us?

We wanted NowPlaying to be cross platform - to work on both desktop and mobile devices. We wanted to do this using their Web Playback API. But there are some big problems:

So, Web Playback is out. What about Web/Spotify Connect?

It allows us to remote control the native app on desktop and mobile. And indeed, we could implement all of NowPlaying using a web app and the Connect API. But.

Why not rate limiting?

Just a quick primer for those who are unfamiliar. As you are probably aware, computing is a finite resource, and companies like Spotify have to build or rent massive data centers to process all the requests they get every second. To prevent their services from failing due to overuse, Spotify implements per-second request rate limiting. This means, as a user of the Spotify Web API, you can only send X requests per second before Spotify will block your request and refuse to execute it. When this happens, you're given a Retry-After header, which contains the amount of seconds you need to wait before Spotify will accept requests from your application again. During this duration, you cannot use the Spotify Web API at all.

I tried finding more concrete details on the limits, but it seems like they're prone to changing and undocumented. The guy in that post said to expect something like 10-20 requests / second, which at first glance seems like a lot, but when you do the math, it wouldn't work for us.

Let's assume the rate limit is set to 20 requests a second. That's 1,200 requests a minute, or 72,000 an hour, which is huge. But it's not enough for NowPlaying.

This is because NowPlaying implements live streaming. That is, for every little change you make in your Spotify app, every single one of your followers also need to have that change performed to their Spotify app. This requires at minimum one request per user.

We only get 20 requests a second. If any single person on our platform gains more than 20 followers at a time (or if more than 20 people stream at the same time that have at least one follower), we can no longer keep their followers in sync with the streamer. We would get rate limited every time they changed anything. Obviously, that's not acceptable.

The limit can apparently be lifted but I have never heard of anyone who has successfully done so, or if doing so would require entering a contract with Spotify or paying them royalties. I found this post where a Spotify employee tells the poster to contact Spotify legal, but no information on if that would cost anything.

We're not the only ones who have to deal with this problem. One of the most popular requests in Spotify's issue tracker is a way to receive real time player updates without having to poll the Player endpoint (each poll attempt would use up a request, and we'd have to poll it at a frequency that seems akin to real time). Discord seems to have a private, custom solution built for them, but I doubt that deal was done for free.

Regardless, even if we got realtime updates, it still wouldn't solve the problem of us having to update every follower's player in real time.

So, with Web Playback and Web/Spotify Connect out, that leaves us with the mobile SDKs. And with the old iOS and Android SDKs now being unsupported, that leaves us with...App Remote.

We're Using App Remote

And with that, abandoning our plans of building a web app. App Remote is a native-only solution, so we can only use it on iOS and Android.

I wish there was an easy way to make this work on Web, but until the Web Playback SDK comes through or the rate limiting situation is drastically changed (both of which I highly doubt), this is what we have to deal with.

So now we have to build mobile apps. This is obviously a huge change in the direction of the project, which is why I wanted to write up this letter and distribute it to you all before our first meeting.

Here's how I see it working.

WebSockets

This part is necessary just so you understand the next section.

Typically the way computers communicate on the Web is through a protocol called HTTP. It's based on a request/response architecture, meaning that you send a request, and the server sends back a response. You can think of this as talking to Siri. When you ask Siri a question, she'll give you an answer, but Siri would never pop up on your phone unprompted and ask you a question or let you know of a new event that happened. This architecture is great for requesting documents like the Web was originally meant for, but terrible for building interactive apps since there's no way to allow for bidirectional communcation.

WebSockets is a Web standard that allows real time communication between various devices. These devices can be Web browsers, mobile phones, laptops, desktops, etc. You can think of WebSockets as texting, for computers. It's how they can have conversations with each other.

App Remote & Us

NowPlaying would be its own app that uses the App Remote SDK to talk to the Spotify app on the user's phone. When NowPlaying is opened, it establishes a WebSocket connection to our NowPlaying service and also a separate connection to the Spotify app. From here, updating player states between multiple devices is easy: just send a message to the WebSocket connection each device maintains with our service, and have the NowPlaying app forward that message to the App Remote SDK.

Here's a visualization of what a typical NowPlaying session could look like between 10 devices, where one device is streaming and the others are following.

NowPlaying App (Device 1) -> NowPlaying Service: Hello. I represent Spotify user <whoever is logged into Spotify on that device>.

NowPlaying App (Device 1) -> App Remote SDK -> Spotify App: What song are we playing right now?

Spotify App -> App Remote SDK -> NowPlaying App (Device 1): We're playing "Thank You For The Music" by ABBA, currently at 0:38.

NowPlaying App (Device 1) -> NowPlaying Service: I want to stream now. I'm streaming "Thank You For The Music" by ABBA, currently at 0:38.

NowPlaying App (Devices 2...10) -> NowPlaying Service: I want to follow Device 1!

NowPlaying Service -> NowPlaying App (Devices 2..10): Okay! Device 1 is currently streaming "Thank You For The Music" by ABBA, currently at 0:38.

NowPlaying App (Devices 2..10) -> App Remote SDK -> Spotify App: Play "Thank You For The Music" by ABBA, starting from 0:38.

...And if the user on Device 1 changes something in the Spotify app, say they skip ahead:

Spotify App -> App Remote SDK -> NowPlaying App (Device 1): Heads up. The user changed the player state. We're now playing "Thank You For The Music" by ABBA at 1:12, not 0:38 anymore.

NowPlaying App (Device 1) -> NowPlaying Service: Hey. I'm changing my stream. I'm streaming "Thank You For The Music" by ABBA at 1:12 now.

NowPlaying Service -> NowPlaying App (Devices 2..10): Device 1 is changing their stream. They're going to play "Thank You For The Music" by ABBA at 1:12 now.

NowPlaying App (Devices 2..10) -> App Remote SDK -> Spotify App: Change of plans. Play "Thank You For The Music" by ABBA at 1:12 now.

Because we're not directly touching Spotify's services, there is no rate limit. This is infinitely scalable, and we don't need to pay Spotify anything to use the App Remote SDK or WebSockets between our own private apps.

Hosting The WebSocket Server

There are a variety of ways to do this but I am leaning towards AWS API Gateway which just recently came out with WS support. API Gateway has no servers involved, which reduces the complexity of running our service by a huge magnitude. We pay for connection minutes (number of minutes each client is connected) and total number of requests. You can look at the pricing tab for more information, but the basic gist is that we pay $1 per million requests and $0.25 per million connection minutes. I just used API Gateway to implement live chat on my own personal website, so I now have enough experience to figure out how to make it work for NowPlaying as well.

Building The Mobile App

Again, various ways we could do this, but I am leaning towards React Native. RN is a cross platform mobile development framework for iOS and Android that allows you to write apps in JavaScript. It is supported by Facebook and used in their FB Market and Messenger apps as well as the Facebook app itself.

It's important to know that the App Remote SDK itself only works fully on iOS. The Android counterpart is in beta, meaning it's being actively developed, but will take a bit to reach a stable stage.

There is one more barrier stopping us: the App Remote SDK is written in Objective-C, while RN uses JavaScript. To get these to play together, we have to use a native module bridge.

When I set out to build NowPlaying over break, I realized I would have to build that bridge myself. And while I broke some ground to try to get the two frameworks co-operating, I soon found react-native-spotify which appears to be a more complete, community driven Spotify API implementation. Right now it conforms to the old streaming SDK so it's not immediately useful to us but work is underway to get it up to date with the new App Remote SDK.

Once this project is complete within the next few weeks, we will have everything required to implement NowPlaying in a simple, straightforward, scalable, and long lasting manner.

Conclusion

NowPlaying is switching from a Web app to a mobile app. This not only allows us to leverage the App Remote SDK, avoid rate limiting, and provide a real, truly live experience, but it opens up the possibility of using other technologies in the future, such as push notifications and geolocation tracking.

We are going to use AWS API Gateway to offer a WebSocket service to connect our various clients together and build the business logic that makes NowPlaying possible.

Our clients will be React Native applications that use the Spotify App Remote SDK to talk to the Spotify app on each user's device. They'll connect to the WebSocket service to receive orders and allow us to remote control Spotify.

We are waiting on the react-native-spotify package to finish adding the App Remote SDK before starting development on the mobile app. Once that package implements App Remote, we can finally break ground and bring the idea to reality.

This is the plan as I see it. Of course I'd love to gather feedback from you all to decide how to proceed. Once again, I hope you had a great break and I look forward to discussing this in person at our next meeting.

Andi


Tagged #school.


Want more where that came from? Sign up to the newsletter!



Powered by Buttondown.