There seems to be an issue with the SoundCloud SDK when used on any mobile browsers. The track doesn't play until I pause and then resume.
SC.stream(trackInfo.url,function(sound){
sound.play();
});
Is this a known issue/behavior? I first thought it's an issue with Android, but I got the same behavior when tested on an iPhone.
EDITED
I thought this might be an async loading issue, but even if I don't call sound.play() right away and have it triggered by user clicking play, it still doesn't work. I have to call play > pause > resume. The good news is that once user take these actions, all subsequent tracks in the custom playlist (non-SoundCloud) can continuously play without any user having to take any actions.
Ok, it seems like the issue is the async loading after more testing. User has to explicitly click play after it's loaded. I got a little thrown off before because there was an unrelated issue that was causing the pause/resume effect. Once user has triggered the action, it's able to play all tracks without any further action from user.
Related
I would like to have a web page being able to act like a music player.
The user enqueues a list of audio files (hosted on the server) and they start playing. When the first audio is over, the second begins, etc, until the last one.
I was able to easily implement this functionality using an <AUDIO> element, and replacing its src attribute with Javascript by adding an event listener on the ended event.
The problem is that this does not work consistently on mobile, because once the screen is locked, the Javascript does not keep executing. It may work for one song or two, but at some point it stops "skipping" to the next audio track.
From my understanding, this behaviour is caused by the fact that mobile browsers stop the Javascript event loop after some time to save battery when the screen is locked. I am aware of the Screen Lock API, I assume keeping the screen always on would solve my problem, but I don't want to keep the screen always on.
I could delegate playing audio files to a web worker, which should theoretically keep running in the background. Still, I'm not sure it won't be stopped when the screen is locked, and most importantly I am not sure it can even play sounds.
Is there anything similar to the Screen Lock API that allows me to ask permission to keep scripts executing also when the screen is locked?
If not so, how could I overcome this problem?
After some research, I discovered that the act of killing the javascript event loop is highly browser-specific.
Chrome for Android seem to let the playback run indefintely.
Firefox for Android is stricter, and kills the event loop.
The System Wake Lock looks like a promising API for solving the above problem. At the moment, the W3C is still in process of collecting use cases in order to be able to define a new standard:
https://github.com/w3c/system-wake-lock/issues/4
I have an html5 audio player on my page that streams from my icecast server, all working OK. However, when people block their phone there's no metadata, only the play button that iOS/Android offers.
Is there a way to show something like 'Glaciar's livestream', like when the Spotify app shows the song's title and artist? I'm using PHP and Javascript apart from HTML and CSS.
Thanks in advance!
You can use the Media Session API to customize what's been shown on the lock screen.
But it is not supported by Safari which means you can't use it to customize the lock screen on an iOS device.
I just came along the same issue. Our Webapp would not display anything on the lock screen even though audio was playing. This is what I just found out:
We are setting up an new Audio() element in javascript - within the user interaction we call audio.load(). Then we wait for the canplay event to fire and with that event handler, we call audio.play(). When the phone now gets locked, there is nothing shown on the lock screen.
However, when we add audio.play() directly after audio.load(), so it is called within the same user interaction, everything shows up fine on the lock screen. So it seems like, it matters if audio.play() is called within a user interaction.
Some more background in case someone wonders why we are not calling play within the user interaction: We usually use an audio context (that is unlocked within a user interaction) and just started to fall back to an audio element, due to numerous audio related bugs in safari.
I'm recording audio using getUserMedia, then allowing the user to click a button to listen to either the recording or another buffer. This has all worked fine for a year, so I don't think I'm violating any of the rules that cause AudioContext to be suspended. And, anyway, I'm testing the AudioContext to make sure it isn't suspended in my button handler.
This has all been working fine on all modern systems with many browsers. However, this is not playing the audio in Safari 13 in iOS. It will return from the promises as if it were playing audio, but nothing sounds until I call getUserMedia again.
As an experiment, I put the following line on the top of my button handler:
navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: {ideal: false},
}
});
And it works!
But, why? I'm not comfortable with that solution because I'm not sure why the browser wants that. It doesn't make sense to me that I'd have to request the microphone to play any sound.
The only clue I have is that once I do the getUserMedia I keep the recording open on Safari (I do that because Safari has a time out - when I request the mic, it pops up a dialog to the user to allow the mic. Sometimes it might take the user 90 seconds to get around to pressing "record", and if I don't leave the mic open it pops up the dialog again.)
Anyone have any idea what is going on? And, I haven't been able to find any technical write up of Safari and audio. Is there anything beyond the standard MDN?
IOS13 also broke one of our applications. It's been working fine for years. No errors are thrown and we are not violating any rules. Here is the link to my post:
Has IOS13 broken <audio> tags used as audio buffers connected to the audio context?
Even though it is a different use of the api, I believe it is related. Apple clearly broke something on this new release.
This was confirmed to be a bug in Safari 13 and was fixed in a maintenance release. We haven't heard any more reports from the field so I guess it auto updated for everyone.
It seems to be a common complaint that mobile devices won't autoplay video or audio. According to the Apple Developer Library it is disabled on purpose:
In Safari on iOS (for all devices, including iPad), where the user may be on a cellular network and be charged per data unit, preload and autoplay are disabled. No data is loaded until the user initiates it. This means the JavaScript play() and load() methods are also inactive until the user initiates playback, unless the play() or load() method is triggered by user action. In other words, a user-initiated Play button works, but an onLoad="play()" event does not.
What is allowed is for a direct user action to trigger the play event. My problem is that I have thumbnails of videos which when clicked load a video element in their place and need to play once they are loaded. On mobile the user has to click twice to make the video play which is not good. I am frustrated because my user actually is triggering a play action but there are a few other events which take place in between. I started testing a different user-triggered-event to see what the scope or limitations of what apple calls a "direct user action" are.
I found that this code triggered the play event:
$(".clickElement").click(function(){
$("video").get(0).play();
});
while this did not:
$(".clickElement").click(function(){
setTimeout(function(){
$("video").get(0).play();
},0);
});
the same went for different timeout durations and when setInterval was used instead.
My question is what / how does apple define a direct user action? Obviously timeouts and intervals aren't direct enough. Is there a way for me to trigger the play event "directly" from the user and allow enough time for my video element to enter the page?
I'm trying to play audio using a HTML5 Audio tag on my phone.
I've loaded the sound but when I run the .play() command, nothing happens.
I made the default controls visible so that I test by pressing that play button and that one works and the sound plays.
I've also tried playing the sound by executing the javascript from the address bar and that works aswell.
The code I'm using to play looks something like this:
setInterval(function(){
if(blahblah){
document.getElementById("player").play();
}
},500);
To make sure that it even tries to play the sound, I put an alert after it, like this:
setInterval(function(){
if(blahblah){
document.getElementById("player").play();
alert("Played!");
}
},500);
I saw the alert, but no sound was played.
Thanks for any help :)
Most mobile devices will only allow you to play audio when it is the result of a user interaction. If you put your play code into a button click event, it should work (assuming you have no other bugs in the code), but the device is preventing your audio from playing from inside setInterval because it doesn't think it has the user's permission to play it.
What I do now, and I admit this is a workaround, is I play and immediately stop the audio inside my button click event, and then call setInterval. It works--for now--because the device thinks it has been granted permission to play that audio by the user, even if I trigger it later. The code inside my button click event looks like this:
document.getElementById("player").play();
document.getElementById("player").pause();
setInterval(function(){
document.getElementById("player").play();
}, 500);
Keep in mind that on mobile, it may not play nearly as smoothly as it does on your computer. Seek alternative approaches where possible.