sampotts / plyr

A simple HTML5, YouTube and Vimeo player
https://plyr.io
MIT License
26.58k stars 2.93k forks source link

HTML5 Audio - metadata preloading is exhausting browser parallel sockets and hanging players #1202

Open adassumpcao opened 6 years ago

adassumpcao commented 6 years ago

It seems metadata preloading is exhausting browser parallel sockets and hanging players (multiplayer scenario).

Scenario

I have a scenario where I am loading several audio players in the same page (~10-50 per page). The sources locations are being loaded initially (on page load) directly in the HTML and then by calling Plyr's constructor with the associated DOM selectors. This works perfectly fine and preload attribute in the audio tag is being respected (as a consequence no network requests are being made and timeDuration displayed is 00:00, like expected).

Issue

Note: this issue was originally opened under issue #1201, this explains better how I got to this particular issue

Conditions:

At some point I have a function that calls API play.source setter for each individual player to set new sources on-the-fly. Since the preload function is not being respected by the source setter (see Issue #1201), a huge bulk of metadata requests (associated to preloading) are being triggered. As a consequence, browser max parallel socket limitations (refer to https://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser) is being hit and some of the requests are getting hung "indefinitely".

Note: if I increase max connections in Firefox config, this is no longer an issue.

As a consequence, the players which have data preloading tasks hung will not be playable. Now, interesting things will happen:

Interesting is that the API source setter starts by canceling networks requests.. https://github.com/sampotts/plyr/blob/de4707125638dc1b04da0b4cf690fb2259fefd63/src/js/source.js#L37

..and it seems at some point this is working correctly. But then when preloading metadata starts, sockets are not being handled correctly, and these limits are being hit really quickly if you update multiple players simultaneously.

Clearly this behavior will be different from browser to browser, since Chrome seems to have no issue. I was wondering if Plyr could have (or if it is even possible) some type of internal socket management/handling capability to avoid hitting browser limitations (by closing or reusing open sockets)?

A workaround for this issue would be fixing Issue #1201 and just don't preload any metadata at all. Metadata loading will now only happen when clicking play and not simultaneously for multiple players. This will definitely work better for multiple player scenarios and avoid firing a huge amount of network requests.

Note: This also assumes, while handling multiple players media play, you hook a "playing"event handler and not only stop() all playing players, but also properly cancel all current network requests by resetting the source with the API source setter.

Thanks for the support :)

Artur

adassumpcao commented 6 years ago

See original post in issue #1201

adassumpcao commented 6 years ago

Since the source setter just starts by removing all media elements..

https://github.com/sampotts/plyr/blob/de4707125638dc1b04da0b4cf690fb2259fefd63/src/js/source.js#L46-L48

..and this media element contains the original preload="none" attribute (which is now lost), perhaps the best way would be to create a new "preload" config option. Then, if this config "preload" is set, it would be easily inherited when calling the source setter (see below). This option could also be used to overload any original options set in the HTML audio element:

https://github.com/sampotts/plyr/blob/de4707125638dc1b04da0b4cf690fb2259fefd63/src/js/source.js#L78-L98

Then when media load() is being called, preload would be properly set:

https://github.com/sampotts/plyr/blob/de4707125638dc1b04da0b4cf690fb2259fefd63/src/js/source.js#L122

friday commented 6 years ago

..and this media element contains the original preload="none" attribute (which is now lost)

I agree with this being a big problem. State should be stored properly so it isn't lost. In a different place where this pattern was used I copied the original attribute and reapplied it to the new element.

Not sure this issue is something Plyr should be concerned with. Plyr doesn't manage network connections. It's really a browser/OS thing, but #1201 looks like a legit issue.

adassumpcao commented 6 years ago

..and this media element contains the original preload="none" attribute (which is now lost)

I agree with this being a big problem. State should be stored properly so it isn't lost. In a different place where this pattern was used I copied the original attribute and reapplied it to the new element.

Not sure this issue is something Plyr should be concerned with. Plyr doesn't manage network connections. It's really a browser/OS thing, but #1201 looks like a legit issue.

Yeah that's what I thought so. I don't event know if it's possible to control the socket management layer of audio/media handling on the browser side. It seems indeed a browser issue, but fixing #1201 would be a nice compromise/workaround to avoid this issue.