If you’ve been on the web since the mid 1990’s you probably remember the annoying songs and sounds that would blast through your speakers whenever you loaded a new page. Thankfully the default for most browsers is to prevent this autoplay functionality, but audio and specifically music are still a huge part of today’s internet.
Today we are going to look somewhat in depth into the Audio Web API, the HTML5 audio tag and finally how to use these two items to create our own visually customizable audio players.
This information is great if you are looking to manipulate or update your pages based on the state of your audio file. What should we do if we want to use this API in our webpages?
Audio HTML Element
The release of HTML5 added a number of semantic tags to our arsenal that offer meaning to our web document’s structure. It also added a number of functional tags for bringing our pages to life. In order to avoid attaching a separate script to your page, HTML5 offers a new <audio> tag that accepts a source attribute for your audio file and returns a new instance of the HTMLAudioElement object.
The default behavior of the audio tag is to not be visible on the screen. However, the audio tag has a popular attribute of ‘controls’ which will display a pause/play button, progress bar and volume controls:
While this is great for a quick and dirty MVP, the visuals of the default controls aren’t great. Making this even more of an issue is that the display is not uniform across browsers and there is very little CSS that can target and alter the display characteristics of this player.
If you need something that works, but don’t care how it looks, an <audio> tag with the controls attribute will work great. If you do care about how your UI looks, let’s look at how to create your custom audio player!
Building our Audio Player
For our solution we will add an <audio> tag to our index.html and then access it through our script.js file. To start, clone my project repository (https://github.com/dpericich/SoundCloud-Audio-Player). Change into the ‘starter_files’ directory and open the HTML file. The current file should have a body containing only a blank <audio> tag. The mp3 file for our song is stored in the ‘assets’ directory. We will set the src attribute of our audio tag to “/final_files/assets/indie_song.mp3” which will instantiate a new Audio object with our song.
The final changes we will do with this HTML file are to add the container and structure elements for our audio player. Because we aren’t using the default audio UI by including ‘controls’, we will need to create our own UI. Here is what the body of our HTML file should look like at this point:
Our styling for this audio player isn’t anything too special, so for brevity I will skip going through the file in depth. Just know that I did not take the time to make this responsive, so if you would like to improve the app please feel free to add some min and max widths to the components and potentially change the flex direction to stack the controls of the player for mobile devices. As it is now our current player looks like this:
Now we have the HTML structure, the CSS styling and an HTMLAudioElement instance containing our indie song’s mp3 file. Now we need to add some functionality to our file. To start, let’s hook into the different element classes and save these references as variables. I assigned the play/pause button, the volume controls and finally the track progress indicator. At the top of our script.js file we use document.querySelector() to grab each of these values, including accessing our Audio object instance.
We can interact and change these elements now, so let’s set up some event handlers to watch for clicks. The easiest functionality to add is the volume controls. With our two separate buttons, we will add event handlers that increment and decrement the volume of our Audio object to a certain point:
The next functionality we’d like to add is playing and pausing the track. The Audio object has built in play() and pause() methods and we are able to access this object from our ‘audioEl’ variable we declared at the top of our file. Let’s add an event listener to the playButton that will handle starting and stopping the music:
The Audio element has a number of boolean flags set on it so that we don’t have to be taxed with creating our own flags for object state. Along with the ‘paused’ flag, we can make use of common tags such as ended. With this all we are doing is checking if the audio is paused and calling audioEl.play() it if is, otherwise we pause it. I am using web unicodes for the play/pause icons so I have to adjust the fontSize, but you can get the same effects using a font awesome font or SVGs.
With our volume controls and play/pause set, we need to have a visual cue for the user for track progression. Sure we could access the audioEl.duration and use setInterval() to get and display audioEl.currentTime every 1000 ms but that’s not very pretty. Instead let us change the position of the ball on the track bar every second the song plays. For this we will need to get the time elapsed every second and use this with our track duration to create a percentage of pixels traversed for our progress indicator. That will look like this:
Here we set an interval on our page to get the percentagePlayed or percent of the elapsedTime in relation to the songs duration. We then can set the left offset on our progress element relative to its container which will display to the user how far through the song they are.
To make this better we could have a state variable to store the interval ID returned when we start the interval and then call clearInterval(audioIntervalId) every time we call audioEl.play(), but I’ll leave that to you. And with that we have a functional audio player with custom styling!
Now you have a basic understanding of the Audio Web API, the HTML5 <audio> tag and a simple approach to building a custom audio player and UI. If you want to continue to learn, you can try adding the Drag and Drop API to allow for audio scrubbing (start with adding ‘draggable=true’ to the div with a class of ‘progress’), add cool visuals to background of the audio player container or even perform visualizations by digging deeper into the Web Audio API. Let me know in the comments how you plan to build on our basic player!