http-streaming
http-streaming copied to clipboard
Quality of the stream drops when small segments are downloaded
Description
When downloading small segments ( a few Kb in size ), the quality of the next few downloaded segments drops. This seem to be happening due to the way the bandwidth is calculated:
stats.bandwidth = Math.floor((stats.bytesReceived / stats.roundTripTime) * 8 * 1000);
It seems that because each network request comes with a few ms of overhead, for really small segments, the calculated bandwidth will seem smaller than it really is, which will cause the subsequent requests to be downloaded in lower quality.
Steps to reproduce
- Go to VideoJS HLS
- Use the following video URL: https://renderapifarmteststorage.blob.core.windows.net/playertest/parts_player2/stream.m3u8
- Open the Network tab in DevTools
- You should notice the drop of quality after small segments have been downloaded ( Like in the image below )
Additional Information
videojs-http-streaming version
videojs-http-streaming 2.14.12
videojs version
what version of videojs does this occur with? video.js 7.5.14
Browsers
Tested on Windows with the following browsers: Edge v101.0.1210.32 Chrome v101.0.4951.54 Firefox v99.0.1
For our project, this issue seems to be resolved by slightly increasing the value of MIN_SEGMENT_DURATION_TO_SAVE_STATS
, so the small parts are ignored when calculating bandwidth.
Using the experimental buffer based ABR also eliminates this problem, but without a way to adjust the decay
parameter passed to movingAverageBandwidthSelector
, the overrall quality of downloaded parts can be worse than when not using it. Currently the decay parameter is hardcoded and is equal to 0.55
Right now, neither of those values can be configured by options passed to the constructor.
Hey! We've detected some video files in a comment on this issue. If you'd like to permanently archive these videos and tie them to this project, a maintainer of the project can reply to this issue with the following commands:
- for https://renderapifarmteststorage.blob.core.windows.net/playertest/parts_player2/stream.m3u8: say
@video-archivist-bot save OEDlPE
👋 Thanks for opening your first issue here! 👋
If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can. To help make it easier for us to investigate your issue, please follow the contributing guidelines.
It's worth noting that your test page is using an outdated and obsolete version of the plugin. The new test page is https://videojs-http-streaming.netlify.app/.
The values in the experiemntalBufferBasedABR
option were chosen after extensive testing to provide a good balance between quality and buffering.
I believe it's possible to configure the decay by passing in a selectPlaylist
as an option. movingAverageBandwidthSelector
is exposed via videojs.Vhs.movingAverageBandwidthSelector
:
videojs('vid', {
html5: {
vhs: {
selectPlaylist: videojs.Vhs.movingAverageBandwidthSelector(0.8)
}
}
});
Hope this helps.
I passed movingAverageBandiwdthSelector
as in your example, but it didn't seem to have worked.
Here's the code I used to initialize videojs
window.videoObject = videojs('#my-video', {
html5: {
vhs: {
selectPlaylist: videojs.Vhs.movingAverageBandwidthSelector(0.8)
}
}
})
However, it seems like selectPlaylist
still points to the default selector (lastBandwidthSelector
).
Here's what it looks like in console:
I also tried to supply my own function with a debugger statement in it, but it was never executed. ( Tested on [email protected] )
Based on what I see in the code here, I don't think selectPlaylist
is accessible from the options?
It looks like it can be overwritten via runtime though: https://github.com/videojs/http-streaming/blob/450eb2dcd022c358bd4dc21c493f9aa6fe1dd9c0/README.md#vhsselectplaylist
Any update on this?
We are facing a similar issue, when a video contains a screenshare or static images. Fragments are smaller and the quality drop down to 240p then start raising again.
@gkatsev Sorrry for the ping, Any update on this or a possible workaround?
We are having a lot of issues with slideshows. the quality drops due to segment beeing really small during screen shares. This really seems CDN specific on how they decide to handle the segments. In my case if using cloudflare we are seeing such isses. When using Mux this is not happening.
We are evaluating paid support but I didnt see any ino on how to get "premium" support.
Also asking for an Update onto this, ABR streaming just isn't greate, the quality is switching in the first instance to 1080p and than again dropping to 360p on a 1Gbit/s lines where the server is located in the same area.
Sometimes the streams are just flapping as hell where it works like a charm on other player like bitmovin. I also validated my HLS data against the akamai stream test, everything fine, no issues at all.
I guess the problem for me is the following line at the VHS/VideoJS code:
const roundTripTime = Date.now() - request.requestTime;
this is kinda unsafe. Example given, this will only work properly if all requirements are fulfilled:
- Webserver has enougth capacity in terms of Bandwidth and espacially latency.
- The server has a fast access to the Files. In my case I need a couple of milliseconds more as my Streaming servers are mounting an S3 volume and serving the data from that Mount. So using request.requestTime is very evil here as some requests will take longer than others to finish. I noticed a heavy fluctoation here when my server needs 250ms more to pull the segment from the remote s3 storage mounted, dispite that I already have buffered the first 30 seconds and that loading segments at least to me happends very fast.
Please find a better more save stragegie as default, or at least provide an option that makes redention selection more save. Maybe exposing more variables so that everybody can build its very own ABR strategy.
@gkatsev If you need a donation to work faster onto this issue, please let me know. As this is one of my very last blockers befor I can finish my project.