hls.js icon indicating copy to clipboard operation
hls.js copied to clipboard

Setting backBufferLength to 0 does not remove old buffered media as expected.

Open tmiller02 opened this issue 1 year ago • 3 comments

What version of Hls.js are you using?

1.5.16

What browser (including version) are you using?

Chrome 129.0.6668.100

What OS (including version) are you using?

macOS Sonoma

Test stream

No response

Configuration

{
  "debug": true,
  "enableWorker": true,
  "lowLatencyMode": true,
  "backBufferLength": 0
}

Additional player setup steps

No response

Checklist

  • [X] The issue observed is not already reported by searching on Github under https://github.com/video-dev/hls.js/issues
  • [X] The issue occurs in the stable client (latest release) on https://hlsjs.video-dev.org/demo and not just on my page
  • [X] The issue occurs in the latest client (main branch) on https://hlsjs-dev.video-dev.org/demo and not just on my page
  • [X] The stream has correct Access-Control-Allow-Origin headers (CORS)
  • [X] There are no network errors such as 404s in the browser console when trying to play the stream

Steps to reproduce

  1. Go to https://hlsjs.video-dev.org/demo
  2. Set backBufferLength to 0 and apply
  3. Play video and look at the media buffer under the timeline tab

Expected behaviour

The docs at https://github.com/video-dev/hls.js/blob/master/docs/API.md#backbufferlength state that setting backBufferLength to 0 should keep the minimum amount.

What actually happened?

Much more of the media buffer is kept than expected. However, setting the backBufferLength to a small value such as 1 does produce the expected behaviour.

This issue is potentially due to a change at https://github.com/video-dev/hls.js/blame/2fa668f9978673f86f6020dfe7bbc24c748f46e3/src/controller/buffer-controller.ts#L1130 the check for flushing the back buffer was changed to only apply if backBufferLength is greater than 0.

Console output

-

Chrome media internals output

No response

tmiller02 avatar Oct 16 '24 13:10 tmiller02

Hi @tmiller02.

Thank you for the bug report. Can you expand on what the expected behavior is with both settings (0 and 1).

HLS.js has to take care not to remove media from the buffer for the current GoP. If it removes the last IDR frame, media can be ejected at and past the playhead, interrupting video playback.

So I'm curious to know if the back buffer length is being correctly capped at 3 target (or segment) durations in either case. This means we also need to know about your playlist target and segment durations and where removal is actually happening in either case.

robwalch avatar Oct 16 '24 17:10 robwalch

Hi Rob,

Many thanks for your swift response. The issue is present on the demo site at https://hlsjs.video-dev.org/demo, with the Big Buck Bunny video where the target duration is set to 11 seconds.

When backBufferLength is set to 1, then media is being removed from the buffer, with just the preceding couple of segments being kept in the buffer. This is what I would expect to see, and is what I see when playing the Big Buck Bunny demo:

Screenshot 2024-10-16 at 19 19 58

However, when backBufferLength is set to 0, then it would appear that media is not being removed from the buffer by HLS.js at all. The first 30 seconds of media was removed from the buffer after around 6:30 minutes of playback, and I presume that may have been removed by the browser, not HLS.js.

Screenshot 2024-10-16 at 19 11 13

I would expect this to have worked in a similar way to when backBufferLength is set to 1, i.e. just the last few segments would be kept in the buffer. That was also the behaviour in older versions of HLS.js. However, it looks like setting backBufferLength to 0 now retains several minutes of video in the buffer, which in this case would be a few dozen segment durations.

I suspect this might have been inadvertently introduced at https://github.com/video-dev/hls.js/commit/301be58cc4efe58b45ec3d8287a5f942e4ff2522#diff-c4df8184b8ec1cc3d6647f954f28fc69f8d7fe0d54d005ac37adf75b7ac5139bR695

where the check to flush the back buffer was changed from something like

if (!Number.isFinite(backBufferLength) || backBufferLength < 0) {
  return
}
<flush the back buffer>

to

if (Number.isFinite(backBufferLength) && backBufferLength > 0) {
  <flush the back buffer>
}

but this means the new check will skip flushing the back buffer if backBufferLength is 0.

tmiller02 avatar Oct 16 '24 18:10 tmiller02

@tmiller02 do you need this patched in v1.5(.18)? Would you be willing to submit a fix?

robwalch avatar Oct 19 '24 13:10 robwalch

@robwalch no rush on getting this patched, as we have a simple workaround. Sure, I've opened a PR at https://github.com/video-dev/hls.js/pull/6784

tmiller02 avatar Oct 21 '24 09:10 tmiller02