<media-player> doesn't respect initial volume and muted props
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:
- Framework: Svelte
- Meta Framework: SvelteKit
- Node: 20.0.0
- OS: Windows@11
- Browser: Chrome@128
Anything Else?
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.
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().
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
The same is happening for playbackRate and volume
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.
Cool I’ll try this today, thanks!
@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.
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".
@mihar-22
I just tested it and it works as expected, make sure you're setting volume between
0and1, for 30% it'd bevolume="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?
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.
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
I'm also experiencing this issue on vue.
Same problem here, vue 3.4.31 + vite 5.3.4
I'm also seeing this on svelte 5 with vidstack 1.12.12. 1.11.30 is okay.
1.11.30 is okay
Is there a real fix to this problem?
Could be this the culprit? Is setted by vidstack and saved in local storage
+1 same issue here
Hi, sorry in advance if i can be boring. I’ve commented on this issue a few times, but haven’t received any response so far. I’m wondering if this is still on your radar or if there’s anyone maintaining this part of the project.
This problem is still relevant and I’d really appreciate any update or guidance. If there’s anything I can do to help move it forward, I’d be happy to contribute.
This is how I workaround it:
- Add a listener on the
playevent - Set the volume to 0 and mute
- Remove the listener so it doesn't mute every time in case the user pauses/plays (so the mute only happens in the first play)
Example on Vue 3 + Vite 6.3.6 + 1.12.13-next:
<script setup lang="ts">
import "vidstack/bundle";
import { computed, onBeforeUnmount, onMounted, useTemplateRef } from "vue";
const props = defineProps<{
url: string;
autoplay?: boolean;
muted?: boolean;
noVolume?: boolean;
posterUrl?: string;
}>();
const playerRef = useTemplateRef("player");
const source = computed(() => ({
src: props.url,
type: "video/mp4",
}));
// Workaround for bug https://github.com/vidstack/player/issues/1416
const forceMute = () => {
(playerRef.value as any).muted = true;
(playerRef.value as any).volume = 0;
playerRef.value.removeEventListener("play", forceMute);
};
onMounted(() => {
if (props.muted && playerRef.value) {
playerRef.value.addEventListener("play", forceMute);
}
});
onBeforeUnmount(() => {
if (playerRef.value) {
playerRef.value.removeEventListener("play", forceMute);
}
});
</script>
<template>
<media-player
ref="player"
:src="source"
:autoplay="autoplay"
:controlsDelay="1000"
:hideControlsOnMouseLeave="false"
:loop="true"
:muted="muted"
playsinline
>
<media-provider></media-provider>
<media-video-layout :thumbnails="posterUrl"></media-video-layout>
</media-player>
</template>