Mute video when autoplay is blocked by browser policy (#6087)

## Issue
When opening a video directly in Chrome Incognito, the video should autoplay (since that's the default Lbry setting), but it doesn't due to browser policy
https://developers.google.com/web/updates/2017/09/autoplay-policy-changes

## Changes
- We don't want to forcefully mute the video when `autoplay=true`; we just want to do it when the browser policy is applied.
- Fortunately, there is already an existing code-block for us to check that.

## Test cases
- [x] "Autoplay=Off" should not be affected.
- [x] After manually unmuting, the next autoplayed video should not be muted (this is "user interacted" opening, so the policy allows autoplay)
- [x] If manually muting, the next autoplayed video should retain user's last setting.

## Known issues
- I've seen `error` occasionally being undefined in the `catch` block. In those cases, the solution doesn't work. We could remove `if (player.autoplay() && !player.muted())` and simply just try muting it, but for now it's better to ensure `NotAllowedError` is due to unmuted first before applying the fix.
- This doesn't work for Firefox as there is an explicit "Allow Autoplay" button in the address bar that user needs to click themselves. Applies to all sites.
This commit is contained in:
infinite-persistence 2021-05-19 23:56:54 +08:00 committed by GitHub
parent df03cf1032
commit 2dac41e5e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 7 additions and 0 deletions

View file

@ -38,6 +38,7 @@ export type Player = {
controlBar: { controlBar: {
addChild: (string, any) => void, addChild: (string, any) => void,
}, },
autoplay: (any) => boolean,
}; };
type Props = { type Props = {

View file

@ -221,6 +221,12 @@ function VideoViewer(props: Props) {
); );
Promise.race([playPromise, timeoutPromise]).catch((error) => { Promise.race([playPromise, timeoutPromise]).catch((error) => {
if (typeof error === 'object' && error.name && error.name === 'NotAllowedError') {
if (player.autoplay() && !player.muted()) {
player.muted(true);
}
}
if (PLAY_TIMEOUT_ERROR) { if (PLAY_TIMEOUT_ERROR) {
const retryPlayPromise = player.play(); const retryPlayPromise = player.play();
Promise.race([retryPlayPromise, timeoutPromise]).catch((error) => { Promise.race([retryPlayPromise, timeoutPromise]).catch((error) => {