1

I have function running every second (for clock) .
I wanted to add sound to every tick tick....(second) but as function is running automatic (means no triggering is taking place) and when sound added produces an error

Error showing is :
Uncaught DOMException: play() failed because the user didn't interact with the document first.

Know that it is not possible to play audio automatic .

So tried to create a start sound btn which play the audio but as second time (of clock) and don't match with audio . So there is a mismatch

I am trying to add that function(audio play) inside second(clock time) calculator .
Is this possible or not

Link to similar question but not able to find the solution

The code is as follows

setInterval(clockRunner, 1000);

function clockRunner() {
  //Clock code goes here
  function trigger() {
    var audioElement = document.getElementById('audiotag1');
    audioElement.play();
  }
}
<audio id="audiotag1" src="https://soundbible.com/mp3/Tick-DeepFrozenApps-397275646.mp3" preload="metadata" controls></audio>
<button onclick="trigger()">Start</button>

Update

Added event listener inside the outer function but this way sound is playing once not every second .

One solution here can be adding another setInterval but this will again create problem of playing sound at different timing of clock's second

Also it shows the same error in the console(mentioned above) until user clicks the btn

setInterval(clockRunner, 1000);

function clockRunner() {
  //Clock code goes here

document.getElementById('demo').innerHTML = new Date();
  setInterval(trigger, 1000);
  document.getElementById("triggerSnd").addEventListener('click', trigger)

  function trigger() {
    var audioElement = document.getElementById('audiotag1');
    audioElement.play();
  }
}
<audio id="audiotag1" src="https://soundbible.com/mp3/Tick-DeepFrozenApps-397275646.mp3" preload="metadata" controls></audio>
<button id="triggerSnd">Start</button>
<div id="demo"></div>

Thanks for help in advance

Rana
  • 2,500
  • 2
  • 7
  • 28
  • The only place you can call `trigger` from is *inside* `clockRunner`. For what purpose do you have this inner function, and not instead have its code directly inside `clockRunner`? – connexo Oct 07 '21 at 14:34
  • Ohh... think that solution can be calling event listener inside `clockRunner` for button and play sound . Thanks @connexo , I will try that way – Rana Oct 07 '21 at 14:38
  • @connexo tried another solution but that way sound plays only once on the click of btn . Solution for this can be adding another `setInterval` but this will create problem of playing sound at different time . Can you help me plz – Rana Oct 07 '21 at 14:54

2 Answers2

1

I've changed my answer completely. Now I didn't need to use an event listener, just the proper API of HTMLMediaElement that audio uses. Note that I've add loop attribute to tick's audio.

var blast = document.getElementById("blast");
var tick = document.getElementById("tick");

var tickDuration, timeDiff, lastTime


tick.onloadedmetadata = () => tickDuration = tick.duration


timeDiff = 0.3 // max difference between sync, dont lower it or it will bug (can explain if u want)
lastTime = 0

blast.addEventListener("timeupdate", () => {
    let bct = blast.currentTime
  let tct = tick.currentTime
  let syncBlastTime = tickDuration - (tickDuration - bct%tickDuration)
  let diff = Math.abs(syncBlastTime - tct)
  lastTime = bct
  
  console.log(`Blast: ${bct} Tick: ${tct}\nSynced time difference (seconds): ${diff.toFixed(6)}`)
  if(diff > timeDiff) { // add this or it will bug the tick audio
        tick.currentTime = syncBlastTime
   }  
})

blast.addEventListener("pause", () => {
   tick.pause()
})

