Simple HTML Custom Audio Player (Step-By-Step Example)

Welcome to a quick tutorial and example on how to create an HTML custom audio player. Want to create your own custom player using HTML audio? Well, it’s quite a tricky situation.

There is no way to change the browser’s default HTML <audio> interface, but we can create our own custom audio player using Javascript:

  • Create a new audio object – var aud = new Audio("AUDIO.mp3");
  • To play and pause – aud.play(); aud.pause();
  • To set the volume – aud.volume = 0.0 TO 1.0;
  • Lastly, to skip to a specified time – aud.currentTime = SECONDS;

That covers the basic idea, but read on for an actual example!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

Download & Demo Custom Player Useful Bits & Links
The End

 

DOWNLOAD & DEMO

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

  • 1-raw-player has zero CSS, only the raw mechanics. Use this if you want to fully customize the audio player yourself.
  • 2-player has styles included. Use this if you want “quickstart”.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

CUSTOM AUDIO PLAYER DEMO (NO STYLES)


/

Volume

My server does not seem to quite like audio streaming (time seek may revert back to 0)… Also, download the above zip file if you want the “nice version”:

 

CUSTOM AUDIO PLAYER

All right, let us now get into the step-by-step example of creating a custom audio player. Take note, there is no CSS involved here, only the pure mechanics.

 

STEP 1) THE HTML

1-raw-player.html
<!-- (A) PLAY/PAUSE BUTTON -->
<button id="aPlay" disabled>Play</button>
 
<!-- (B) TRACK TIME -->
<span id="aNow"></span> / <span id="aTime"></span>
 
<!-- (C) SEEK BAR -->
<input id="aSeek" type="range" min="0" value="0" step="1" disabled/>

<!-- (D) VOLUME SLIDE -->
<input id="aVolume" type="range" min="0" max="1" value="1" step="0.1" disabled/>

This should be self-explanatory, there are only 4 HTML controls here.

  1. <button id="aPlay"> The play/pause button.
  2. <span id="aNow"> is the current playtime of the track, <span id="aTime"> is the total time of the track.
  3. <input id="aSeek"> Time seek slider, the value is in seconds.
  4. <input id="aVolume"> Volume slider. As in the introduction, this is a value from 0.0 (muted) to 1.0 (full volume).

 

 

STEP 2) INITIALIZE AUDIO PLAYER

1-raw-player.js
window.addEventListener("DOMContentLoaded", () => {
  // (A) AUDIO OBJECT + HTML CONTROLS
  var audio = new Audio("sugar-palm-fairy.mp3"), // CHANGE TO YOUR OWN!
      aPlay = document.getElementById("aPlay"),
      aNow = document.getElementById("aNow"),
      aTime = document.getElementById("aTime"),
      aSeek = document.getElementById("aSeek"),
      aVolume = document.getElementById("aVolume");
});
  • Captain Obvious to the rescue. To prevent things from screwing up, we wait for the page to load DOMContentLoaded before initializing the Javascript.
  • Create the new Audio() and fetch all the HTML controls.

 

STEP 3) PLAY/PAUSE BUTTON

1-raw-player.js
// (B) PLAY/PAUSE BUTTON
// (B1) CLICK TO PLAY/PAUSE
aPlay.addEventListener("click", () => {
  if (audio.paused) { audio.play(); }
  else { audio.pause(); }
});
 
// (B2) AUTO SET PLAY/PAUSE TEXT
audio.addEventListener("play", () => {
  aPlay.innerHTML = "Pause";
});
audio.addEventListener("pause", () => {
  aPlay.innerHTML = "Play";
});
  • (B1) Don’t think this needs any explanation… If the audio is paused, we click to play. If the audio is playing, we click to pause.
  • (B2) Automatically set the play/pause text on the button.

 

 

STEP 4) TRACK TIME

