Search code examples
javascripthtmltransitionhtml5-audio

Can I "transition" the volume of an <audio> element, using javascript?


If I wish to change the opacity of a <div> irregularly over time, I can use CSS animation and @keyframes:

.myDiv {
  animation: myAnimation 10s linear;
}

@keyframes myAnimation {

    0% {opacity: 1;}
   80% {opacity: 1;}
   81% {opacity: 0.99;}
  100% {opacity: 0;}

}

}

But what if I want to change the volume of an <audio class="my-audio"> element irregularly over time in an identical manner?

I know I can begin with:

var myAudio = document.getElementsByClassName('my-audio')[0];
myAudio.volume = 1.0;

But how can I change the volume to 0.99, when 81% of the sound clip has played and fade uniformly down to a volume to 0.0, when 100% of the sound clip has played?

Is there a javascript syntax for this kind of aural transition or am I looking for something which doesn't exist (yet)?


Solution

  • Here's what I came up with in the end:

    1. The script determines the duration of the audio element, after which it calculates the point during the audio at which the fade needs to start.
    2. A setInterval commences which monitors how much of the audio has played by repeatedly checking the currentTime property.
    3. At the start-point of the fade a setInterval commences which repeatedly reduces the volume of the audio, until it reaches zero.

    Working Example:

    var myAudio = document.getElementsByTagName('audio')[0];
    var myAudioVolume = 1.0;
    var myAudioDuration;
    var myAudioPlayInterval;
    var myAudioCheckInterval;
    var myAudioDuration1Percent;
    var myAudioFadeStart = 30; // The percentage of playback before the fade starts
    
    
    setTimeout(function(){
        myAudioDuration = myAudio.duration;
        myAudioDuration1Percent = (myAudio.duration / 100); 
    }, 200);
    
    
    function myAudioFadeVolume() {
    
        myAudioFader = setInterval(function(){
            myAudioVolume = myAudio.volume;
    
            myAudioVolume = myAudioVolume - (1 / myAudioFadeStart);
            console.log('myAudio volume is now ' + myAudioVolume);
            myAudio.volume = myAudioVolume;
    
            if (myAudioVolume < 0.05) {
                
                myAudio.volume = 0;
                clearInterval(myAudioFader);
            }
    
        }, (myAudioDuration1Percent * 1000));
    }
    
    function myAudioFindFadeStart() {
    
        myAudioCheckInterval = setInterval(function(){
    
            if (myAudio.currentTime > (myAudioDuration1Percent * myAudioFadeStart)) {
    
                myAudioFadeVolume();
                clearInterval(myAudioCheckInterval);
            }
        }, 10);
    }
    
    setTimeout(function(){
        myAudio.play();
        myAudioFindFadeStart();
    }, 1500);
    <audio class="my-audio">
      <source src="https://www.w3schools.com/tags/mov_bbb.mp4" type="audio/ogg">
    </audio>