I have an mp3 from an external URL via <audio></audio>
tag.
As on mobile it takes a few seconds to download before being ready to play, I've added a spinner which reveals the player only once the mp3 is ready to play - so nobody is going to click on play if there's no sound yet.
Everything works, except an ENORMOUS NETWORK PAYLOAD, as the page finish to load only when the first bytes of the mp3 are dowloaded and therefore is ready to play (the mp3 comes in ranges of data - partial content code 206).
So, to avoid the ENORMOUS NETWORK PAYLOAD, I'm thinking to lazy load the mp3, or maybe the whole player, using intersection observer, as the mp3 audio tag is below the fold. But then the mp3 is not downloaded at all.
I've placed the intersection observer after the audio tag is revealed (after the loading spinner is gone), but the mp3 is not downloaded. I've tried everything everywhere, but no success.
I just started to learn some javascript, and I'm not even sure if using the intersectin observer to load the page first, and then the mp3, is a good idea in this case. And anyway I can't make it work, so any help or suggestion is much appreciated. Thank you.
Here's the code:
<div class="player">
<div class="hide animated" id="player"> {# spinner #}
<audio data-src="https://some.com/track.mp3"></audio>
</div> {# spinner #}
<div class="circle-spin" id="loaderSpinner" role="status"></div> {# spinner #}
</div>
--
// SPINNER
window.addEventListener("load", function(){
document.getElementById("loaderSpinner").style.display = "none";
document.getElementById("player").classList.remove('hide');
});
// On the document's DOMContentLoaded event, this script should queries the DOM for audio tag -- so, I guess
document.addEventListener("DOMContentLoaded", function() {
const mp3 = document.querySelector('audio');
const io = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (!entry.isIntersecting) return;
entry.target.src = entry.target.getAttribute('data-src');
io.unobserve(entry.target);
})
});
io.observe(mp3);
});
// And here's some customization for audio player controls which starts with load sound via <audio tag
const audioElement = document.querySelector("audio");
const audioCtx = new AudioContext();
const track = audioCtx.createMediaElementSource(audioElement);
// follows Player controls and attributes...
// and finally an event listener that waits for the page to load etc etc
window.addEventListener("load", () => {
// Set times after page load
setTimes();
// etc etc etc...
I think the problem comes from the fact that your observer will never trigger because your audio has no source.
The audio tag is not even added to the DOM if there is no valid src from the tests I quickly ran.
Also, what you are trying to achieve is already baked in the audio tag. You can use the preload
attribute to tell the browser if/how it should preload the audio stream.
Values can be:
auto
The author thinks that the browser should load the entire audio file when the page loads
metadata
The author thinks that the browser should load only metadata when the page loads
none
The author thinks that the browser should NOT load the audio file when the page loads
So, for you, I think you'd like none or metadata.
Parts of the answer come from W3CSchools