Player.js: Chrome 66 prevents autoplay

Created on 7 May 2018  Â·  21Comments  Â·  Source: vimeo/player.js

Expected Behavior

When using the create video example prior to Chrome 66 auto play will work.

Actual Behavior

Autoplay fails to autoplay video due to the new autoplay policy.

Steps to Reproduce

Use the create video example in Chrome 66 or later with the default policy

Comment

Having the ability to override the policy is required as there is specific situations that autoplay is expected by the user

api bug

Most helpful comment

Yes, I believe the player.js library should be updated to set allow="autoplay; fullscreen" on the iframe that it generates.

From here: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes

Chrome's autoplay policies are simple:
...
Autoplay with sound is allowed if: ... User has interacted with the domain (click, tap, etc.)...
...

and

Top frames can delegate autoplay permission to their iframes to allow autoplay with sound.

which links to

https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#iframe

which shows

<!-- Autoplay and Fullscreen are allowed. -->
<iframe src="https://cross-origin.com/myvideo.html" allow="autoplay; fullscreen">

Currently even if a user clicks a thumbnail which triggers a lightbox that loads the video via player.js (which should be allowed to autoplay with sound), it will not autoplay unless muted, that's a big problem, and it can be solved by Vimeo.

All 21 comments

Hi @KnightAR -

Nothing in the example you cited sets the video to autoplay. To do that you would need to add the autoplay parameter to the options like so:

    var options = {
        id: 59777392,
        width: 640,
        loop: true,
        autoplay: true
    };

However, you are correct that once you do add that in the video will still not autoplay in Chrome 66 though it will in other browsers (like Safari). Unfortunately, it is not within our power to override Chrome's policy. Chrome only allows for muted autoplay.

Therefore, to get autoplay to work on Chrome 66, you would need to invoke the muted parameter. This can be seen here. (In place of the loop, muted and autoplay parameters, you can also use background to see the same behavior.)

Hi. the muted param has no effect at all.

All autoplay loading hangs at the very first progress event. No error event is dispatched to tell people there is a problem and to mute the player before attending playback.

The player hangs in a play state but it's paused. You have to toggle 3 times to get playback started.

The autogenerated code doesn't include

allow="autoplay"

But doing this manually doesn't help.

I have been able to work around this change, by detecting a waiting state in youtube , then toggling mute and then attempting to resume.

They don't provide an error event either which you would be able to get a promise returned to do muting fallback normally.

Vimeo , nothing works whatsoever, just hangs. I've had to temporarily turn off autoplay for vimeo. It should accept a mute call and then a play command call. And then on next page load it will start autoplaying as normally. This behaviour is working for the others (youtube,dailymotion)

@danrossi

muted autoplay should work, see jsfiddle here:
https://jsfiddle.net/luwes/1r243v7z/

allow="autoplay"

indeed has no effect because the video still has to be muted or the user has to have a high enough media engagement index.

we'll soon have a fix that will resolve the halted state where it will go in a pause state correctly, sorry for the inconvenience.

This is the solution I have come up with. I have discovered the api player is forcing muting at all times for Chrome.

This is wrong. If it does a proper promise on play , it can catch a failure. On the second page load in fact it doesn't need to be muted, this is the mistake it has made. An error event of autoplay failure would be preferable.

For both Youtube and Dailmotion I check for similar hanging on a buffer event and no playback, mute and continue playback. For Vimeo it hangs on each request and requires muting.

I have to use an Iframe first, because the api creates a dodgy wrapper which is doubling up ratio scaling, as its done outside it.

I create my iframe and add the attribute

el.setAttribute("allow", "autoplay");

I have now finally figured out a work around after hours of work.

I configure the player config with autoplay as normal. NO "muted" config other browsers can autoplay without this restriction. You don't technically need to mute at all times as I said above.

So

var options = {
        id: 59777392,
        width: 640,
        autoplay: true
    };

On the ready event, and if autoplay and chrome is detected with

(/Chrome/i).test(UA) && !(/Edge/i).test(UA)

Check if its forced to pause. Then mute and resume play.

if (this.startMuted) {
            this.vimeoPlayer.getPaused().then((paused) => {
                        if (paused) {
                            this.vimeoPlayer.setVolume(0);
                            this.vimeoPlayer.play();
                        }
                });
        }

I had a secondary play call in there that was causing problems. If I called this at any spot other than the ready event, the actual player is broken as in no progress and the play button disappears.

That code shouldn't be triggering on every page load.

I have to do another implementation of the player. And this time I need to use the wrapper. As I can't add the iframe to the body at that particular time and it causes problems.

The generated iframe doesn't generate this

el.setAttribute("allow", "autoplay");

I'm not sure if this has any effect. Because autoplay is required to be muted at all times, it will hang in a paused state.

