HTML 5 delay audio.play () on mobile devices

I just built a real-time application using socket.io, where the user "master" can play sounds on receiving devices (desktop browsers, mobile browsers). This master user sees a list of sound files and can click "Play" in the sound file.

Sound playback in browsers is instant. However, on mobile phones there is a delay of 0.5-2 seconds (my Nexus 4 and iPhone 5 about 1 second and iPhone 3GS 1-2 seconds).

I tried several things to optimize sound reproduction to make it faster on mobile phones. Right now (in the best "phase" of its optimization, I would say), I am combining all mp3s together into one audio file (it creates .mp3, .ogg and .mp4 files). I need ideas on how I can further fix / improve this problem. The bottleneck really looks like hmtl 5 audio methods like .play() .

In receivers I use as such:

 <audio id="audioFile" preload="auto"> <source src="/output.m4a" type="audio/mp4"/> <source src="/output.mp3" type="audio/mpeg"/> <source src="/output.ogg" type="audio/ogg"/> <p>Your browser does not support HTML5 audio.</p> </audio> 

In my JS:

 var audioFile = document.getElementById('audioFile'); // Little hack for mobile, as only a user generated click will enable us to play the sounds $('#prepareAudioBtn').on('click', function () { $(this).hide(); audioFile.play(); audioFile.pause(); audioFile.currentTime = 0; }); // Master user triggered a sound sprite to play socket.on('playAudio', function (audioClip) { if (audioFile.paused) audioFile.play(); audioFile.currentTime = audioClip.startTime; // checks every 750ms to pause the clip if the endTime has been reached. // There is a second of "silence" between each sound sprite so the pause is sure to happen at a correct time. timeListener(audioClip.endTime); }); function timeListener(clipEndTime) { this.clear = function () { clearInterval(interval); interval = null; }; if (interval !== null) { this.clear(); } interval = setInterval(function () { if (audioFile.currentTime >= clipEndTime) { audioFile.pause(); this.clear(); } }, 750); } 

Also considered blob for each sound, but some sounds may take minutes, so I resorted to combining all the sounds together for 1 large audio file (better than several audio tags on the page for each clip)

+6
source share
4 answers

Instead of pausing / playing, I just set the volume to 0 when it should not play, and back to 1 when it should play. Audio currentTime and volume methods do not slow down audio playback even on iPhone 3GS.

I also added a loop attribute to the audio element, so it should never be .play() 'ed again.

It was great to combine all the mp3 sounds together, because of this, these solutions may work.

Edit: audioElement.muted = true or audioElement.muted = false makes more sense.

Edit2: cannot control the volume of the username on iOS, so I have to pause () and play () the audio element, not just mute and mute it.

+1
source

I had the same latency problem when testing on a mobile phone. I found out that some HTML 5 games use for audio since games require very low latencies. Some use SoundJS . I recommend you try this library.

You can find a comparison of HTML Audio and SoundJS tag usage speed here:

http://www.nickfrazier.com/javascript/audio/ui/2016/08/14/js-sound-libraries.html

(check on mobile to hear the difference)

From my tests, SoundJS is much faster.

In fact, it is good enough for use in the game or for audio feedback in the user interface.

+1
source

Your setup works well on the desktop due to the preload attribute.

Unfortunately, here's Apple on the topic of preload :

Safari on iOS never boots.

And here is MDN :

Note. This value is often ignored on mobile platforms.

Mobile platforms compromise to save battery and data, to load media when they actually interact with the user or play software ( autoplay usually does not work for similar reasons).

I think the best thing you are going to do is to combine your tracks together, as you said, you did, so you do not need to pay the initial load โ€œcostโ€ the same.

0
source

Old question, but here is my solution using one of the answers above:

 const el = document.createElement("audio"); el.muted = true; el.loop = true; const source = document.createElement("source"); source.src = lineSe; source.type = "audio/mpeg"; el.appendChild(source); // need to call this function after user first interaction, or safari won't do it. function firstPlay() { el.play(); } let timeout = null; function play() { // In case user press the button too fast, cancel last timeout if (lineSeTimeout) { clearTimeout(timeout); } // Back to beginning el.currentTime = 0; // unmute el.muted = false; // set to mute after the audio finish. In my case 500ms later // onended event won't work because loop=tue timeout = setTimeout(() => { // mute audio again el.muted = true; }, 500); } 
0
source

Source: https://habr.com/ru/post/1215102/


All Articles