The canplaythrough
event (like canplay
) fires as the readyState
property changes. These events and the property reflect how much video the browser is able to play from the current position. So if you seek to a new position that is not buffered, the browser can no longer play from your current position, so the readyState
has to drop down to HAVE_METADATA
. Once that new section is loaded, readyState
eventually works its way back up to HAVE_ENOUGH_DATA
, and the event will fire again.
As of this fix from 2009, Chrome mimics the behavior of Firefox, which is to drop the readyState
down to HAVE_METADATA
on every seek, even if the video is fully buffered. Presumably, this is because even if the video is loaded from the network, it still takes time to load that section back into memory and display the current frame.
If you need to make sure your event only gets handled once, you can maintain more detailed state, or you can remove the listener after it runs the first time, like this:
media.removeEventListener('canplaythrough', canStartPlayback);
Here's an example that fires a bunch of these events and logs them to the console so you can see them in action when you seek: http://jsbin.com/buparoye/1/edit