I wrote a small language learning app for my own use which plays audio recordings with howlerjs. The audio is played in a loop, when the end is reached, it just restarts until the user intervenes.
To the Problem: When I turn off my phone (standby) the audio file still plays - like it should - but is not restarted ones the end is reached.
Is there a JavaScript trick I can use to restart it even when my phone is off? Or can I change a setting in Chrome/Firefox to stop Chrome/Firefox from preventing a restart?
I didn't see, that howlerjs has a loop attribute, one can set to true. I always restarted the audio again via code, when it was finished. Thanks to Kaiido it works now.
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
Some mobile sites, like YouTube and Twitch, will pause html <video> elements if other apps (like Spotify, or a podcast player that puts media controls in the notifications) start to play audio.
Interestingly, these don't just take audio focus - they also stop playing if they can't obtain it. As an example, I'm using firefox for android, so I tried disabling its ability to take audio focus with adb:
cmd appops set org.mozilla.firefox TAKE_AUDIO_FOCUS ignore
But now, videos just immediately pause, since it can't pause the other audio source.
How do the sites detect this? I attached a debugger to my phone and looked through the docs but I didn't see anything in either place.
I'm not sure about how this specific flag "TAKE_AUDIO_FOCUS" is interpretted, but modern Android focus management is based on "requesting" (not taking) audio focus. Apps would request it and either get it immediately or listen for updates from the AudioManager as to whether they got it. Similarly they will get updates when someone else requests (and then subsequently receives) focus, and they should react accordingly (i.e. pause/duck themselves). Presumably the apps you mention have asked for audioFocus and were denied it and then hadn't received focus yet, so they just chose to stay paused rather than start playing audio/video and blare out over the app that hadn't released focus yet.
source: https://developer.android.com/guide/topics/media-apps/audio-focus
I want to generate a "beep" sound every minute on the web browser.
For the "every minute" thing I rely on setInterval() since there is a seconds counter and I want to update the second counter every second. I am well aware of the non-real timing facts going on but it's not a big deal in this case.
The real deal is generating a short notification sound after every 59 seconds.
I am currently doing it using the audio API.
As follows:
a=new AudioContext();
function pitar(volumen, frecuencia, duracion){
v=a.createOscillator()
u=a.createGain()
v.connect(u)
v.frequency.value=frecuencia
v.type="square"
u.connect(a.destination)
u.gain.value=volumen*0.01
v.start(a.currentTime)
v.stop(a.currentTime+duracion*0.001)
}
pitar(999,220,300);
What is the problem?
This is not working on Safari.
This is not Working on chrome on iOS.
Specific errors:
Console log says for Chrome: "The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page."
It basically just works as expected on Firefox.
I tried to do it by checking if the AudioContext is available in the current browser and using a base64 encoded mp3 beep when it's not, following this older way:
How do I make JavaScript beep?
But it still won't work without the user interacting (id est. clicking somewhere on the page.)
I can somehow force the user to click once, by putting a button saying something like: "Hey, let's start".
But that will enable the click only for the first time, and not for every other minute.
I thought about creating a one minute audio file with 1 second beep and 59 seconds in silence and play it on replay. But even that would be problematic, since the beep would not be synchronized with the counter.
Another solution, would be to record a video and play that on loop.
Regarding this question - Play infinitely looping video on-load in HTML5 - it also won't work since autoplay requires muted on some browsers.
Any way of hiding the controlers and creating a custom javascript play button?
Or do you know any better way to achieve this?
Chrome apparently stops updating a page when you go idle (i.e. when the screen saver comes up).
My problem is I've written an alarm app, and it doesn't work because the Javascript stops running when the computer goes idle. Is there any way around this?
Update: After testing a few different things, it seems that Chrome doesn't stop updating a page, it just stops rendering it. So for my problem (an alarm app), this is solved.
Are you using requestAnimationFrame? I know Chrome explicitly pauses those callbacks, but it may not also pause setTimeout.
I've been evaluating HTML5 audio on iOS 4 and have been trying to understand its limitations. From what I can tell...
It is possible to play audio in the background
It is not possible to fire JavaScript events in the background upon track completion
It is possible to fire JavaScript events while the screen is off, but Safari must be in the foreground (before turning the screen off)
My goal for this current project is to create a dynamic playlist that will continue to fire events and move to the next track even while Safari is not in the foreground. Is this possible with the current way HTML5 audio works on iOS?
I am curious about how the chaining of JavaScript events works on iOS if anyone has additional information. It seems that you are allowed to queue back to back sounds, but it must happen shortly after a "human" function happens (for example, tapping an element). Anything else that tries to queue a sound outside of this human function is denied the ability to play.
Also...
Is it even possible to have events that fire to move a real iOS application to the next track? It seems as if the application is only allowed to finish its current audio stream and then it goes into an idle state. Just trying to figure out all the angles here!
This is quite an old question, so I'm not sure if you've found an answer already or not.
One thing I know is that an audio clip cannot be played via JavaScript on mobile Safari.
Autoplay audio files on an iPad with HTML5
The only way to make audio play, is through a click event. This wasn't the case on 3.x, but on 4.x it is. This is because Apple doesn't want the webapp to download audio on a 3g connection programmatically, so they force the user to initiate it.
I would think that if all of the tracks were started downloading (cached), then it may be possible. I would try forcing the user to start one track, and at the same time call .load() on all of the other tracks (in the same click handler). This will force the iOS device to start downloading the audio tracks, and you may be able to play the next track (not sure though).