2

I'm using video.js to play HLS video stream that has multiple qualities in the m3u8 file. I noticed that video.js selects a lower quality than expected for a given quality. I checked the same stream and bandwidth with another HLS player, the "Native MPEG-Dash + HLS Playback" extension for chrome, and it gave a notch up quality, without buffering. This was consistent.

I also went as far as modifying the m3u8 file, cheating, tampering with the stated bandwidth to reflect that related TS segments was of lower bandwidth than it was really. I then played the video again under the same conditions. This time video.js bit on the cheat, and chose the higher quality videos, still without buffering. My conclusion is that although video.js is capable for higher quality, it chooses the lower quality files, probably to be on the safe side, with higher safety margin than other players.

Question: How can I lower this safety margin for video.js? I prefer higher quality with some risk of buffering, than always playing lower quality.

Yaron T
  • 21
  • 1

1 Answers1

0

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.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689