How to make the media load at runtime without playing it now?

I am creating a web application that can be opened for a long time. I donโ€™t want to download audio during loading (when HTML is being loaded and parsed) in order to make the first download as fast as possible and save precious resources from mobile users. Audio is muted by default. Putting audio in CSS or using preloading is not suitable here because I donโ€™t want to load it while loading with the rest.

I'm looking for the perfect method for loading audio at runtime , (after the checkbox is checked, it can be 20 minutes after the application opens), given the list of audio elements.

The list is already in the allSounds variable. I have the following sound on a webpage (there is more):

  <audio preload="none"> <source src="sound1.mp3"> </audio> 

I want to keep the same HTML, because after the second visit I can easily change it (this works fine with server-side HTML generation)

  <audio preload="auto"> <source src="sound1.mp3"> </audio> 

and it works.

Once the option is enabled, I want to download sounds, but not immediately play them. I know .play () loads sounds. But I want to avoid the delay between pressing a button and the corresponding feedback sound. Better not to play sound than to linger (in my application).

I made this event handler for loading sounds (it works), but in the chrome console it says that the download was canceled and then restarted. I donโ€™t know exactly what I am doing wrong. Is this the right way to make load sounds? What are other ways? If possible, without changing the HTML.

 let loadSounds = function () { allSounds.forEach(function (sound) { sound.preload = "auto"; sound.load(); }); loadSounds = function () {}; // Execute once }; 

here is the playSound function, but not very important for questions

 const playSound = function (sound) { // PS /* only plays ready sound to avoid delays between fetching*/ if (!soundEnabled)) { return; } if (sound.readyState < sound.HAVE_ENOUGH_DATA) { return; } sound.play(); }; 

Side question: should there be preload="full" in the HTML specification?

See also: Preload the mp3 file in the queue to avoid delays in playing the next file in the queue

how can we play audio with text highlighted word to word angularjs

+7
javascript html media
source share
4 answers

For audio caching, Base64 needs to encode your MP3 files and run a Base64 encoded MP3 file with data:audio/mpeg;base64, Then you can preload / cache the file using css using something like:

 body::after { content:url(myfile.mp3); display:none; } 
+2
source share

I think I just used preloading without attracting an audio tag at all ...

Example:

 var link = document.createElement('link') link.rel = 'preload' link.href = 'sound1.mp3' link.as = 'audio' link.onload = function() { // Done loading the mp3 } document.head.appendChild(link) 
+2
source share

I am sure I have found a solution for you. As far as I know, your sounds are additional functionality and are not required for everyone. In this case, I would suggest downloading sounds using pure javascript after the user clicks the unmute button.

A simple sketch of the solution:

 window.addEventListener('load', function(event) { var audioloaded = false; var audioobject = null; // Load audio on first click document.getElementById('unmute').addEventListener('click', function(event) { if (!audioloaded) { // Load audio on first click audioobject = document.createElement("audio"); audioobject.preload = "auto"; // Load now!!! var source = document.createElement("source"); source.src = "sound1.mp3"; // Append src audioobject.appendChild(source); audioobject.load(); // Just for sure, old browsers fallback audioloaded = true; // Globally remember that audio is loaded } // Other mute / unmute stuff here that you already got... ;) }); // Play sound on click document.getElementById('playsound').addEventListener('click', function(event) { audioobject.play(); }); }); 

Of course, the button should have id="unmute" , and for simplicity - the body id="body" and the sound button id="playsound . You can change this, of course, to suit your needs. After that, when someone click unmute, the sound object will be generated and dynamically loaded.

I have not tried this solution, so there may be some small errors (hopefully not!). But I hope this gives you an idea (sketch) of how this can be accomplished using pure javascript.

Do not be afraid that this is pure javascript, without html. This is additional functionality, and javascript is the best way to implement it.

+1
source share

You can use the Blob URL view Blob URL file

 let urls = [ "https://upload.wikimedia.org/wikipedia/commons/b/be/Hidden_Tribe_-_Didgeridoo_1_Live.ogg" , "https://upload.wikimedia.org/wikipedia/commons/6/6e/Micronesia_National_Anthem.ogg" ]; let audioNodes, mediaBlobs, blobUrls; const request = url => fetch(url).then(response => response.blob()) .catch(err => {throw err}); const handleResponse = response => { mediaBlobs = response; blobUrls = mediaBlobs.map(blob => URL.createObjectURL(blob)); audioNodes = blobUrls.map(blobURL => new Audio(blobURL)); } const handleMediaSelection = () => { const select = document.createElement("select"); document.body.appendChild(select); const label = new Option("Select audio to play"); select.appendChild(label); select.onchange = () => { audioNodes.forEach(audio => { audio.pause(); audio.currentTime = 0; }); audioNodes[select.value].play(); } select.onclick = () => { const media = audioNodes.find(audio => audio.currentTime > 0); if (media) { media.pause(); media.currentTime = 0; select.selectedIndex = 0; } } mediaBlobs.forEach((blob, index) => { let option = new Option( new URL(urls[index]).pathname.split("/").pop() , index ); option.onclick = () => console.log() select.appendChild(option); }) } const handleError = err => { console.error(err); } Promise.all(urls.map(request)) .then(handleResponse) .then(handleMediaSelection) .catch(handleError); 
0
source share

All Articles