Sunday, October 27, 2013

A Simple Chromecast Media Streamer

The Google Chromecast became available over the summer to great anticipation and excitement.

I decided to buy one for a couple of reasons :
  1. I needed a way to play Netflix on one of my TV's that didn't currently have that ability.
  2. I wanted a way to cheaply and easily play videos that I had sitting on a NAS.
For 2. I had actually made some attempts via alternative methods using a Raspberry Pi running a number of different versions of XMBC. While initially things would look promising, when it actually came to using it anger things fell apart. After reading up on the Chromecast SDK  it seemed like I could write my own media streamer fairly simply.

So what follows is details of my attempt. Overall it was an interesting investigation into what can be achieved with the Chromecast with a small amount of code. Some things work well and other things not so much. Particularly the media status listener support seemed somewhat flaky.

The source code for the application is available here. The majority of the chromecast interaction can be found in  chromecast.js.

To try it out you must
  1. Checkout the app from github and run npm install
  2. Get your URL(s) whitelisted 
  3. Modify receiver.html and chromecast.js setting your application id
  4. Point your whitelisted URL at your modified receiver.html
  5. Add the domain you plan to run the sender web application on to the Chrome browser Chromecast setttings. See the "Whitelisting Chrome Apps" section here 
  6. Run the server via "node lib/server.js [port] [path to media]"
  7. Point your Chromecast enabled browser at http://[host]:[port] to load the Media List Page
I decided (at least initially) to go the Google Chrome route for the application.

Receiver

For the receiver I ended up using the sample one from cast-chrome-sender-helloworld. I just had to hook it up to my whitelisted URL and host it somewhere. In the end I just put it on a Jetty instance running on the Raspberry Pi. To make it available I setup a port forward in my home networks router pointing at the Raspberry Pi jetty instance.

Sender

The sender part of the application runs in the Chrome Browser.
  • It provides access to the list of media available on the NAS (actually this can be any filesystem directory accesible to the web application). 
  • It enables the media to be played, started, stop and paused. It also enables the play position to be set
I wrote the sender in javascript running on Node.js. It's hosted within my home network running on my Raspberry Pi. This part did not have to visible outside of my home and that included the URL's for the media. I was happy to find that I could pass internally based URL's to the receiver that pointed to the node.js server and they would load fine.

The backend part of sender application simply provided a rest handler to :
  1. Get a list of available media
  2. Get and set the currently playing media
  3. Get and set the current activity id so that page reloads of the sender application can pick up on what the receiver is currently doing.
It also used a Connect static registration to enable loading the media from the NAS/filesystem.

For the frontend I decided to use a mobile friendly setup with the hopes that the Chrome browser in IOS and Android will eventually get cast support (neither of them currently do). It uses jQuery, jQuery Mobile, Backbone.js and Underscore.js with all modules in AMD format. My Zazl Optimizer is also used to provide dynamically built and optimized javascript to the frontend.

The media list page looks like this :

You can select one of the list media files to play or navigate to the Playing page.

The playing page looks like this :
You can select the Chromecast Receiver to play on, the current position by setting the slider value, and start, pause and stop the media itself.