1-raw-player.js
// (C) TRACK PROGRESS
// (C1) SUPPORT FUNCTION - FORMAT HH:MM:SS
var timeString = (secs) => {
  // HOURS, MINUTES, SECONDS
  let ss = Math.floor(secs),
      hh = Math.floor(ss / 3600),
      mm = Math.floor((ss - (hh * 3600)) / 60);
  ss = ss - (hh * 3600) - (mm * 60);
 
  // RETURN FORMATTED TIME
  if (hh>0) { mm = mm<10 ? "0"+mm : mm; }
  ss = ss<10 ? "0"+ss : ss;
  return hh>0 ? `${hh}:${mm}:${ss}` : `${mm}:${ss}` ;
};
 
// (C2) INIT SET TRACK TIME
audio.addEventListener("loadedmetadata", () => {
  aNow.innerHTML = timeString(0);
  aTime.innerHTML = timeString(audio.duration);
});
 
// (C3) UPDATE TIME ON PLAYING
audio.addEventListener("timeupdate", () => {
  aNow.innerHTML = timeString(audio.currentTime);
});
  • Both audio.duration and audio.currentTime are in seconds (with 2 decimal places of microseconds).
  • (C1) To display a “nice-looking time”, we have to create our own support function to format it.
  • (C2) When we get the metadata of the audio file, update the HTML total time.
  • (C3) Automatically update the HTML current time as the track plays.

 

 

STEP 5) TIME SEEK BAR

1-raw-player.js
// (D) SEEK BAR
audio.addEventListener("loadedmetadata", () => {
  // (D1) SET SEEK BAR MAX TIME
  aSeek.max = Math.floor(audio.duration);
 
  // (D2) USER CHANGE SEEK BAR TIME
  var aSeeking = false; // USER IS NOW CHANGING TIME
  aSeek.addEventListener("input", () => {
    aSeeking = true; // PREVENTS CLASH WITH (D3)
  });
  aSeek.addEventListener("change", () => {
    audio.currentTime = aSeek.value;
    if (!audio.paused) { audio.play(); }
    aSeeking = false;
  });
 
  // (D3) UPDATE SEEK BAR ON PLAYING
  audio.addEventListener("timeupdate", () => {
    if (!aSeeking) { aSeek.value = Math.floor(audio.currentTime); }
  });
});
  • (D1) Remember the HTML <input type="range"> seek bar from earlier? This step simply sets the max as we get to know the length of the track.
  • (D2) As the user changes the seek bar, we simply update audio.currentTime.
  • (D3) Automatically update the HTML seek bar as the track plays.
  • (D2 & D3) Take note of the flag aSeeking here.
    • As the user is manually changing the seek bar, we do not want (D3) to update. Very irritating, the user tries to drag the time, (D3) sets it backward.
    • So we use the aSeeking flag as “protection”. When the user starts dragging the seek bar, we don’t allow (D3) to run.

 

STEP 6) VOLUME CONTROL

1-raw-player.js
// (E) VOLUME
aVolume.addEventListener("change", () => {
  audio.volume = aVolume.value;
});

Well… Just update the audio.volume as the user moves the slider.

 

STEP 7) ENABLE/DISABLE CONTROLS

1-raw-player.js
// (F) ENABLE/DISABLE CONTROLS
audio.addEventListener("canplay", () => {
  aPlay.disabled = false;
  aVolume.disabled = false;
  aSeek.disabled = false;
});
audio.addEventListener("waiting", () => {
  aPlay.disabled = true;
  aVolume.disabled = true;
  aSeek.disabled = true;
});
  • canplay When the browser has sufficient audio buffer to play, we enable the controls.
  • waiting When there is an insufficient buffer, we disable the controls.

Another way of doing this is to use canplaythrough instead – This makes sure the browser can play the full song without stopping to load, but the initial loading will take longer.

 

 

USEFUL BITS & LINKS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

COMPATIBILITY CHECKS

This audio player is obviously not backward compatible with the ancient browsers. But it should work well across all “Grade A” modern browsers.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

2 thoughts on “Simple HTML Custom Audio Player (Step-By-Step Example)”

Leave a Comment

Your email address will not be published. Required fields are marked *