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.
Related
I am attaching a screenshot for reference to get more elaborated idea about the problem am facing.. Kind of hell.
I am well aware about autoplay policy and have gone through possible approches which involves user interaction. Also, am not a fond of displaying any screen or button to user to make him click, never, i do not want that.
I am developing a wordpress plugin and having microphone feature which can attach to textbpx on any wordpress website, user clicks on it (user interaction) comes in.
I have also read that i need to resume suspended audio context, which am doing and as you can see in screenshot the state of audio context "running" before and after audio elements play mathod.
I am using audio element created using Audio() constructor.
Note: screenshot is a photo of mac system, I am debugging iphone xr using usb cable.
Can somebody help me out or enlighten me on what am doing wrong or there is any technical limitation.
Sigh! after a week lasted hell finally I managed to make things works.
To give an overview of solution let me first describe high level rough idea of work flow which has problem on iOS Sfari.
Problematic workflow
clickHandler --> AudioContext creation --> Playing audio using audio element.
All the audios followed by this workflow miserably failed in 'play' promise.
Solution which worked for me
clickHandler --> Play audio using audio element -> AudioContext creation --> Playing audio using audio element.
The point of interest in a solution which worked for me is you have to play audio using audio element as first line of code in 'clickHandler'. No doubt the promise still fails but subsequent audios does play.
Also, I was creating new audio element for each new audio source to be played, Which was wrong as auto-play policy imposed on 'per-element' basis. So instead of creating new audio element for each source I just create it once on page load (or whatever suits for you as one time creation) and whenever I want to play different audio file I just change the '.src' property/attribute.
So this is how It worked for me. I must mention throughout the week lasted hell, previously answered questions here and their problem specific solutions have been guiding light which gave me new perspective in a hunt for solution. Also the articles on internet, webkit , chrome, apple's documentation on Auto play policy helped a lot.
I'm facing problem with facebook video embedded on my post. My client wanted me to follow this method: https://medium.com/#BenBillups/facebook-video-embeds-that-actually-work-57037f8cdcf3
I've done all of the part except PHP code because that wasn't required by my client. Now what is happening. When page loads a play button appear to start video. On click it work just fine. It plays the video but only on desktops. The click event triggers on mobiles and tablets. But it doesn't start the video.
Please take a look at https://candylish.com/mix-and-match-swirl-cookies/ and also check in mobile. You'll see the difference.
In short, you've to click twice in mobile to start video.
Please help me sort this out.
Thanks :)
I think you are simply dealing with mobile browser's general reluctance to start playing video, when they can't determine it was directly connected to a user interaction (and therefor likely willingly triggered by the user.)
//Autoplay
FB.Event.subscribe('xfbml.ready', function(msg) {
if (msg.type === 'video') {
msg.instance.play();
}
});
This code waits for one of the SDK's events to fire and then tries to call the play method, introducing exactly the kind of asynchronism/detachment that gets this blocked, because techniques like that are often used in a malicious way.
In short, you've to click twice in mobile to start video.
That second click is "a whole different animal" altogether ... it happens on the native play button of the (now) embedded social plugin. The other script is not involved at all any more at this point, and this click is a direct user interaction that triggers the video to play, so it is allowed to work. This isn't nested into anything asynchronous or callbacks, it is straight up click => trigger play.
I don't think you will find any example using this technique where this will work differently.
Mobile browsers are more gracious when it comes to autoplay-on-page-load(!) videos, if those videos do not contain an audio track or are embedded to be muted by default. I don't think Facebook offers the latter as an option for mobile to begin with (the data-autoplay attribute does that for desktop, but is documented to not work on mobile) - so at most you could try with a Facebook video that is silent to begin with; but apart from that I'm not sure this restriction resp. when it actually gets lifted even applies here, it's probably not going to fulfill your client's requirement either.
I started typing this as a comment, but besides that it has gotten a little longer now, in this case I think it can't be done actually simply is the answer, even if it might not be a satisfying one.
I have created a Web App which plays music playlist and it works well on desktop browsers and also in mozilla and opera of android. But When I play the songs on Chrome browser of Android and I turn off the screen, it stops after playing the current song. And as soon as I turn the screen on, it starts loading the next song in line.
From my observations, what I have understood is Google Chrome browser on android pauses the javascript code from executing if the screen is turned off till the screen is not waken up again. Is there any way I can prevent my specific library from pausing? Any approach or events?
Some related this question is what I am looking for: JavaScript halts in inactive android Chrome tab
There are so many WebApps which does not stop playing music. Does it need some permissions from Google App Store?
check what happens with youtube, at least few years ago i had an awful time dealing with that and that's what proved to my client it cant be done in the given time frame and budget. that was actually device specific, on some devices it worked fine and on others it didnt. check if it happens on other devices. the only solutions i could think of ware either to prevent screen turn off (on problematic devices or all of them at the beginning), or to build an app and handle onPause event
I don't think that you can change the behaviour of the Chrome app, if they want to save battery in the background and stop the javascript, you won't reactivate it.
There are maybe some other ways to get it working.
Tell your users that they should use Firefox or Opera on their mobile device.
All apps are allowed to play or stream music in the background, so you could make or use an app for your task.
Maybe you can use the default music player app on android. Open a playlist of streams using the app. (I don't know if this is possible, because I have no android device.)
I know that is not exactly what you want, but a maybe a way to get it working.
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.
So making a HTML5 game using the new Cocos2D Javascript 3.0 that just came out. Come into a pretty annoying pain in the ass with how audio is played on iOS and iPad. My game is aiming to be cross platform, and the audio works on browser and android devices. It even works on Windows Phone!
I have tried manipulating iOS's event handler (I'm aware that it doesn't allow you to play audio unless the user interacts with the device) but previous versions of cocos2D HTML5 have suggested that it's audio engine used to support iOS with no hassle. Now, it doesn't seem to...
Also I've looked at alternatives such as Howler.js, however implementing that to work with iOS requires that I have SimpleAudioEngine, which I do not believe 3.0 has.
Can anyone recommend any solutions? I'd be happy enough if I was even able to just play the background music on iOS.
I was using this to help for anyone interested
http://www.cocos2d-x.org/docs/manual/framework/html5/release-notes/v3.0a/upgrade-guide/en
Fixed it. As I said, you can only play sounds once the user has actually interacted with the system, via a touch or click etc... I had this prior to asking my question. Seems the problem was that the audio hadn't loaded in time for the event to be triggered :D
Changed my audio to a .mp3 since it's much smaller, and wrapped my music to be played upon button entry.
var closeItem = cc.MenuItemSprite.create(
cc.Sprite.create(res.play),
playButton,
function () {
cc.log("New Game!");
this.playEffect();
);
playEffect:function() {
var audioengine = cc.audioEngine;
audioengine.playMusic(res.music, true);
}