Yes, I believe the player.js library should be updated to set allow="autoplay; fullscreen" on the iframe that it generates.

From here: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes

Chrome's autoplay policies are simple:
...
Autoplay with sound is allowed if: ... User has interacted with the domain (click, tap, etc.)...
...

and

Top frames can delegate autoplay permission to their iframes to allow autoplay with sound.

which links to

https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#iframe

which shows

<!-- Autoplay and Fullscreen are allowed. -->
<iframe src="https://cross-origin.com/myvideo.html" allow="autoplay; fullscreen">

Currently even if a user clicks a thumbnail which triggers a lightbox that loads the video via player.js (which should be allowed to autoplay with sound), it will not autoplay unless muted, that's a big problem, and it can be solved by Vimeo.

I don't believe I can inject the autoplay attribute externally unless I build an iframe before hand. Should I modify the iframe generator myself for now ? I can't seem to find where this is done. I had to revert back to building an iframe and setting up a url to it for now. The autoplay attribute needs to be added before a source is set.

@danrossi Can you explain this a bit more "I have discovered the api player is forcing muting at all times for Chrome."? Also, can you provide an example of your setup in a JS fiddle? Thanks.

It's because of the missing autoplay attribute. I have done another integration into another feature. And for some reason I am not getting a blocker requiring muting on every load. It is playing with full volume. In another integration I do , trying to look at it.

Update: I'm sorry its still doing it. it doesn't require to be muted on every load. When there is a user click to start loading the api which then autoplays there is no blocker. But without user interaction, there is a blocker and pauses.

Here is the basis of the autoplay work around. It should be working but isn't. It shouldn't be forcing to mute on each load either, Youtube does not. This hang check, setting volume and play is working for Youtube.

For some reason in this demo, play after setting the volume does nothing. The same code in another feature can mute and then play.

https://jsfiddle.net/danrossi303/omcvv1z9/8/

It seems I need to set a delay to try and attempt play again. But this blocker shouldn't be there to begin with all the time.

https://jsfiddle.net/danrossi303/omcvv1z9/9/

@danrossi setVolume returns a promise (https://github.com/vimeo/player.js#setvolumevolume-number-promisenumber-rangeerrorerror) which should then call play. Also, in your example you can set a player param of muted: 1 to avoid setting the volume manually. This will ensure autoplay will function within the updated browser autoplay policies.

I've done that here, but it seems the volume doesn't return a promise to begin playback.

I've also just noticed now I am not receiving timeupdate events either !

https://jsfiddle.net/danrossi303/omcvv1z9/12/

vimeoPlayer.on('timeupdate', function(e) {
            console.log("time", e);
});

The mute property is not the desired effect, because that means it's enabled on each page load when it doesn't need to be. A native play returns a promise if it needs to be muted.

This is the only way for higher level to know if it needs to mute or not in that paused check code.

Even with the attribute there as I mentioned, the backend player still wants it muted on every load. I am using an external iframe with the attribute enabled.

It's not doing a promise check. The promise check means it doesn't need to be muted at all times the browser is determining that with some ratio.

Youtube doesn't need muting at all times, but it will simply hang on startup, which determines the need to mute and resume.

I'll update the api source and confirm.

the allow attribute isn't being included by the api at all. It expects it in an external iframe.

@luwes, @fisherinnovation Are you ignoring @alibosworth's comment?

This is a scenario Chrome specifically allows. We need a fix in the library for this to work.

I have a custom component with a special play button & placeholder image before we actually load the Vimeo player (for performance & privacy reasons.) Clicking that play button gives us the permission to load the iframe with autoplay. But we need the iframe delegation parameters for it to work.

EDIT:
I see that the HTML from the Vimeo oEmbed API is being loaded. And I do get that you don't want to string-replace that HTML string. Is there an option to open an issue with the oEmbed API team?

Thanks for re-opening.

If I can help I would love to.

Thanks for your patience and sorry for the delay.

The oEmbed api should now return an iframe with allow="autoplay; fullscreen" by default. Hope this helps.
https://vimeo.com/api/oembed.json?url=https%3A%2F%2Fvimeo.com%2F3198167

Please let us know if something is not working like expected.

Oh my god, that was quick! Rarely have I seen such a quick fix. Thanks so much @luwes!

Hi — not sure if this is the right thread to inquire, but on http://playerjs.io/test.html the generated iframe doesn't have allow="autoplay". Am I perhaps doing something wrong as I test my embed as part of becoming player.js-compliant? Thank you!

@christianpbrink That's a different repository: https://github.com/embedly/player.js

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JohnnyWalkerDesign picture JohnnyWalkerDesign  Â·  4Comments

startupmasters picture startupmasters  Â·  5Comments

kewalter picture kewalter  Â·  5Comments

luwes picture luwes  Â·  5Comments

woodhall2k picture woodhall2k  Â·  4Comments