Building a browser based music player

Published July 2, 2012

For the past week or so I've been working on a web based music player. I've found Grooveshark to be really convenient and for a while I've been wanting something similar that works on my own collection (i.e. something to run inside a private network).

Screenshot: (please forgive lack of styling)

(click for full size)

It currently supports (to some degree) the standard stuff:

  • playing music (yep), with pause/stop controls
  • A collection:
    • Tree expansion/collapse
    • Searching (via server)
    • Album artwork (via server)
    • Drag and drop to playlist
  • Playlists:
    • Saving/loading named playlists (but client support for switching names incomplete so far)
    • Selections and hotkeys
    • Sorting and grouping - so when you sort by artist it'll subsort by album and then tracknumber

It's not really ready for public consumption yet but the code is all on GitHub. You'll have to adapt bits of it for your own MySQL server and change the filesystem path(s) to your collection.

The technical details are:

  • Client:
    • Standard HTML5/CSS/JavaScript etc. Using KnockoutJS, an MVVM framework.
    • Basically a massive wrapper around the <audio> tag, but I'm finding browser support between Chrome and FF is surprisingly inconsistent and slightly rubbish so I might offload it to a JS sound library.
    • Most stuff is lazily loaded from the server, e.g. the collection tree requests its children when you expand a node
  • Server:
    • Written in Python/Flask (micro-framework)
    • Uses MySQL (may swap this for SQLite at some point)
    • Supposed to be a very thin and safe wrapper around the filesystem, but it is growing. In future I intend to have it handling transcoding of formats (e.g. browsers don't support flac, so transcode flac=>ogg), and fetching missing album artwork from a webservice.

I'm really liking KnockoutJS! The data binding is great for all kinds of things. One of the nice things for a complex UI, like this, is being able to recalculate heights and widths easily. CSS is a bit crippled in some ways; it's hard to get things to scale nicely - for example the collection panel (left) and the playlist panel (right) must fit inside the browser window, and the latter must scale across to fill the available width.

I have a screen object set up with various knockout properties; something like this:

(function($) {
    window.Screen = function() {
        this.appWidth = ko.observable(0);
        this.leftPanelWidth = ko.observable(200);
        this.rightPanelWidth = ko.computed(function() {
            return this.appWidth() - this.leftPanelWidth();
        $(window).resize(function() {
            this.appWidth( $(window).width() );

Then in your view:

    .right-panel, .left-panel {
        float: left;

<div class='left-panel'
    data-bind="style: { width: $root.screen.leftPanelWidth() + 'px' }"
<div class='right-panel'
    data-bind="style: { width: $root.screen.rightPanelWidth() + 'px' }"

So when the browser is resized, the panels resize themselves automagically.