Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chrome autoplay policy changes #939

Open
robbue opened this issue Apr 19, 2018 · 112 comments
Open

Chrome autoplay policy changes #939

robbue opened this issue Apr 19, 2018 · 112 comments
Milestone

Comments

@robbue
Copy link

robbue commented Apr 19, 2018

Chrome 66 have changed its autoplay policy:

An AudioContext must be created or resumed after the document received a user gesture to enable audio playback.
https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio

mobileAutoEnable could be updated to adjust for Chrome (desktop and mobile) as well.

@goldfire goldfire added this to the 2.1.0 milestone May 4, 2018
@inear
Copy link

inear commented May 6, 2018

Maybe a subject of its own, but could we somehow register the start time of a play call and use that to seek to the offset position when the AudioContext is resumed? This to avoid having all created instances fire of at the same time when resumed. Sounds are very often timed to visual events which is so frustrating with the new policy. This would be a very good reason for more devs to use this library.

@TxAg12
Copy link

TxAg12 commented May 6, 2018

Maybe we could organize to unbreak the internet? I cannot even imagine the economic cost of everyone--most working for free--spending time to hack around these content restrictions.

@sammcgrail
Copy link

Hoping for a fix in 2.1.0 ! Gosh darn it chrome you broke my little toy app!

@goldfire
Copy link
Owner

goldfire commented May 8, 2018

FYI, the mobileAutoEnable system should still be working on desktop Chrome as well. I just marked it for 2.1.0 as it now makes sense to update the API naming since this isn't a mobile-only issue anymore. If anyone is seeing issues with this not working with Chrome desktop then that would be a more urgent matter.

@dangrima90
Copy link

@goldfire I'm having issues due to this Chrome update. In the application I'm working on every time a sound is loaded I'm seeing the warning mentioned above, which results in the sounds not playing.

Since in Google's autoplay policy (https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio) it is mentioned that muted autoplay is allowed I've tried to load the application sounds with the mute setting set to true - but so far I didn't see any difference. I don't know if there's any workaround at the moment, or maybe I'm doing something wrong.

Since you mentioned mobileAutoEnable, am I correct in assuming that the mobileAutoEnable is enabled by default? And if so, sounds are played once there's the first user interaction?

@goldfire
Copy link
Owner

goldfire commented May 9, 2018

There is currently an open Chromium report about this that is picking up a lot of support. If we can at least get them to add a way to detect this it would make it much easier to handle within the library: https://bugs.chromium.org/p/chromium/issues/detail?id=840866.

@dangrima90
Copy link

Thank you for your reply, let's hope we'll have a way forward soon. I'm a bit disappointed with this change but that's the life of a developer I guess haha.

@inear
Copy link

inear commented May 9, 2018

It's not just the problem with resuming the AudioContext, it's also about what should happen when it does. Right now all the sounds that I've tried playing before it's resumed (showing the warning) is played in the same time when resumed.

@jmo84
Copy link

jmo84 commented May 9, 2018

Everybody go to the bug report and vote for it. https://bugs.chromium.org/p/chromium/issues/detail?id=840866

@Sieabah
Copy link

Sieabah commented May 12, 2018

@goldfire I believe there is a way to test it by checking the state of the AudioContext.

From their docs there is this:

To detect whether browser will require user interaction to play audio, you can check the state of the AudioContext after you've created it. If you are allowed to play, it should immediately switch to running. Otherwise it will be suspended. If you listen to the statechange event, you can detect changes asynchronously.

At least that way people using Howler will be able to inspect the state. I've been looking through how howl.state() works and if we had access to the raw state value from the audio context it'd allow us to check if interaction is required.

Edit: As it currently stands, state() only returns if it's loaded essentially and playing() will be true despite it not actually playing.

Somewhat related

@goldfire
Copy link
Owner

@Sieabah Unfortunately, this behavior is not consistent across browsers, which is why howler tries to resume the audio context on play. However, if the audio is still locked, the promise on resume neither resolves nor rejects, essentially leaving the state in limbo. I'm sure we can find a way to work around this, but I'm hoping we hear something soon on what/if anything is going to be changed.

@Sieabah
Copy link

Sieabah commented May 12, 2018

@goldfire Right, but you could detect this issue by detecting (for chrome) whether the state is suspended or not immediately after play? I'm all for the universal solution, but currently there is no way to use howler is a reactive way.

