Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Video doesn't pause when playing state changes too fast (false->true->false) #1152

Closed
rejebsab opened this issue Jan 23, 2021 · 2 comments
Closed

Comments

@rejebsab
Copy link

rejebsab commented Jan 23, 2021

Current Behavior

I wrote an Instagram/Facebook like Play/Pause for videos based on video entire visibility. So user will scroll on his page and will have videos that play when in focus ("playing"=true) and pause when goes out of focus ("playing"=false).

Now when i scroll up and down slowly, everything works fine. Video plays when "playing" is true, and pauses when "playing" is false. However when i scroll very quickly top-down and down-top, i notice that even though the "playing" property has been updated to false, some videos continues playing and do not pause.

Expected Behavior

What ever the scroll speed is, the video should play on when it is on focus ("playing"=true) and should stop when it goes out of focus ("playing"=false).

Steps to Reproduce

  1. User needs to interact with the document before audio or video content is played automatically.
  2. Scroll very quickly from top to down and vice versa.

Investigation

After investigating i found out that react player has a condition to trigger Pause event as below:

  1. Files:
    a) react-player/lazy/Player.js
    b) react-player/lib/Player.js

  2. Condition
    if (prevProps.playing && !playing && this.isPlaying) {
    this.player.pause();
    }

So it possible that, when the "playing" property changes quickly from (false) to (true) to (false) again, then "this.isPlaying" doesn't have enough time to follow the changes and stays at false because video didn't play yet.

Proposed Fix

if (prevProps.playing && !playing) {
this.player.pause();
}

@rejebsab rejebsab changed the title Video does not pause when playing state change too fast (false->true->false) Video does not pause when playing state changes too fast (false->true->false) Jan 23, 2021
@rejebsab rejebsab changed the title Video does not pause when playing state changes too fast (false->true->false) Video doesn't pause when playing state changes too fast (false->true->false) Jan 23, 2021
@cookpete
Copy link
Owner

Similar discussion here: #1079 (comment)

It has been a while (years) since I looked at the isPlaying logic in any detail. I remember seeing lots of bugs without it, and I guess this is one of the bugs that we see with it.

Consider a very simple example using onPlay and onPause to keep playing in sync if the user uses the native controls:

const [playing, setPlaying] = useState(true)

return (
  <ReactPlayer
    url='file.mp4'
    controls
    playing={playing}
    onPlay={() => setPlaying(true)}
    onPause={() => setPlaying(false)}
  />
)

Without the isPlaying check, we still have problems when playing changes too fast:

  1. Video is playing, user clicks pause and setPlaying(false) is called
  2. Before onPause is fired by player API, user clicks play and playing goes back to true
  3. onPause then gets fired by the player API, which does setPlaying(false) again
  4. onPlay is fired from step 2 and calls setPlaying(true)
  5. onPause is fired from step 3 and calls setPlaying(true)
  6. etc

Also, more generally, we don't want to call play() on a player that is playing, or pause() on a paused player. We don't want onPlay or onPause to fire incorrectly, and we want to avoid problems with player APIs that might have weird behaviour.

My suggestion would be to add debounce/throttle logic to your app to ensure that playing can't be toggled quickly enough to break things. Not an ideal solution, but I don’t have any better ideas for the player logic, and I don’t have enough time for a full rewrite (as much as I would love to).

@prabushitha
Copy link

prabushitha commented Jan 19, 2024

I had a similar issue where my use case was that I had to stop the video when it reaches beyond X seconds.
It worked perfectly with playing prop false, but when seeked from the control bar, it didn't stop.

So I had to forcefully stop from the internal player like below. I'm using wistia videos. Didn't check with other media. But most of them should have a pause in the internal API.

const playerRef = useRef();
useEffect(() => {
  const internalPlayer = playerRef?.current ? playerRef.current.getInternalPlayer() : null;
  if (!playing && internalPlayer && internalPlayer.state() === 'playing') {
    internalPlayer.pause();
  }
}, [playing, playerRef?.current]);

return  (
  <ReactPlayer
    ref={playerRef}
    playing={playing}
    ...
  />
);

@luwes luwes closed this as not planned Won't fix, can't repro, duplicate, stale Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants