Edit: this doesn’t seem to apply for Safari in iOS. But it may still be helpful.
———
Well it literally took me years to take the time to step through all the video.js code and finally figure out why this was happening but it was definitley worth it!
Enable logging!
First of all I recommend enabling debug logging. You can type this in the console, or incorporate it into your site's JS. This will show you details about the decisions it's making for you. Don't forget to turn it off for production.
videojs.log.level('debug')
VideoJS heuristics
VideoJS determines the first segment to play by excluding some of the video tracks (representations) based on heuristics.
- It will exclude representations where the known bandwidth is less than the bandwidth of the file (to try to prevent buffering).
- It will by default exclude representations where the width and height of the video on screen is smaller than the video file.
However by default it does not use the device pixel ratio (might be 2 or 3 on a typical smartphone or retina display) to calculate the width and height of the displayed player unless you enable the useDevicePixelRatio
option.
So for my 8 second looping video it would start by picking the 360px version instead of the 1080 version. And it looked terrible!
TLDR;
So once I set these two options I'm getting the 1080 video size on my phone, but a smaller 720 on a simulated old phone with 1x resolution.
hls: {
limitRenditionByPlayerDimensions: true,
useDevicePixelRatio: true
}
Further options
You can also add the following options to hls
. I wouldn't recommend bandwidth
unless you really really need to ignore the bandwidth and pick a version based solely on the dimensions of player:
useNetworkInformationApi
Uses browser API to estimate bandwidth. This maxes out at 10Mbps (to avoid [fingerprinting][1]) but if video.js thinks the bandwidth is higher based on observation it will use the higher value.
bandwidth
Override bandwidth estimate. To make the player ignore bandwidth when making decisions about which version to pick you can set this to `bandwidth: 10e6` which is 10Mbps or even `Number.MAX_VALUE`
I just added a note to a related Github issue How does videoJS determines quality of first segment? suggesting that the default be changed or the docs improved.