I'm against google making this huge change just because they're a huge browser, but I don't believe they're going to back down on this. Is there any reason why you use resume() and not play() to check if audio is locked?

Off the wall solution, would it be possible to play a tiny sound file that is dead silent at init to see if audio is locked?

@goldfire
Copy link
Owner

I just added this Chromium bug relating to the issue with AudioContext.resume: https://bugs.chromium.org/p/chromium/issues/detail?id=842921

@goldfire
Copy link
Owner

Chrome has reverted this change on Web Audio (not on HTML5 Audio) and has said it will come back in Chrome 70, due for release in October. The AudioContext issue is also fixed in Chrome 68.

@Sieabah
Copy link

Sieabah commented May 16, 2018

@goldfire Great news!

@robbue
Copy link
Author

robbue commented May 16, 2018

Good news, but only delays the massive side-effects of this change until October. But at least we (and Chrome) have some time to smooth things out.

@goldfire
Copy link
Owner

Commit 310736b updates mobileAutoEnable to work on Chrome as well. I'm going to keep this open though as the naming really needs to updated as a breaking change since this will no longer only apply to mobile.

@Sieabah
Copy link

Sieabah commented Jul 12, 2018

@goldfire Where does howler stand in supporting the new chrome autoplay api changes?

@abelsonlive
Copy link

I'm using react-howler, but I had some luck detecting instances when autoplay is blocked by checking if window.Howler.state == 'suspended'

@Sieabah
Copy link

Sieabah commented Jul 13, 2018

@abelsonlive Seems messy to check the window object directly.

@dangrima90
Copy link

Any way forward on this? At the moment the following warning is being shown in the console:

The Web Audio autoplay policy will be re-enabled in Chrome 70 (October 2018). Please check that your website is compatible with it. https://goo.gl/7K7WLu

I'm not understanding what I should do, will this be handled by howler or must the application find a solution for this?

@sajjanbalar
Copy link

Hi,

I was able to catch this error and handle it using the onplayerror handler. There is not much you can do to stop this from happening, but handling it and showing a play button (instead of a pause) and stuff like that is easy.

@goldfire
Copy link
Owner

goldfire commented Aug 9, 2018

Sorry about the delay, I've been swamped lately. I'm working on some changes to address this though.

@goldfire
Copy link
Owner

Okay, so I'm considering two different approaches here:

  1. If the audio is locked, howler just throws a playerror and discards the playback.
  2. As suggested above by @inear, the time the playback was started is tracked and then when audio is unlocked, howler either seeks to the position the sound would have been at or discards the playback if it would have already concluded.

Option 2 I think would be the most beneficial for most applications, but does anyone have any scenarios where this might be best left to the application to handle (and thus going with option 1)?

@Sieabah
Copy link

Sieabah commented Aug 10, 2018

The issue with Option 2 is you wouldn't know that the play failed unless you kept checking either after playing or in a loop elsewhere. Which creates an awkward loop of logic whereas if you errored on play you could create some popup asking for user input.

@goldfire
Copy link
Owner

@Sieabah The library would still be detecting that the audio is locked either way, that would be able to be checked at a global level.

@jmo84
Copy link

jmo84 commented Aug 12, 2018

Option 2 sounds like the best option but please keep emitting the playerror event described in Option 1. The only thing I can think of that would be a problem with Option 2 is if it adds too much code to the library.

@inear
Copy link

inear commented Aug 12, 2018

I would appreciate the functionality in option 2 to be available if possible, but could live with using a option-parameter to activate sync to intended global time for sounds that is part of a visual timeline. And use option 1 as default. With that per-sound-parameter we could use it in places where we don't know of context is created, like in cinematic intros, or after the first load. Also, we then don't magically solve the issue, but encourage devs to think twice about their solution and learn to design for the autoplay policy, because it seems like it will stick around. The option 2 is a way out for existing sites where we don't have control over the flow. Or if we just can't have an interaction point at the beginning of the experience.

@Sieabah
Copy link

Sieabah commented Aug 13, 2018

@goldfire So the intended solution is to have code which checks every x seconds or so to see if it's locked and provide a prompt? How would you trigger all the sounds to play again or would Howler automatically do that?

It just seems messy to have check at the global scope.

@Tectract
Copy link

Unsubscribed. You guys are bad software devs.

@dangrima90
Copy link

dangrima90 commented May 30, 2019

