javascriptnode.jshowler.js

Howler.js - The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page


I am trying to trigger an alarm after a certain time has ended. I am using Howler.js to play the alarm, but for some reason, it is displaying this error: howler.js:2500 The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. I switched to Howler because a similar error was coming when I tried to use Audio() Web API in JavaScript.

Here is my code:

const { Howl, Howler } = require("howler");

let i;
let timer;
var alarm = new Howl({
  src: ["alarm.mp3"],
});
let playTimer = true;
const timerDisplay = document.getElementById("timerDisplay");

document.addEventListener("DOMContentLoaded", () => {
  i = 5;

  timer = setInterval(() => {
    if (playTimer == true) {
      if (i != 0) {
        timerDisplay.textContent = i;
        i--;
      }

      if (i == 0) {
        alarm.play();
        clearInterval(timer);
      }
    }
  }, 1000);
});

I don't know if this is helpful or not, but just to let you know, I am using Parcel as my bundler. Thank you in advance for any answer.


Solution

  • As @Kokodoko said in the comments of my question, the audio had to be triggered by some form of user interaction. So, I added a button in my HTML and replaced the

    document.addEventListener("DOMContentLoaded", () => {})

    with

    startTimerBtn.addEventListener("click", () => {})

    So this is the final code:

    const { Howl, Howler } = require("howler");
    
    let i;
    let timer;
    var alarm = new Howl({
      src: ["alarm.mp3"],
    });
    let playTimer = true;
    const timerDisplay = document.getElementById("timerDisplay");
    const startTimerBtn = document.getElementById("startTimer");
    
    startTimerBtn.addEventListener("click", () => {
      i = 5;
    
      timer = setInterval(() => {
        if (playTimer == true) {
          if (i != 0) {
            timerDisplay.textContent = i;
            i--;
          }
    
          if (i == 0) {
            alarm.play();
            clearInterval(timer);
          }
        }
      }, 1000);
    });
    
    

    Although this wasn't the solution I intended to get, it suits my needs well.

    Also, one small other thing for others using Parcel.js like me. Just in case you don't know, you have to put your audio file in Parcel's dist directory so that it can play. For some reason, it wasn't bundling automatically.