fix web player crossfade transition state causing stutter on playerData change

This commit is contained in:
jeffvli
2025-12-08 21:46:13 -08:00
parent 38b06fdd06
commit 628b0184de
2 changed files with 46 additions and 8 deletions
@@ -85,6 +85,7 @@ export function WaveSurferPlayer() {
currentPlayerNum: num, currentPlayerNum: num,
currentTime: e.playedSeconds, currentTime: e.playedSeconds,
duration: getDuration(playerRef.current.player1().ref), duration: getDuration(playerRef.current.player1().ref),
hasNextSong: Boolean(player2),
isTransitioning, isTransitioning,
nextPlayer: playerRef.current.player2(), nextPlayer: playerRef.current.player2(),
playerNum: 1, playerNum: 1,
@@ -104,7 +105,7 @@ export function WaveSurferPlayer() {
break; break;
} }
}, },
[crossfadeDuration, isTransitioning, num, transitionType, volume], [crossfadeDuration, isTransitioning, num, player2, transitionType, volume],
); );
const onProgressPlayer2 = useCallback( const onProgressPlayer2 = useCallback(
@@ -121,6 +122,7 @@ export function WaveSurferPlayer() {
currentPlayerNum: num, currentPlayerNum: num,
currentTime: e.playedSeconds, currentTime: e.playedSeconds,
duration: getDuration(playerRef.current.player2().ref), duration: getDuration(playerRef.current.player2().ref),
hasNextSong: Boolean(player1),
isTransitioning, isTransitioning,
nextPlayer: playerRef.current.player1(), nextPlayer: playerRef.current.player1(),
playerNum: 2, playerNum: 2,
@@ -140,7 +142,7 @@ export function WaveSurferPlayer() {
break; break;
} }
}, },
[crossfadeDuration, isTransitioning, num, transitionType, volume], [crossfadeDuration, isTransitioning, num, player1, transitionType, volume],
); );
const handleOnEndedPlayer1 = useCallback(() => { const handleOnEndedPlayer1 = useCallback(() => {
@@ -260,6 +262,7 @@ function crossfadeHandler(args: {
currentPlayerNum: number; currentPlayerNum: number;
currentTime: number; currentTime: number;
duration: number; duration: number;
hasNextSong: boolean;
isTransitioning: boolean | string; isTransitioning: boolean | string;
nextPlayer: { nextPlayer: {
ref: null | WaveSurfer; ref: null | WaveSurfer;
@@ -275,6 +278,7 @@ function crossfadeHandler(args: {
currentPlayerNum, currentPlayerNum,
currentTime, currentTime,
duration, duration,
hasNextSong,
isTransitioning, isTransitioning,
nextPlayer, nextPlayer,
playerNum, playerNum,
@@ -283,8 +287,20 @@ function crossfadeHandler(args: {
} = args; } = args;
const player = `player${playerNum}`; const player = `player${playerNum}`;
// If there is no next song queued, don't begin or continue a transition
if (!hasNextSong) {
currentPlayer.setVolume(volume);
nextPlayer.setVolume(0);
nextPlayer.ref?.pause();
if (isTransitioning) {
setIsTransitioning(false);
}
return;
}
if (!isTransitioning) { if (!isTransitioning) {
if (currentTime > duration - crossfadeDuration) { if (duration > 0 && currentTime > duration - crossfadeDuration) {
nextPlayer.setVolume(0); nextPlayer.setVolume(0);
nextPlayer.ref?.play(); nextPlayer.ref?.play();
return setIsTransitioning(player); return setIsTransitioning(player);
@@ -106,6 +106,7 @@ export function WebPlayer() {
currentPlayerNum: num, currentPlayerNum: num,
currentTime: e.playedSeconds, currentTime: e.playedSeconds,
duration: getDuration(playerRef.current.player1().ref), duration: getDuration(playerRef.current.player1().ref),
hasNextSong: Boolean(player2),
isTransitioning, isTransitioning,
nextPlayer: playerRef.current.player2(), nextPlayer: playerRef.current.player2(),
playerNum: 1, playerNum: 1,
@@ -125,7 +126,7 @@ export function WebPlayer() {
break; break;
} }
}, },
[crossfadeDuration, crossfadeStyle, isTransitioning, num, transitionType, volume], [crossfadeDuration, crossfadeStyle, isTransitioning, num, player2, transitionType, volume],
); );
const onProgressPlayer2 = useCallback( const onProgressPlayer2 = useCallback(
@@ -143,6 +144,7 @@ export function WebPlayer() {
currentPlayerNum: num, currentPlayerNum: num,
currentTime: e.playedSeconds, currentTime: e.playedSeconds,
duration: getDuration(playerRef.current.player2().ref), duration: getDuration(playerRef.current.player2().ref),
hasNextSong: Boolean(player1),
isTransitioning, isTransitioning,
nextPlayer: playerRef.current.player1(), nextPlayer: playerRef.current.player1(),
playerNum: 2, playerNum: 2,
@@ -162,7 +164,7 @@ export function WebPlayer() {
break; break;
} }
}, },
[crossfadeDuration, crossfadeStyle, isTransitioning, num, transitionType, volume], [crossfadeDuration, crossfadeStyle, isTransitioning, num, player1, transitionType, volume],
); );
const handleOnEndedPlayer1 = useCallback(() => { const handleOnEndedPlayer1 = useCallback(() => {
@@ -193,7 +195,12 @@ export function WebPlayer() {
usePlayerEvents( usePlayerEvents(
{ {
onCurrentSongChange: () => {
setIsTransitioning(false);
},
onPlayerSeekToTimestamp: (properties) => { onPlayerSeekToTimestamp: (properties) => {
setIsTransitioning(false);
const timestamp = properties.timestamp; const timestamp = properties.timestamp;
// Reset transition state if seeking during a crossfade transition // Reset transition state if seeking during a crossfade transition
@@ -218,6 +225,8 @@ export function WebPlayer() {
} }
}, },
onPlayerStatus: async (properties) => { onPlayerStatus: async (properties) => {
setIsTransitioning(false);
const status = properties.status; const status = properties.status;
// Reset crossfade transition if paused during a crossfade transition // Reset crossfade transition if paused during a crossfade transition
@@ -226,8 +235,6 @@ export function WebPlayer() {
isTransitioning && isTransitioning &&
transitionType === PlayerStyle.CROSSFADE transitionType === PlayerStyle.CROSSFADE
) { ) {
setIsTransitioning(false);
if (num === 1) { if (num === 1) {
playerRef.current?.player1()?.setVolume(volume); playerRef.current?.player1()?.setVolume(volume);
playerRef.current?.player2()?.setVolume(0); playerRef.current?.player2()?.setVolume(0);
@@ -461,6 +468,7 @@ function crossfadeHandler(args: {
currentPlayerNum: number; currentPlayerNum: number;
currentTime: number; currentTime: number;
duration: number; duration: number;
hasNextSong: boolean;
isTransitioning: boolean | string; isTransitioning: boolean | string;
nextPlayer: { nextPlayer: {
ref: null | ReactPlayer; ref: null | ReactPlayer;
@@ -477,6 +485,7 @@ function crossfadeHandler(args: {
currentPlayerNum, currentPlayerNum,
currentTime, currentTime,
duration, duration,
hasNextSong,
isTransitioning, isTransitioning,
nextPlayer, nextPlayer,
playerNum, playerNum,
@@ -485,8 +494,21 @@ function crossfadeHandler(args: {
} = args; } = args;
const player = `player${playerNum}`; const player = `player${playerNum}`;
// If there is no next song to transition to, ensure we don't enter or stay in a transition
if (!hasNextSong) {
currentPlayer.setVolume(volume);
nextPlayer.setVolume(0);
nextPlayer.ref?.getInternalPlayer()?.pause();
if (isTransitioning) {
setIsTransitioning(false);
}
return;
}
if (!isTransitioning) { if (!isTransitioning) {
if (currentTime > duration - crossfadeDuration) { if (duration > 0 && currentTime > duration - crossfadeDuration) {
nextPlayer.setVolume(0); nextPlayer.setVolume(0);
nextPlayer.ref?.getInternalPlayer().play(); nextPlayer.ref?.getInternalPlayer().play();
return setIsTransitioning(player); return setIsTransitioning(player);