From 4ad575d50eeebafb78f68d7e25d1807fa50adc94 Mon Sep 17 00:00:00 2001 From: Rob Walch Date: Fri, 16 Feb 2024 15:43:11 -0800 Subject: [PATCH] Shift DateRange metadata Cue times when media timeline is shifted Fixes #6203 --- src/controller/id3-track-controller.ts | 43 ++++++++++++++++++++------ 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/controller/id3-track-controller.ts b/src/controller/id3-track-controller.ts index f0b89523a2d..a11ed785d6b 100644 --- a/src/controller/id3-track-controller.ts +++ b/src/controller/id3-track-controller.ts @@ -10,10 +10,12 @@ import { isDateRangeCueAttribute, isSCTE35Attribute, } from '../loader/date-range'; +import { LevelDetails } from '../loader/level-details'; import { MetadataSchema } from '../types/demuxer'; import type { BufferFlushingData, FragParsingMetadataData, + LevelPTSUpdatedData, LevelUpdatedData, MediaAttachedData, } from '../types/events'; @@ -95,7 +97,7 @@ class ID3TrackController implements ComponentAPI { this._registerListeners(); } - destroy() { + public destroy() { this._unregisterListeners(); this.id3Track = null; this.media = null; @@ -112,6 +114,7 @@ class ID3TrackController implements ComponentAPI { hls.on(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this); hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this); hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this); + hls.on(Events.LEVEL_PTS_UPDATED, this.onLevelPtsUpdated, this); } private _unregisterListeners() { @@ -122,17 +125,18 @@ class ID3TrackController implements ComponentAPI { hls.off(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this); hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this); hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this); + hls.off(Events.LEVEL_PTS_UPDATED, this.onLevelPtsUpdated, this); } // Add ID3 metatadata text track. - protected onMediaAttached( + private onMediaAttached( event: Events.MEDIA_ATTACHED, data: MediaAttachedData, ): void { this.media = data.media; } - protected onMediaDetaching(): void { + private onMediaDetaching(): void { if (!this.id3Track) { return; } @@ -146,13 +150,13 @@ class ID3TrackController implements ComponentAPI { this.dateRangeCuesAppended = {}; } - createTrack(media: HTMLMediaElement): TextTrack { + private createTrack(media: HTMLMediaElement): TextTrack { const track = this.getID3Track(media.textTracks) as TextTrack; track.mode = 'hidden'; return track; } - getID3Track(textTracks: TextTrackList): TextTrack | void { + private getID3Track(textTracks: TextTrackList): TextTrack | void { if (!this.media) { return; } @@ -169,7 +173,7 @@ class ID3TrackController implements ComponentAPI { return this.media.addTextTrack('metadata', 'id3'); } - onFragParsingMetadata( + private onFragParsingMetadata( event: Events.FRAG_PARSING_METADATA, data: FragParsingMetadataData, ) { @@ -243,7 +247,7 @@ class ID3TrackController implements ComponentAPI { } } - updateId3CueEnds(startTime: number, type: MetadataSchema) { + private updateId3CueEnds(startTime: number, type: MetadataSchema) { const cues = this.id3Track?.cues; if (cues) { for (let i = cues.length; i--; ) { @@ -259,7 +263,7 @@ class ID3TrackController implements ComponentAPI { } } - onBufferFlushing( + private onBufferFlushing( event: Events.BUFFER_FLUSHING, { startOffset, endOffset, type }: BufferFlushingData, ) { @@ -291,7 +295,23 @@ class ID3TrackController implements ComponentAPI { } } - onLevelUpdated(event: Events.LEVEL_UPDATED, { details }: LevelUpdatedData) { + private onLevelUpdated( + event: Events.LEVEL_UPDATED, + { details }: LevelUpdatedData, + ) { + this.updateDateRangeCues(details, true); + } + + private onLevelPtsUpdated( + event: Events.LEVEL_PTS_UPDATED, + data: LevelPTSUpdatedData, + ) { + if (Math.abs(data.drift) > 0.01) { + this.updateDateRangeCues(data.details); + } + } + + private updateDateRangeCues(details: LevelDetails, removeOldCues?: true) { if ( !this.media || !details.hasProgramDateTime || @@ -303,7 +323,7 @@ class ID3TrackController implements ComponentAPI { const { dateRanges } = details; const ids = Object.keys(dateRanges); // Remove cues from track not found in details.dateRanges - if (id3Track) { + if (id3Track && removeOldCues) { const idsToRemove = Object.keys(dateRangeCuesAppended).filter( (id) => !ids.includes(id), ); @@ -376,6 +396,9 @@ class ID3TrackController implements ComponentAPI { if (cue) { if (durationKnown && !appendedDateRangeCues.durationKnown) { cue.endTime = endTime; + } else if (Math.abs(cue.startTime - startTime) > 0.01) { + cue.startTime = startTime; + cue.endTime = endTime; } } else if (Cue) { let data = dateRange.attr[key];