blast.addEventListener("playing", () => {
   tick.play()
})
<audio id="blast" src="http://stream.arrowcaz.nl/caz64kmp3" controls="loop"></audio>
<audio id="tick" src="https://soundbible.com/mp3/A-Z_Vocalized-Mike_Koenig-197996831.mp3" loop controls='loop'></audio>
<br />
testing_22
  • 2,340
  • 1
  • 12
  • 28
  • But as `sound` is inside clock `function` so when I trigger the `audio` it will play irregular with the speed of seconds needle – Rana Oct 07 '21 at 15:03
  • You can attach a `pause` event to clear it – testing_22 Oct 07 '21 at 15:13
  • I want to play sound every sound but when trigger with different `setInterval` there is irregularities in playing of sound . Know that `pause` can remove sound but I want to remove irregularities in playing of sound – Rana Oct 07 '21 at 15:16
  • I got it. Updated. Check it now if it solves your problem – testing_22 Oct 07 '21 at 16:09
  • Thanks for help(+1) . But one problem comes up the first click produces sound faster(first 2 clicks) and after that it plays alright . Can see in the updated question – Rana Oct 07 '21 at 16:48
  • I forgot to update and went lunch, lol. Now you can check – testing_22 Oct 07 '21 at 17:48
  • Thanks for replay and update . But can you tell in the above question context (taking it as example) , I have updated the clock code and an audio which run on clicking start but clock is running automatic . And there seems difference in seconds change(timer) and audio play can you tell in that view point – Rana Oct 07 '21 at 18:31
1

If you make use of some variables, you can control your code to perform like a clock. It's worth noting that there are two possibilities, either the clock has started or it has stopped.

The interval will run when you clicked to start and it will be cleared in stopping it. Here I can't notice any mismatch between the sound and the timer.

var start = document.getElementById("triggerSnd")
var audioElement = document.getElementById('audiotag1')
var demo = document.getElementById('demo')
var interval, isMuted = true

// The second argument of addEventListener should be a function
// that receives an argument 'event'

clockRunner();
clock(); // call firstly
setInterval(() => clock(), 1000)
    
start.addEventListener('click', clockRunner)

function clock(isMuted){
  //Clock code goes here
  demo.innerText = new Date();
  audioElement.play();
}

function clockRunner() {
    audioElement.muted = isMuted
    start.innerText = isMuted ? "Start" : "Stop"
    isMuted = !isMuted
}
<audio id="audiotag1" src="https://soundbible.com/mp3/Tick-DeepFrozenApps-397275646.mp3" preload="metadata"></audio>
<button id="triggerSnd">Start</button>
<div id="demo"></div>
testing_22
  • 2,340
  • 1
  • 12
  • 28
  • It is because here clock is started with a trigger (same as that of sound) but I used trigger for sound only as wanted to let the clock run all the time . And again thanks for help (+1). Is there a way to let the clock remain automatic and it only audio run with trigger – Rana Oct 07 '21 at 20:16
  • And also can you tell about this `if(!hasStarted)`line as `hasStarted = false` so how we can use `!` not operator . What does this code making sense – Rana Oct 07 '21 at 20:20
  • Yes, you can start it muted and then unmute. How about it now? I omitted `controls` attribute to hide it showing toggling the icon – testing_22 Oct 07 '21 at 23:13
  • Thanks a lot it helped me . Can you tell about `isMuted = !isMuted` and the above question about `if(!hasStarted)` line as `hasStarted = false` you used before this answer – Rana Oct 08 '21 at 08:20
  • Also why did you write `//call firstly` behind `clock()` – Rana Oct 08 '21 at 12:20
  • Because setInterval adds a delay at the first call. So I called clock() outside once to avoid it – testing_22 Oct 08 '21 at 13:34
  • Also Can you tell about `isMuted = !isMuted` and the above question about `if(!hasStarted)` line as `hasStarted = false` you used before this answer – Rana Oct 08 '21 at 13:43
  • One last thing : The error still shows up in console as mentioned in the question `Uncaught DOMException: play() failed because the user didn't interact with the document first.` – Rana Oct 08 '21 at 14:01
  • `isMuted = !isMuted` negates the value of this variable (supposing it's boolean) and reassigns its value. Same applies to previoud `hasStarted`. For instance, if `isMuted` is true, then it changes to false. The logic is every time you click the start/stop button to toggle the value of isMuted. Once true, it doesn't play sound. Once false, it plays – testing_22 Oct 08 '21 at 16:20
  • Try adding `autoplay` tag to audio. If it does not work, try [this](https://stackoverflow.com/questions/49930680/how-to-handle-uncaught-in-promise-domexception-play-failed-because-the-use) – testing_22 Oct 08 '21 at 16:23
  • Audio is playing after the click on `start` but until the button is clicked error is showing up every second and stops when btn is clicked . I think it is not possible to remove that but thanks for help . If you find anything that may help feel free to help : ) – Rana Oct 09 '21 at 08:39