Open bowczarek opened 3 years ago
@bowczarek Thanks a lot, I was bangin' my head with this; As I use speed control for my webcams timelapse, I wasn't able to set the default speed.. I just removed size
parameters from my list of videos, and now just work as expected. That's still the case on plyr v. 3.6.9
First and foremost @sampotts thanks for your awesome contribution π₯ π π !
Expected behaviour
If you pass selected speed option when initializing Plyr instance and then set sources programatically with
size
(quality) specified then the selected speed should be set on player, for example it should be set to 2 initially in the following code snippet:Actual behaviour
Actual behavior is that it is set back to 1 after Plyr instance initialization. By debugging the sources, I believe I found the reason or at least some initial place in code that you can refer to and might help to fix the bug. It will be quite long, took me some time to investigate but please stay a while and listen ;)
There are two actions here:
I'll start from the 2nd instruction (backwards). Namely, if you specify the
size
(quality) on sources then the wholequality
setter on plyr object (plyr.js
) is invoked that finally invokesquality
setter onmedia
object which in our case ishtml5
so its implementation is inhtml5.js
(I'll skip irrelevant lines):If you don't specify
size
(quality) on source then it returns immediately andquality
setter onmedia
object is not invoked as you can see aboveif (!options.length) { return; }
.Otherwise, if we specify the
size
(which is our case) then here is first most important thing that happens. When we take a look into thatmedia.quality
setter (html5.js
), we can find following code (i'll skip irrelevant lines, just paste most important one that are invoked in this scenario):Now, two critical things happen here:
playbackRate
variable fromplayer.media
, which means the value will be snaphotted at this time, it won't be a reference to the current speed value (you would need to always reference from the object referenceplayer.media.playbackRate
), which in described case will be 1 (instead of desired 2), I explain in a second whyloadmetadata
event occurs the player speed is reset back to that snapshotted valueplayer.speed = playbackRate
Ok, now we may wonder why it is set back to 1, if this whole logic is invoked after Plyr initialization (first instruction in our case). We would expect it to be already set to 2 even if it is snapshotted from destructuring right? To find that out we need to take a look at first instruction (step) which is already mentioned several times
Plyr
initialization.When
Plyr
is initialized, itsspeed
setter (plyr.js
) is invoked (again, I'll skip irrelevant code, leave just last instruction):As you can see speed on
media
object is set usingsetTimeout
method with time interval set to0
, which according to specification (https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#settimeout), does not mean it's invoked immediately:So now everything should be clear, we got some race condition happening here. To sum up, the speed from
Plyr
initialization (where we pass 2) is actually set after the value is snapshotted when we set the sources from the second instruction and thenloadmetadata
that happens at the end resets it back to 1.Two additional things from my side that you may guys consider or reason about:
loadmetadata
event, maybe it's not needed?ratechange
event is always generated, even if you just initializePlyr
instance, you can see that also in my code sandbox. I would actually expect it to be fired only when you change the speed after thePlyr
initialization.Steps to reproduce
I created a sample code sandbox with vanilla js where you can see that behaviour. Check the comments I added there, if you comment out
size
(quality), all of a sudden it works as expected. If you keep it, then in the console you can see that two events with speed change happen, and the 2nd one always reverts the value back to 1.As an analogy you can try setting the initial volume as well, which works just fine as expected, because the logic of setting volume does not have those quirks of speed I described above.
https://codesandbox.io/s/plyr-speed-issue-jdy01
Environment