vidstack / player

UI components and hooks for building video/audio players on the web. Robust, customizable, and accessible. Modern alternative to JW Player and Video.js.
https://vidstack.io
MIT License
2.33k stars 137 forks source link

<media-player> doesn't respect initial volume and muted props #1416

Open zshall opened 2 months ago

zshall commented 2 months ago

Current Behavior:

When embedding a <media-player> in Svelte with volume set to 0 and muted set to true, the player starts at full volume.

If you bind:this={player} and programatically set player.muted and player.volume it works.

Expected Behavior:

The player should start muted.

Steps To Reproduce:

    <media-player
        class="w-full"
        src={props.src}
        playsInline
        bind:this={player}
        muted={true}
        >
        <media-provider></media-provider>
    </media-player>

Reproduction Link: StackBlitz example

Environment:

Example:

Anything Else?

image

zshall commented 2 months ago

In further testing I've noticed that programmatically setting the volume is also a bit off if you do it right around the time you load the player. If I have a method that's called onMount() or onCanPlay() such as this:

function onCanPlay() {
        player.volume = 0.2;
        player.muted = true;

        player.play();
    }

It doesn't work. The player is unmuted at full volume when it loads.

Same thing if I reverse the order:

function onCanPlay() {
        player.play();

        player.volume = 0.2;
        player.muted = true;
    }

Player is unmuted at full volume.

A workaround

The only workarounds I've found are to set a timeout for 0 ms that calls this code and then it works:

function onCanPlay() {
        player.play();

        setTimeout(() => {
            if (player) {
                player.volume = 0.2;
                player.muted = true; // works with a 0ms timeout
            }
        }, 0);
    }

This isn't a great solution; is there a preferred way to interact with volume programmatically? My use case is that I have a $store that holds volume and muting info for a number of different video and audio players and I need them to all sync up with the same volume variables, therefore if the program starts muted I need the player to also start muted.

zshall commented 2 months ago

Tested and you can't use a remote object to do it either right on launch.

setTimeout(() => {
            remote.changeVolume(0.2);
            remote.mute(true); // works
        }, 0);

This also only works if you setTimeout().

hatsch commented 2 months ago

this bug is not present in v1.11.30-next first version affected is v1.12.0-next

i am using this in my nuxt app to only have 1 player unmuted

geerew commented 2 months ago

The same is happening for playbackRate and volume

mihar-22 commented 2 months ago

Thanks for reporting! This is a hydration bug with Svelte 4 as mentioned in the docs. You can either upgrade to Svelte 5 or you can mount the player client-side only by dynamically importing it.

👉 Section in docs mentioning this issue.

zshall commented 2 months ago

Cool I’ll try this today, thanks!

hatsch commented 2 months ago

@mihar-22 as mentioned earlier, this bug is also affecting nuxt/vuejs. i have ssr disabled in my app. so i doubt it's solely an issue with hydration

version v1.11.30-next is not affected.

mihar-22 commented 2 months ago

I just tested it and it works as expected, make sure you're setting volume between 0 and 1, for 30% it'd be volume="0.3".

Daedalus11069 commented 2 months ago

@mihar-22

I just tested it and it works as expected, make sure you're setting volume between 0 and 1, for 30% it'd be volume="0.3".

Here is a stackblitz reproducing the bug: https://stackblitz.com/edit/vidstack-examples-qufbsu?file=src%2FPlayer.vue

The player's ref of volume is set to 0.1 by default. The volume slider shows this below, but the actual player volume is at 1.

This bug is still present; can you please share how you have yours working?

Zibbp commented 2 months ago

I can also reproduce this using the javascript/cdn import: https://stackblitz.com/edit/stackblitz-starters-jdj5p2?file=index.html Changing the import URL to use @v1.11.30 works as expected, so some issue in newer releases.

plcdnl commented 1 month ago

same issue on nuxt. Everything works fine with 1.11.30. Thank you for the workaround. @mihar-22, really sorry for the ping, but i think is necessary to re-open the issue

RedstoneWizard08 commented 2 weeks ago

I'm also experiencing this issue on vue.

truanthh commented 1 week ago

Same problem here, vue 3.4.31 + vite 5.3.4