Third party stream players stuck on lowest bit rate

Trying to get a third party player working with Cloudflare stream.

All seem to get stuck at 240p quality, and don’t change up to anything better.

I’ve tried videojs/hlsjs, flowplayer, radiant, and jwplayer, with similar results - as well as Akamai’s player test tool which has a lot of debug info - including that multiple qualities are available, but it also gets stuck on the lowest rate.

For those players which offer manual quality switching, i can manually choose a higher quality, and the video plays perfectly - but having to manually select that is not a good user experience.

Am I missing something? Or is something broken about how CF’s m3u8 manifests are vs what these third party players expect which is causing it to not automatically select a higher quality?

1 Like

Hi there, we’re actively working on some improvements to how we communicate video bitrates to client players.

Could you please open a support ticket and share details about specifically what video IDs you’re seeing this for? This will help us look into what might be causing issues on your end.

@irvinebroque I tried to open a ticket yesterday, and i got an auto-reply telling me that I needed to be a Pro subscriber to open a ticket, else I should post to the community forum.

I couldn’t find a way to apply Pro to the Stream product, only to domains? Do I just pick any domain and add Pro to that, or how do I get to where I can open a ticket for the Stream product?

I’ll DM you here in the forum.

Hi irvinebroque,

We are facing the same issue, can you please DM me?

Regards,

I’m having exactly the same issue. I’ve been using HLS JS but found the same problem in other libraries, like Shaka player, so it can’t be the player that’s the issue.

When I load a stream’s .m3u8, it starts with the 240p, which is the lowest quality. That’s understandable if it doesn’t know the user’s bandwidth. However it sticks at that rendition, even when it could auto-switch to a higher one. As the user says, I can manually switch to a higher one and that plays fine. However it is far better that it auto-switches, as that is what viewers are used to from YouTube etc.

To compare, I tried loading the default rival .m3u8 loaded by the HLS JS demo page hls.js demo which is https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8

That starts off at 720p (makes sense - that is the first rendition in the .m3u8), moves next to 1080p, and stays there. So it looks great.

That’s a vod, so I thought I’d try live too. I picked a random demo .m3u8 from AWS IVS: https://4c62a87c1810.us-west-2.playback.live-video.net/api/video/v1/us-west-2.049054135175.channel.LaSuL3bHBRR7.m3u8 Again, I played that using the same page hls.js demo so it’s the same player, config etc. It started from the 1080p, and stayed there. So it looked great too. No quality issues there.

So … it’s either that the files being served from Cloudflare are served slower (and so the HLS JS logic doesn’t think it can safely auto switch up to a higher quality) or that the bandwidth values used by Cloudflare are much higher than other platforms. For example it seems that the AWS IVS demo uses around 5mbps for 1080p, while Stream uses 11mbps. It would make sense players would be more willing to switch up if the absolute bandwidth value they would parse from the .m3u8 is lower.

There doesn’t seem any way to change the bitrates used by Stream to lower values. I can try one of the suggested solutions to proxy the .m3u8 to change the ordering and/or fake the bandwidth values down to lower ones to make the player more willing to pick it and/or download the lot and serve it from my own CDN, but neither is ideal.

Has anyone else had any luck with fixing the quality?

Related to How do you set the default stream video quality to 1080p?

Hi gregsanderson,

The problem appears to be that the bitrate is 1) way higher than the HLS specs for each quality level, and 2) the bitrate in the manifest doesn’t match the actual stream that’s served, so the players struggle to work out what to do. I’ve reached out to a couple of different player vendors who came to the same conclusion.

Someone on the Cloudflare team did reach out, and mentioned that they are working on a fix. This was about 5 months ago, and despite several attempts I’ve not been able to get any update on the situation or an ETA for the fix, so for the time being we’ve had to move to another solution for video delivery :frowning:

1 Like

Thanks @sesmale

That makes sense. Yep it’s disappointing.

I’m thinking a quick fix could either be to override the HLS JS logic internally so while it would initially parse the .m3u8 and get the values provided by Stream, I could change them locally using JS to be lower ones. And then in theory HLS JS will be more willing to auto-switch. That wouldn’t work on iOS or native, but would on desktop.

Or proxy the Stream .m3u8 (e.g via a Worker) and in real-time re-order and change the values within it.

(Or try another solution, as you have)

Update to this for anyone else coming here having the same issue:

From my experiments this weekend, it seems to be due to the way bandwidth is estimated by the players. Hence why it affects auto, not manual, quality selection. The player has to figure out the bandwidth and pick a suitable rendition. If it thinks the bandwidth is low, it naturally picks the worst quality (e.g 240p). And that is what’s happening here. If you load up a .m3u8 using e.g the HLS demo app, and in the console type in hls.bandwidthEstimate you get a real-time value of what the HLS JS estimates the bandwidth to be. For e.g the Bunny test vod .m3u8 linked above, it’s correct. For a Stream .m3u8, it’s very wrong. It’s far too low. And that explains why it picks the 1080p for the Bunny vod, but 240p for the Stream.

The question then is why is it wrong. I see there is an open issue:

Sure enough the Bunny vod had 10s segments, and so each segment was far bigger in size. It would follow that the bandwidth estimate would be more accurate. Since the latency part of the timing would be outweighed by the transfer part. The shorter the segment and the smaller the bitrate, the smaller the file size. And so the less accurate the bandwidth estimate and so the greater the chance of it sticking to the lowest rendition (as it thinks that is all the connection can support).

However this can’t be the whole story since other providers use e.g 2s segments (which I also made on Stream by forcing a keyframe every 2s, and Stream notes that and also produces 2s segments). The Stream .m3u8 stayed stuck on the 240p, whereas the other provider jumped to 1080p and stayed there. Again, because the bandwidth estimate was higher and so the player figured (correctly) it could use a higher bitrate. Hmmm.

I see there is a pull request to change how the bandwidth is estimated which may help when that gets merged. The only other thing I can think for now is to use a custom loader to pretend the bandwidth values are lower than they are, and so the player will be more willing to pick a higher one. As that (faked) low bandwidth would be under its estimate. HLS JS defaults to a 0.7 multiplier, it seems. The trade-off is that if the connection really is bad, the player would pick a rendition that actually could not play smoothly and so that viewer would suffer buffering.

This happens when you open the m3u8 file directly in Safari or put it in a <video> element too. It only happens with Cloudflare stream. Adding ?clientBandwidthHint=10​ to the url it ramps up to 1080p immediately.

I created a ticket for this (2635804) but so far there’s not much progress.