Spotify Web API - Play songs through voice commands

A demo that recognizes voice commands and plays the desired song. Remember to enable your microphone and grant access to the web app to make it work.

HTML

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/annyang/1.4.0/annyang.min.js"></script>
<link rel="stylesheet" href="https://developer.spotify.com/web-api/static/css/cached.css">
<main>
    <div id="commands">
         <h1>Play songs through voice commands</h1>
         <p>This demo uses speech recognition and the <a href="https://developer.spotify.com/web-api/">Spotify Web API</a> to play songs. Try it using some of the commands below. Remember to allow the use of the microphone.</p>
        <p>For instance "Play Some Nights"</p>
        
        <h2>Voice commands</h2>
        <ul>
            <li>Play {song name}</li>
            <li>Play {song name} by {artist name}</li>
        </ul>
    </div>
    <div id="conversation"></div>
</main>
<footer>This demo uses the Spotify Web API and the library <a href="https://github.com/TalAter/annyang">annyang</a> to make it easy to match recognised text with rules.</footer>

CSS

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
h1, h2, p {
    margin-bottom: 20px;
}
h1 {
    line-height: 1.3em;
}
body {
    font-family: Helvetica, Arial;
    font-size: 16px;
    line-height: 1.3em;
    display: flex;
    min-height: 100vh;
    flex-direction: column;
}
main {
    flex: 1;
    margin: 20px auto;
    max-width: 800px;
    padding: 0 20px;
}
footer {
    background-color: #eee;
    padding: 10px;
    text-align: center
}
ul {
    margin-left: 30px;
}
.action, .recognized {
    padding: 10px;
    position: relative;
    margin-bottom: 10px;
    width:80%;
}
.action {
    text-align: right;
    background-color: #ddd;
    margin-left:20%;
    border-radius: 5px 5px 0 5px;
}
.action:after {
    content:"";
    position: absolute;
    width: 0;
    height: 0;
    border-width: 18px;
    border-style: solid;
    border-color: transparent transparent #ddd transparent;
    bottom: 0px;
    right: -17px;
}
.recognized {
    text-align: left;
    background-color: #eee;
    font-weight: bold;
    border-radius: 5px 5px 5px 0;
}
.recognized:after {
    content:"";
    position: absolute;
    width: 0;
    height: 0;
    border-width: 18px;
    border-style: solid;
    border-color: transparent transparent #eee transparent;
    bottom: 0px;
    left: -17px;
}
.recognized > div:before {
    content: open-quote
}
.recognized > div:after {
    content: close-quote
}
#conversation {
    padding: 20px;
}
#conversation::before {
    content:"";
    height: 1px;
    width: 200px;
    background-color: #ddd;
    display: block;
    margin: 10px auto;
}
#conversation img {
    margin-top: 5px;
}

JavaScript

(function () {
    var audio = new Audio();

    function searchTracks(query) {
        $.ajax({
            url: 'https://api.spotify.com/v1/search',
            data: {
                q: query,
                type: 'track'
            },
            success: function (response) {
                if (response.tracks.items.length) {
                    var track = response.tracks.items[0];
                    audio.src = track.preview_url;
                    audio.play();
                    communicateAction('<div>Playing ' + track.name + ' by ' + track.artists[0].name + '</div><img width="150" src="' + track.album.images[1].url + '">');
                }
            }
        });
    }

    function playSong(songName, artistName) {
        var query = songName;
        if (artistName) {
            query += ' artist:' + artistName;
        }

        searchTracks(query);
    }

    function communicateAction(text) {
        var rec = document.getElementById('conversation');
        rec.innerHTML += '<div class="action">' + text + '</div>';
    }

    function recognized(text) {
        var rec = document.getElementById('conversation');
        rec.innerHTML += '<div class="recognized"><div>' + text + '</div></div>';
    }

    if (annyang) {
        // Let's define our first command. First the text we expect, and then the function it should call
        var commands = {
            'stop': function () {
                audio.pause();
            },
                'play track *song': function (song) {
                recognized('Play track ' + song);
                playSong(song);
            },
                'play *song by *artist': function (song, artist) {
                recognized('Play song ' + song + ' by ' + artist);
                playSong(song, artist);
            },
                'play song *song': function (song) {
                recognized('Play song ' + song);
                playSong(song);
            },
                'play *song':...