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

Bug: Play event behavior does not match video play event #898

Open
1 task done
andrewbrennanfr opened this issue Apr 10, 2024 · 4 comments
Open
1 task done

Bug: Play event behavior does not match video play event #898

andrewbrennanfr opened this issue Apr 10, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@andrewbrennanfr
Copy link

andrewbrennanfr commented Apr 10, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Which Mux Elements/Packages does this apply to? Select all that apply

mux-video

Which browsers are you using?

Chrome

Which operating systems are you using?

macOS

Description

In your docs, it's mentioned that the Mux player emits all of events available on the HTML5 video element & I would expect the same behaviors between both.

I've experienced 2 cases where there is a misalignment in behavior - both very similar.

The order of events emitted from the player is not the same - which is particularly problematic in the case of an error loading the video.


<mux-video /> => https://stackblitz.com/edit/vitejs-vite-e37ply?file=src%2FApp.vue&terminal=dev
<video /> => https://stackblitz.com/edit/vitejs-vite-mmoxmh?file=src%2FApp.vue&terminal=dev

Reduced test case

https://stackblitz.com/edit/vitejs-vite-e37ply?file=src%2FApp.vue&terminal=dev

Steps to reproduce

✅ Case 1 - A video successfully loads

Order of events for <video /> element

  • Load video player
  • loadedmetadata event is emitted first
  • Then play event is emitted

Order of events for <mux-video /> element

  • Load mux video
  • play event is emitted first
  • Then loadedmetadata event is emitted

❌ Case 2 - A video does not successfully load

Order of events for <video /> element

  • Load video player
  • error event is emitted

Order of events for <mux-video /> element

  • Load mux video
  • play event is emitted (even though the video isn't played)
  • Then error event is emitted

Current Behavior

The play event is always emitted immediately when autoplay is true - even if the video is errored.

The play event is emitted, before the loadedmetadata - which should not be the case.

Expected Behavior

play can & should only be emitted after the video successfully loads - both when autoplay is true & also if the user was to try & play the video before it loaded successfully.

Errors

No response

What version of the package are you using?

v0.17.5

@andrewbrennanfr andrewbrennanfr added bug Something isn't working Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug labels Apr 10, 2024
@luwes luwes removed the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Apr 17, 2024
@luwes
Copy link
Contributor

luwes commented Apr 18, 2024

I can confirm this is a different behavior, I'll bring this up with the team but it might be not sufficient reason to change.
The cause of this is that we explicitly call video.play() internally.

play can & should only be emitted after the video successfully loads - both when autoplay is true & also if the user was to try & play the video before it loaded successfully.

This quote is not fully correct. For the playing event that would be true I believe.

The play event is called whenever the play() method is called, the returned promise doesn't even need to resolve.

https://codesandbox.io/p/sandbox/mux-video-vs-video-events-yhd22m?file=%2Findex.html%3A41%2C48

@andrewbrennanfr
Copy link
Author

andrewbrennanfr commented Apr 18, 2024

@luwes The problem arises when you want to tell, that the video has actually started playing from the beginning... Is there an alternative to doing that?

If we agree that the @play event emits, even when the video hasn't played yet - so the alternative would be to use @playing. But the @playing event fires slightly "too late". The currentTime is no longer 0. Where as with @play, when played from the start, still has a currentTime of 0.

@cjpillsbury
Copy link
Contributor

Hey @andrewbrennanfr it might be helpful to understand the scenario you're trying to account for.

From your discussion, it sounds like you have a setup where you have autoplay set and you'd like to monitor if an error occurs when attempting to load and subsequently (auto)play the media. Is that correct? If yes, you may want to go with a less presumptuous monitoring condition, like:

const errorListener = (event) => {
  console.log("AN ERROR OCCURRED BEFORE PLAYBACK", event);
};

muxVideoEl.addEventListener("error", errorListener);

// Condition to stop monitoring for an error
muxVideoEl.addEventListener(
  "playing",
  (_event) => {
    muxVideoEl.removeEventListener("error", errorListener);
  },
  // Only listen for the first occurrence of "playing"
  { once: true }
);

This should account for errors before playback, regardless of autoplay, a user seek after loading media but before playing, etc.

Let us know if that is appropriately capturing your scenario. As @luwes points out, we do end up doing some programmatic work "under the hood," including invoking the underlying HTMLMediaElement::play() method under certain conditions (particularly to try our best to autoplay given the various constraints on that behavior), so I'd be extremely hesitant to add code complexity or "swallow" events for these cases.

@andrewbrennanfr
Copy link
Author

andrewbrennanfr commented Apr 18, 2024

@luwes So what I'm trying to do is, add some logging, whenever the user plays from 0.
So the once also likely won't work here.

So for example:

I want to log something when:

  • if the user plays from 0
  • if the user replays the video from 0
  • the video is autoplayed

I do not want to log something when:

  • if the user pauses & seeks to 0.00001 & plays again
  • the video errors or otherwise fails to play
  • the user seeks to 0 during playback

The play solves this problem for me (in theory) - if it behaved like the video play event.

How I've "solved" it for now is a variation of:

let isLoading = true

const handlePlay = () => {
  if (isLoading) { // don't continue if still loading
    return  
  }

  // log something based on `currentTime === 0`
}

const handleMetaDataLoaded = () => {
  isLoading = false

  handlePlay() // resume the play event
}

This way I'm sure the video has loaded successfully before playing. But it's a bit of a workaround, rather than a real fix.

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

No branches or pull requests

3 participants