music collab

hiatus over

So… winter break is over and now time to get back to the swing of things and the realization that I can’t just sit around and do what I want for weeks at a time.

I managed to actually work on this tons over break. I started with some design and that got the ideas going and things just started to click. I did a lot of reading on nodejs and how I should set things up to have an effective web server along with delivering the data needed for the app to work. I am using express to deliver content and data to the client. I set up some different paths as get/post responders so that the same server can act as an API too (e.g. a POST to /user/playlist will update a users playlist while a GET to /user/playlist will get the current authenticated users playlist). Below I am going to outline some of the main areas I worked on and the current status of them.

Users

I have created a basic registration process (just to create users for testing) but no validation is currently in place. To access the main portion of the site I am making it mandatory to be logged in, again to make it easier for testing. Once authenticated, you can search for songs (complete with a suggestion-esque functionality) and modify your playlist.

Playlist

Currently there are several functions you can do with your playlist. When searching for songs, you can add any song to your playlist. You can then reorder your playlist (using jQuery UI’s sortable functionality) and delete items from your playlist. Right now, clicking the play button will play the first song in your playlist.

TODO

The next step I am looking into is the room aspect – where a user will hit play and this will start their room and allow other users to listen along at the same time (the whole point of this project…). I have some ideas behind this but will need to test them out. Here is a screenshot from the app! Lots of work to still do…  :tounge:

node is now set up

I got everything set up on the server on campus, and everything worked like a charm. I got my dependencies installed for expanding shortened urls (following the redirects to get the final url of the mp3) and the socket.io. I tested the connection to the server and it looked good. I also started looking at the YouTube api a lot more because of this site that sparked some inspiration that YouTube may be a really good choice to choose for the data source (dragontape). I figured out how to use Google’s instant searching for YouTube for predictive results which I think is a really useful feature. I am going to be doing some work later today hopefully and this week since school is out (I am working full time all week but at least I don’t have work and school to keep me busy).

progress with nodejs app

I started this weekend working on the service part of the app where the client will communicate to get the data. I made some pretty significant progress, well at least I think I did, with the backend part of the application. I am using nodejs in conjunction with socket.io and url-expander. With using socket.io, I am able to have the client and server open to each other with constant communication. How I have it set up right now is:

  1. the client emits a search query to the server
  2. the server goes out to the API and fetches the data
  3. the server then makes sure each url has .mp3 in it (for embedding in the html5 audio tag)
  4. expands url’s that do not contain .mp3 (or removes them from the array if it can’t be resolved)
  5. returns array of JSON objects back to the client

This works right now for testing, but is not how I want the final architecture to be. One of the main things I want to do is make everything much more efficient. Going out to just one API and parsing through the data, turning into my objects, resolving the urls takes way too much time. I want to store things locally in a mongodb to allow for quick access. This comes with some system architecture requirements for this to be efficient.

When a query comes into the server, it will check the db for the query and get the results. If the number results is more than X (not sure what the minimum number of results should be), then the data is returned to the user and the search term is put into a queue (I was thinking of putting this into a local array, but I might look into something like redis). Every 30min or so the server will go out to the APIs, fetch the data, parse it and put it into the database if the entry doesn’t exist. If the results from the db initially are less than X, the server will go out to the APIs, parse the data, store it to a database and spit it back to the user.

With this architecture, it will help allow for efficient searching of data. I will definitely be continuing to think of improvements and this is by far not the final solution. One of the next steps will also be reading up on sorting music data by relevancy when returning data to the user.

architecture

I’ve been trying to think of the best ways to go about setting up the architecture to have fresh, relevant data but at the same time be efficient. One of the main things I want to do is store song information retrieved from the different data sources to prevent having to go out, call the API and parse the data each time. So I wanted to check the database for the song first, and if there are more than ~30 entries return that data and put the query into a queue. If there are less than 30 entries, the API’s will be called to retrieve the data and not put the query in the queue. Every 1hr the queue will be checked and if there are items in there, the server will go out and refresh the database with new information.

Here is a rough diagram of the architecture.

cURL for API’s

So I have a good 3 API’s now I want to use for getting music:

  • ex.fm
  • SoundCloud
  • YouTube

I have some cURL commands to see some sample data.

ex.fm API

curl http://ex.fm/api/v3/song/search/tycho
{
    "status_text": "OK",
    "status_code": 200,
    "results": 269,
    "start": 0,
    "total": 269,
    "songs": [
        {
            "album": null,
            "similar_artists": [
                "ulrich schnauss",
                "milosh",
                "boards of canada",
                "casino versus japan",
                "dusty brown"
            ],
            "buy_link": null,
            "listened": null,
            "artist": "Tycho",
            "url": "http://www.tumblr.com/audio_file/8443852514/tumblr_lpc9skHMdQ1qap72t?plead=please-dont-download-this-or-our-lawyers-wont-let-us-host-audio",
            "image": {
                "small": "http://userserve-ak.last.fm/serve/64/68083084.jpg",
                "large": "http://userserve-ak.last.fm/serve/252/68083084.jpg",
                "medium": "http://userserve-ak.last.fm/serve/126/68083084.jpg"
            },
            "title": "Tycho",
            "metadata_state": "complete",
            "edit_id": null,
            "sources": [
                "http://www.tumblr.com/dashboard/3/8443881398",
                "http://paris2london.tumblr.com/post/8443852514/marcutio-tycho-hours-first-single-from"
            ],
            "viewer_love": null,
            "recent_loves": [],
            "user_love": {
                "username": "afiqrostam",
                "comment": null,
                "context": null,
                "source": "http://www.tumblr.com/dashboard/3/8443881398",
                "created_on": "Wed Aug 03 15:49:58 +0000 2011",
                "client_id": "exfm_extension"
            },
            "last_loved": "Wed Aug 03 15:49:58 +0000 2011",
            "aliases": [],
            "loved_count": 1,
            "id": "241m",
            "tags": [
                "downtempo",
                "idm",
                "electronic",
                "chillout",
                "ambient"
            ],
            "trending_rank_today": null
        }
    }
}

The problem with this API was that the song URL’s returned were not always to the mp3 file and instead a redirect URL. I was able to solve this problem with another cURL command

curl -sL -w "%{url_effective}\n" "http://www.tumblr.com/audio_file/8443852514/tumblr_lpc9skHMdQ1qap72t?plead=please-dont-download-this-or-our-lawyers-wont-let-us-host-audio" -o /dev/null
http://ak-media.soundcloud.com/Op1JrfqHz3nZ.128.mp3?AWSAccessKeyId=AKIAJBHW5FB4ERKUQUOQ&Expires=1323632265&Signature=UuCtODrRIp%2FpudjgOabRuitCUS0%3D&__gda__=1323632265_43fe3a8009a1bb5e7be8155512fdac55

So now I have the URL to embed into my page.

The other API’s were easier to get the file. SoundCloud allows you to pass a streamable parameter into the request to get songs that can be streamed off-site. With YouTube, you can get the video URL and with that use an HTML5 video wrapper for YouTube. Using this wrapper, the HTML5 video properties and events are exposed to me.

Today I am working on some demos using a “service” (I quote that because it is in no way final and is just to gather the data from the multiple sources and spit it back) I am creating to return results to a page where you can search for music.

API’s & Inspiration

So I’ve been searching around a lot for different API’s that seem like they could help me. Along the way, I’ve been finding inspiration for what I want to try and accomplish throughout the project.

The biggest source of inspiration for me is turntable.fm. The idea of being able to be a DJ and have your taste in music heard and loved by others is just a great idea to me. For me, I don’t like searching for a specific artist or song and playing it; I like having other people play music so I can discover new things. I can’t tell you how many times I’ve asked my friend to make a playlist for me or give me some new music to listen to. This solves that problem and lets you find new music without having to manually transfer songs to people.

Another site I found yesterday is called Blip.fm. This site has some ideas I really like. When you search for songs, it will find results but when you play them, they could be a youtube video or a song from Grooveshark’s stream API. This brings me to the API’s…

I didn’t want to lean towards Echo Nest’s deprecated song API to return URL’s for songs, but I think as of now it is the best bet. I found another similar API that is not deprecated, ex.fm, but the searching is lacking and the URL’s returned are not exactly what I am looking for. The best way to go about this would be getting an API key for Grooveshark’s API. Their API is exactly what I am looking for. Only problem, of course, is that it is request only… I applied for a key using my RIT information (hoping they will see that it is for a class at a University and act faster) but not news thus far.

some more resources

Here are some links I found that could help out down the road.

I am going to try and work on using nodejs and a “room” where someone will queue music to play. The info will be stored in a mongodb as a JSON object.

gathering ideas

things of interest:

  • music
  • discovering new music
  • social
  • collaboration
  • chat
  • “radio” rooms
  • favoriting

inspiration

I really like the idea of discovering new music instead of finding a specific artist/song and playing that. With new music sites like turntable.fm, pandora and last.fm, you are able to listen to a specific genre of music instead of a specific artist. The other side that I like is collaborating to make playlists or taking turns playing songs (like turntable.fm or collaborative playlists on spotify). My idea is to use a music delivery service (YouTube will be easiest because of the lack of API’s delivering MP3′s – echo nest is a possibility but it is deprecated =/) to allow users to create playlists and rooms for others to listen in. The music will be playing at the same time for everyone listening – just like the radio. This will allow people to discuss about the current track at the current time into the song.

Another sort of branch off of this idea is a kind of party view where you can listen in a room or have a playlist queued up and can display this on a TV at a party. On the site could also be a QR code so that when people are listening in, they can scan the code and get artist information fed to them on their mobile devices while the song is playing.

server side:

  • nodejs to handle chat and connections to a room
  • mongodb to store JSON of room/song information
  • API to be called by client for getting room and song information

client side:

  • Popcornjs to make comment on song at specific spot
  • receiving and sending chat messages to nodejs server
  • possibility of scrobbling to last.fm (would involve user registration)

services

  • YouTube API
  • Popcornjs to handle song commenting
  • nodejs for connections and chat
  • mongodb for storing JSON (songs, rooms, users)
  • echo nest to deliver artist information