Skip to content

Fix Crossfade randomly muting music until manual unmute#4307

Open
Orionicelion wants to merge 1 commit intopear-devs:masterfrom
Orionicelion:master
Open

Fix Crossfade randomly muting music until manual unmute#4307
Orionicelion wants to merge 1 commit intopear-devs:masterfrom
Orionicelion:master

Conversation

@Orionicelion
Copy link

Fixes multiple open issues on the crossfade plugin muting after a transition

if (
video.currentTime >=
video.duration - (this.config?.secondsBeforeEnd ?? 0) &&
video.duration - (this.config?.secondsBeforeEnd ?? 0) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Insert ··

Suggested change
video.duration - (this.config?.secondsBeforeEnd ?? 0) &&
video.duration - (this.config?.secondsBeforeEnd ?? 0) &&


const crossfade = (cb: () => void) => {
if (!isReadyToCrossfade()) {
ensureVideoVolume()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <prettier/prettier> reported by reviewdog 🐶
Insert ;

Suggested change
ensureVideoVolume()
ensureVideoVolume();


const crossfade = (cb: () => void) => {
if (!isReadyToCrossfade()) {
ensureVideoVolume()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [eslint] <stylistic/semi> reported by reviewdog 🐶
Missing semicolon.

Suggested change
ensureVideoVolume()
ensureVideoVolume();

@JellyBrick JellyBrick requested a review from Copilot February 7, 2026 23:50
@JellyBrick JellyBrick added the bug Something isn't working label Feb 7, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to fix a recurring issue in the crossfade plugin where music can end up muted (video volume stuck at 0) after transitions, requiring manual unmute.

Changes:

  • Initialize waitForTransition and introduce originalVolume tracking to restore volume after crossfade-related volume changes.
  • Add ensureVideoVolume() and invoke it in several transition/navigation paths to recover from unintended mute states.
  • Adjust crossfade/sync logic to use originalVolume when fading back in and to trigger a fade-in when the video is already playing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +281 to +283
video.addEventListener('seeking', onSeeking);
video.addEventListener('pause', onPause);
video.addEventListener('play', onPlay);
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syncVideoWithTransitionAudio adds seeking/pause/play listeners every time it’s called, but they are never removed. Since createAudioForCrossfade calls this on each navigation, listeners can accumulate on the same <video> element, leading to duplicated transitionAudio.play/pause/seek calls and repeated fades. Consider removing prior listeners (store handler refs in outer scope) or using an AbortController/signal to clean them up when unloading/creating a new transitionAudio.

Copilot uses AI. Check for mistakes.
Comment on lines 275 to 278
// Fade in
const videoVolume = video.volume;
const videoVolume = originalVolume || video.volume || 1;
video.volume = 0;
videoFader.fadeTo(videoVolume);
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The volume restoration/fade target uses originalVolume || video.volume || 1. Because 0 is falsy, a legitimate 0 volume will fall through to 1, which can cause an unwanted jump/unmute. Prefer an explicit > 0 check or nullish coalescing (??) with a separately tracked “last non-zero volume”.

Copilot uses AI. Check for mistakes.
Comment on lines +203 to +208
const ensureVideoVolume = () => {
const video = document.querySelector('video');
if (video && video.volume === 0 && originalVolume > 0) {
video.volume = originalVolume;
}
};
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change introduces non-trivial volume state recovery behavior (tracking/restoring previous volume across navigations). There are Playwright tests in the repo (including plugin-level unit tests), but this plugin has no coverage for crossfade/volume handling. Adding a regression test (unit test for extracted helper or an e2e test that reproduces the “volume stuck at 0 after transition” case) would help prevent future regressions.

Copilot uses AI. Check for mistakes.
Comment on lines +203 to +208
const ensureVideoVolume = () => {
const video = document.querySelector('video');
if (video && video.volume === 0 && originalVolume > 0) {
video.volume = originalVolume;
}
};
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensureVideoVolume will restore the video volume to originalVolume whenever video.volume === 0. Since originalVolume defaults to 1 and is updated whenever the user volume is > 0, this can unintentionally unmute users who explicitly set volume to 0 (or start muted), and can also override intentional “mute by volume=0” behavior. Consider tracking whether the plugin set the volume to 0 (e.g., a pluginMuted/didFadeToZero flag) and only restoring in that case, and initialize originalVolume from the current video element when available instead of a hard-coded 1.

Copilot uses AI. Check for mistakes.
Comment on lines 310 to 312
if (!isReadyToCrossfade()) {
ensureVideoVolume()
cb();
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon after ensureVideoVolume(); this file otherwise uses semicolons consistently and this will likely fail lint/format checks.

Copilot uses AI. Check for mistakes.
Copy link
Member

@JellyBrick JellyBrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix these issues.
(See review comments)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants