video-dev/hls.js

WebVTT: Text cues split over multiple segments with different timing causing duplicate subtitles

Hyddan opened this issue · 2 comments

What version of Hls.js are you using?

Latest (1.5.15)

What browser (including version) are you using?

Latest Chrome (128.0.6613.114)

What OS (including version) are you using?

Windows 11

Test stream

https://storage.googleapis.com/shaka-demo-assets/angel-one-hls/hls.m3u8

Configuration

{}

Additional player setup steps

hls.once(Hls.Events.MANIFEST_LOADED, (e, data) => {
  hls.subtitleTrack = 2;
});

Checklist

Steps to reproduce

Select the french subtitles of this stream (id: 2) and at the 4 second mark the subtitle will be duplicated.

Minimal reproduction available here:
https://hyddan.github.io/hls.js-duplicate-cues-reproduction/

Expected behaviour

I'm not sure if this should be a feature request rather than a bug, and I'm also not entirely sure what is the correct behavior here so if this is already working as it should then feel free to close this.. But it seems like when this subtitle was split over two segments the start time of it was altered - presumably clamped to the start time of the segment as the manifest states that it has 4-second segments.
This however means that the duplicate is not caught by hls.js's current duplication-catcher method which relies on the ids generated from the start and end times.

In my own setup, I have 'solved' this by matching on text content and, if found, modifying the times on the existing cue instead of adding it.

const cueByTextContent = findCueByTextContent(track, cue.text);
if (cueByTextContent) { // Adjust times instead of adding
  cueByTextContent.startTime = Math.min(cueByTextContent.startTime, cue.startTime);
  cueByTextContent.endTime = Math.max(cueByTextContent.endTime, cue.endTime);
}
else {
  track.addCue(cue);
}

Though I am not sure this would work well enough in a general case.

What actually happened?

Subtitles are duplicated.

hls js-duplicate-cues

Console output

N/A

Chrome media internals output

N/A

The VTT described, with overlapping times (please confirm if the overlap or this is a rounding error), are being rendered as expected. Adding a matching identifier to both VTT time range might work to deduplicate the cues but still would not result in merging of the time ranges.

The correct segmentation for these subs would be to either clip the overlapping time values (a should end at the time that b starts) or make both entries have the same start and end time (cues can extend beyond the start and end of a segment time range without being considered invalid).

This must be done in the WebVTT files. This is not something the client (hls.js) should do as it would result in incorrect rendering of properly segmented VTT where the repeating overlap is expected.

@robwalch in this case they don't overlap actually and it is not a rounding error.

In this particular case the the timing in the first segment is 00:00:03.837 --> 00:00:07.300 and in the second 00:00:04.000 --> 00:00:07.300 (presumably this start time is clamped to the start time of the segment), so here it would act more like deduplication instead of extending the range.

But the overlap case was what I mostly had in mind could be helped by merging the ranges. I can however agree that it is not hls.js' responsibility to handle that, especially since it is already possible to handle on the outside by disabling renderTextTracksNatively so we can close this.