@Tectract I think you need to accept the update to the policy and deal with it. All that's needed is a simple user interaction - it won't break your application.

I understand that the change did break your application, but it's not the end of the world. As been mentioned by others there are plenty of reasons why this policy has been put into place. Speaking from my experience - yes it was annoying as it did break the applications I've built but at the end of the day it's not just Chrome that's implementing this policy. This policy has been in place on Apple for a while and also there's been a discrepancy between desktop and mobile devices with regards to this policy.

Like it or not at least now we have consistency with different devices and browsers - it's not difficult to handle. The way I have solved it is to simply have a sound off/on button on your site which is always off by default. Therefore for a user to switch on the sound they have to click and you're done.

I'd call that a simple solution with a small compromise - whether you like the implementation is another matter 😄

@TheBigK
Copy link

TheBigK commented Jul 17, 2019

I'm running into the same issue. Chrome won't let me play music without having user click on something. Also; audio stops abruptly when playing and I've no clue if it's a related issue.

@Sieabah
Copy link

Sieabah commented Jul 17, 2019

@TheBigK Did you read the thread? It's a feature of chrome not a bug.

As for it stops abruptly, are you sure you're not triggering a stop event or your audio file isn't corrupted? Think that may be a separate issue (new issue on this repo).

@Tectract
Copy link

It's a feature of chrome not a bug

That's laughable, it's a huge bug. This is one of the biggest engineering screw-ups I've seen in a long time. In order to "disable autoplay video", Chrome devs instead decided to disabled autoplay audio, thereby breaking thousands of gaming and financial applications over the SCREAMING OBJECTION OF DEVELOPERS, while failing to actually BLOCK AUTOPLAY VIDEO, and doing it in a way that there's no easy way to permanently whitelist any site.

Oh yeah, if that wasn't bad enough, then they rubbed salt in the wound by excluding their own web properties from this bug:

https://arstechnica.com/gaming/2018/05/chromes-autoplay-video-blocker-is-accidentally-killing-web-based-games/

@mike7a
Copy link

mike7a commented Jul 17, 2019

There's a million ways to workaround this. Why are you so bent outta shape?

@Tectract
Copy link

Not really. It broke my application that's why. Chrome devs are idiots who introduce new bugs instead of properly fixing old ones, then they dust off their hands, "Job well done! Oh wait, just exclude our own sites, because that breaks everything hahaha!". It's insulting to developers and their users whose time gets wasted, and it degrades the web experience of millions of people and makes the internet less useful, that's why.

How can I make my application play notification sounds to alert them about trades on their accounts after long periods of inactivity, @fallingC0de? They have to come and click on the page again. They can't whitelist my site. It's a BUG, not a feature. I still have TONS of autoplay video popups modal spam about newsletters on EVERY SITE, they can't fix that, but they can break my bespoke trading platform. THANKS CHROME, MORE BUGS PLEASE!

@jjavierdguezas
Copy link

please, I and I'm sure a lot of colleagues are subscribed to this issue to be up to date with any change on the subject, do not spam this with personal opinions or discussions that do not contribute anything, just please

@mike7a
Copy link

mike7a commented Jul 17, 2019

So, after long periods of inactivity the sound is muted like it was when they first come to the page? How long does the inactivity have to be for that?

@Tectract
Copy link

Tectract commented Jul 17, 2019

So, after long periods of inactivity the sound is muted like it was when they first come to the page?

Yes, Chrome auto-mutes your page again if a certain activity indicator score goes too low. Or if they just didn't click on the page initially. I could make a button that is MUTED at the beginning that they would have to un-mute with a click, I think, but it would only be temporary.

How long does the inactivity have to be for that?

Could be periods of unknown length, days or even weeks potentially. The sound is supposed to alert them to come and look because a trade has occured, or to notify you while you are around the house not at the computer. This is a feature my customers WANT and LOVE, but chrome broke it. What I want to do is specifically what they disabled, instead of actually disabling autoplay video.

@Sieabah
Copy link

Sieabah commented Jul 17, 2019

Yes, Chrome auto-mutes your page again if a certain activity indicator score goes too low. Or if they just didn't click on the page initially. I could make a button that is MUTED at the beginning that they would have to un-mute with a click, I think, but it would only be temporary.

You sure about that? I've accidentally left my site playing for a very long time and it was still playing >24 hours later. Would greatly appreciate a link to the source to prove your point. Otherwise you're making claims which are false.

