Audio delay on Safari Desktop - javascript

I have a page with several <audio> tags. Whenever I play the audio in Chrome (Desktop, macOS), it starts immediately, while in Safari (13.1, macOS) it waits for some time before starting playing (the weird thing is that it waits longer if they are several audio tags on the page).
I thought that the problem was with the "preload" attribute not set, so I've set it to "auto" according to the docs]1, but it didn't change a thing.
I don't want to use a 3rd party library to keep as as simple as possible.
How can I remove this delay? And why is it longer the more audio tags I have on the page?

I was not able to remove the delay completely, but I made it much better by setting preload to ="metadata". For some reason it makes files load much quicker for playback.
Chrome actually is smart about this. When the preload is set to auto, it caches around 1mb of each audio file upon page load, so it can play it quicker when you press "Play" button.
I also started listening to onwaiting event of the audio element, so I can show the preloader to make experience a little bit better.
Since Safari fires oncanplay and onplaying much sooner when the file is actually ready to play, I don't just hide preloader on this events, but after a 1.5 second timeout to smooth it out.
That's good enough for me, since the lag decreased from 30 seconds (with 10 audio elements on page) to just 1.5 seconds.

Related

Mp3 sound is delayed on phone (iphone 7) - Blazor WASM + javascript

I have blazor WASM app with "correct" .mp3 file that is played via javascript code. On the Desktop lets say its pretty instant after pressing button but on the phone its skips few ms and then it seems there is delay and its not good user experience. I tried to look up some solutions but couldnt find anything. Is there any way to solve it or its just because of phone (Iphone 7)?
sounds.js:
window.PlayAudio = (elementName) => {
document.getElementById(elementName).play();
}
*.razor:
<audio id="sound" src="#navManager.BaseUri/sound/correct.mp3" />
<button id="soundButton" #onclick="PlaySound">Click me to play "correct" sound</button>
...
public async Task PlaySound()
{
await JSRuntime.InvokeAsync<string>("PlayAudio", "sound");
}
Please see the repo and webapp:
https://github.com/Laftek/BlazorWASMPWAStaticPublish
https://laftek.github.io/BlazorWASMPWAStaticPublish/Lottie/7
Thank you any help would be much apprieciated.
This is not a Blazor issue-- it's a client browser behavior. It was once the standard across all devices, but I think newer devices have dropped some of the restrictions as audio files are no longer considered "large files."
Getting consistent media playback across all platforms has always been EXTREMELY difficult-- especially apple products, and most especially older apple products. I suspect that the sound will not start loading at all until a user action (like a button click). Then, unless you have fast data transfer, it will take some time to buffer. This was a common security feature for mobile devices to prevent sites from wasting users' data with media they didn't want.
The solution is to catch a click early on in the site's progress-- usually with a loading screen and "click here to enter." Then IN THAT CLICK HANDLER (important) you pre-start all your audio files by playing them and immediately pausing them again. Now, they will (probably) load, and when you really want to play the file, it will be loaded and ready.
Note that a simulated click will not work, so you can't just do element.onclick() after the page renders. It has to be an actual user interaction.
Javascript audio elements have various events, like canplay which let you know when enough of an audio source is loaded that you can start playing it.
https://www.w3schools.com/tags/ref_av_dom.asp
If you're lucky, Blazor has exposed the oncanplay event. Then you can use that even to enable your plaback button. I don't know if they have got around to audio events yet or not.

How to cache the video on the browser and used the cached version every time the video is played

i am using a video on my website. The problem is the video gets downloaded every time it is loaded. For eg. When the video loads for the first time the browser downloads the 5.3 mb of video. Since i am using html 5 video loop and autoplay, it loops and again downloads another 5.3mb of video. This happens every time the video is loaded.
Is there any trick to cache the video for once and used the cached version as long as the video is played.
Answered for anyone else that comes across this question.
Chrome has an option to disable the cache while devtools is open. This is set as default to unchecked, i.e normal behaviour.
If you look at the screenshot in the question, you can see in the size column "(from cache)" that although it looks like Chrome is re-downloading the video each time, it is actually getting it from the cache.

How do I host more than six html5 video players on a page?

I have a single page website on which I would like to host up to 14 videos using the html5 video player. The video files are all between 80 and 150mbs and I'm currently hosting them on AWS S3.
I'm running into a problem, however, which is that the players do not load well. Once I click play, they take often 10 seconds to start playing. Because of this, I tried turning on the preload function (i.e. preload="auto"), but this led to other problems. Because there are so many players on the page, some of the players stall -- I think because when a browser tries to download too many at once, some will stall.
In order to mitigate that problem, I setup a queue to preload the videos three at a time. That works, but now I've run into another problem: Chrome, at least, stalls giving a message "waiting for available socket...." I know from this that that is probably due to a limit on the maximum six websockets that can be open at once.
So now I'm truly stumped. I'm not sure how to guarantee that the videos start playing in a reasonable time (1-3 seconds) after the user hits play, and not max out the browser's limits. I'm starting to wonder if this just can't be accomplished given the limits of the html5 video player.
If anyone has any ideas about workaround, or ways in which approach could be altered it would be much appreciated.
So instead of turning preloading on, I would suggest you set preload to none
e.g:
<video id="myVideo" preload="none">
Think of it this way - if you set 14 fairly large videos to all download at once, so they are available immediately for the user wants them, you'll end up with no one video actually fully loaded.
If you set them to not download at all until the user requests one (i.e. clicks the play button) then there may still be a small delay. However they'll end up downloading less overall, they'll only download the videos they actually watch and the page is much less likely to crash. This is much more considerate to the user too (think those on low bandwidth/throttled connections).
However, not all browsers respect the preload="none" option and may preload parts of the video anyway. The safest possible, but more complicated way would be to put placeholder images with fake play buttons on them, which on user click dynamically inserts a video tag to the DOM. That way you can be sure no video tag is ever loaded until it is requested.

How do I stop HTML5 audio from playing even when removed from the DOM in iPad iOS7

I'm having an issue where my audio/video slide based website will play every sound file, but not stop even if it was completely removed from the DOM. This only affects iOS7 on iPad.
Why not pause the audio before removing it. I haven't tried it but it might be a work around what seems to be a bug.
document.getElementById('audioPlayerId').pause()

Is there a way to get the progress of an mp3 download on the ipad?

We are developing a Javascript web app for the Ipad that requires sounds to be preloaded before it loads. We don't know what sounds the user needs until they click on an exercise and then they need multiple sounds to be preloaded before the exercise starts.
I am aware there is no preload method, and that the download needs to be bound to a direct tap / click event. We have spent a considerable amount of time trying many combinations of adding media elements dynamically on every click (loaded with dummy sounds) and then trying to swap them with the mp3's we need at the time.
We have given up on that approach and thought we could just join the sounds into one file and move the play head to the desired ranges (contained in a JSON file). We got this working successfully on the desktop but we can't do it on the Ipad because we don't know when the sound is completely downloaded.
Even after the user initiates the sound to be played, the device has no method for checking when the sound is fully downloaded. In fact, it doesn't download the whole file unless it is playing. What we have discovered is that we can not consistently get the duration unless the play head has reached the end in a linear fashion. We have tried to check the buffered.start() and buffered.end() properties against our own duration (we have the JSON file with all the times) but as soon as we try and set audioElement.currentTime and stopTime, it just plays the whole sound from beginning to end.
We have found that the seekable property to be unreliable as well.
We are now working with ios5 and I believe that older versions work differently in regards to the duration property.
Has anyone been able to get this working?

Categories