This is a feature my customers WANT and LOVE, but chrome broke it. What I want to do is specifically what they disabled, instead of actually disabling autoplay video.

Grow up and deal with it. Stop bickering about it here when we already agree with you it's a dumb feature. You're being a broken record with your immature approach to this topic. We all get it, your precious application is broken, so did ours. How did we fix it? We worked around their dumb user engagement. If you want your app to be fixed you have to do it that way. You can't refuse on principle to do it and complain that it doesn't work, at least not here of all places. Go complain on the google forums like you do here and see how that works out for you.

I've given you multiple ways to fix the problem for yourself and it's your own fault at this point to not adjust to their dumb policy. Literally having a toggle for notifications sounds is all you need, and if you even read the spec once a user approves your site for sound enough times you don't need to ask for permission! So if your users come back to your page daily and enable notifications at a point you don't need to ask them anymore. So do that or just be quiet, I personally don't care anymore about how your trading platform doesn't notify your users.

Just keep your repetitious opinion to yourself at this point, it's clearly not forwarding any useful discussion besides giving you a platform to vent.

@Tectract
Copy link

Tectract commented Jul 18, 2019

Grow up and deal with it. Stop bickering

What a shitty dev you are. God I'm glad I don't use any software that you administer. If my employees said that to someone in a support ticket on my repos, I'd fire their asses so fast their head would spin.

@Tectract
Copy link

If you guys really want to end this thread, tell us all the best ways around this bug, in detail, use references if you have to. Tell us how to re-enable sound once it gets turned off by Chrome, and all the hacks for preventing that, or seemlessly making the problem go away. Tell people it's a bug, not a feature. They set out to stop autoplay video and instead they broke background sound, even after tons of devs told them "this is the wrong way to fix this, you're gonna break all our sites". That's a bug not a feature.

@Sieabah
Copy link

Sieabah commented Jul 31, 2019

When you're able to convince the goliath that is Google that they're wrong, be my guest. So far they haven't ever backed down even after all games on the internet broke. Calling me a shitty dev for working around the playground Google has made for all of us is one who isn't wasting time fighting a battle that literally cannot be beaten. Have you not seen the autoplaying audio/video proposal that would ban it entirely by law?

All I know is my applications work again within the dumb constraints put out ahead of me, does yours?

What a shitty dev you are. God I'm glad I don't use any software that you administer. If my employees said that to someone in a support ticket on my repos, I'd fire their asses so fast their head would spin.

I'm being realistic instead of complaining on an issue that Google doesn't even look at. I've agreed with you about this policy but that goes out the window when you want to huff and puff and act like you're the golden standard of what's right. What you're doing is not productive in the slightest and insulting your way to a solution shows that you'd be a pretty awful manager. Maybe your employees tell you otherwise so you don't lash out and fire them? Regardless this isn't the place to bicker, insult, and argue. It's a place to come up with solutions for people running into this issue. The discussion you're looking for is on google's own issue tracker with regards to this issue. I've participated there more than you have so I'm glad you're making an enemy out of, hope you feel good about yourself.

@Tectract
Copy link

Cool story bro. Fact remains that they didn't disable autoplay, they only broke games and financial apps. It's a bug not a feature. People who call it a feature are useless yes-men. Like you.

@RichardGale
Copy link

RichardGale commented Jul 31, 2019

Can we close, mute or stop comments on this issue, I'm getting tired of this discussion that isn't helping progress the issue.

@st-h
Copy link

st-h commented Jul 31, 2019

@RichardGale at the top of this thread there is a button which should be labeled something like unsubscribe. That might be the easiest/fastest option to resolve unwanted notifications from a single issue. Granted that does not change the fact that most comments here are totally unrelated to howler itself...

@Tectract
Copy link

I'm tired of people saying "That's not a bug, it's a feature!". And then brushing off the fact that thousands and thousands of people's websites are now broken, with no possible solution, ON PURPOSE BY THE BROWSER DEVS.

@RichardGale
Copy link

You're probably also tired that Microsoft stopped supporting MS DOS ON PURPOSE and broke THOUSANDS and THOUSANDS of MS DOS games. I guess those devs either stopped writing for MS DOS or moved with the times and switched to Windows.

@Tectract
Copy link

DOS still works.

@hmans
Copy link

hmans commented Feb 23, 2020

If my employees said that to someone in a support ticket on my repos, I'd fire their asses so fast their head would spin.

Howler is not commercial software, and GitHub Issues is not a support ticket system.

@Tectract
Copy link

I'm still angry about this MAJOR BUG that they introduced into Chrome. I'm just an end-user here to say "shit is broken, because of a major upstream bug". Anyone who calls breaking sound on pretty much every site out there, for all use-cases, a "feature", is a tool.

@AlGantori
Copy link

AlGantori commented Apr 16, 2020

Can someone show some code to detect this situation, or help me fix below, thank you.

I added listening for onplayerror which seems to fire/emit and I am able to show a pause button. However when the user presses the button and the code attempts audio.play no sound plays out, I run into a loop?

Even though intellisense in VSCode does not show it I am treating Howler.play to return a promise.

What did I miss?

There is apparently a couple of parameters with onplayerror accord to the documentation, how do I retrieve those?

  // 20160820
    PlayOne(Media: string) {
        Log.Called(this, "PlayOne", "Media is", Media)
        return new Promise((resolve, reject) => { // return a promise
            this.audio = new Howl({ src: [Media] });                     // create audio wo/ src
            //
            // https://github.com/goldfire/howler.js#onloaderror-function
            this.audio.on('loaderror', () => {
                Log.Event(this, "AudioPlayList", "loaderror")
                reject(Media);
                // reject;
            });
            this.audio.on('onplayerror ', () => {
                Log.Event(this, "AudioPlayList", "onplayerror")
                resolve(Media);
                // reject;
            });
            this.audio.on('end', () => {
                Log.Event(this, "AudioPlayList", "audio ENDED")
                resolve(Media);
                return resolve;
            });

            return this.audio.play()
        });
    }

from the View controller of the application I catch the failed promise like so to tell the view to handle and react by displaying the pause button.

                // -) Invoke the Sound playing
                let Sound = this.Slides.Audio(this.Slides.Index)
                this.AudioPlayList.Play(Sound).then(data => {
                    Log.Promise(this, "PlayIndex", "AudioPlayList.Play", "Done Playing")
                })
                    .catch(error => {
                        Log.X(this, "PlayIndex", "AudioPlayList.Play", error)
                        // https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#best-practices
                        this.UQSView.RequireUserGestureToPlay()
                    })

image

Feel free to fix my "promise" handling and coding I am just hacking my way to JS via TS. One minute I think I understand Promises and then the next minute it's like I never heard of them before.

@AlGantori
Copy link

@goldfire thank you for providing a component that works.

I think you mean by "The library would still be detecting that the audio is locked either way, that would be able to be checked at a global level." that option 1 would be available as well?

IOW, there is a simple mean for the app to detect the situation (a user interaction is required by chrome) and the app retry or create a new howler.play() upon the user click some play/pause/resume button?

Thank you for clarifying, that's the behavior I am trying to fix/code the above reply/request.

@stefan-reich
Copy link

So kindly tell me, is there still any way to reliably play a notification sound in a Chrome background tab?

I have to chime in with the Chrome critics in saying that Google should at least have given us an option to declare a website "trusted" so it can play sound at any time.

@Gavitron
Copy link

hi, so I was trying to resurrect the venerable hypnotoad site, which is basically an animated frog and a background sound that needs to play as soon as the page loads, with zero user interaction. How can I make a page play a sound as soon as it is the active page, without having to design an onerous UI forcing the user to click? this site was literally a gif & an mp3 before the Chrome developers removed the feature. can I use an onHover event instead of an onClick?

@stefan-reich
Copy link

@Gavitron No, user needs to click.

@ltakato
Copy link

ltakato commented Dec 10, 2020

@stefan-reich did you find a solution? I'm trying to achieve an issue like you said. It works after clicking, but when user refresh page, browser asks again for interaction/gesture.

@stefan-reich
Copy link

stefan-reich commented Dec 10, 2020

@ltakato I don't think there is a solution... user needs to click first. You can try to never actually switch pages, for example by using a frame set or by converting the website into a single page with JavaScript reloads (hard but possible). That you keep a page loaded and thus Chrome remembers that the user has clicked.

If user presses F5... you're just lost.

@georgiosd
Copy link

Is anyone having success unlocking with the example given in the docs here? https://github.com/goldfire/howler.js#mobilechrome-playback

I can play the audio after the unlock event but Chrome is muted!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests