-
Notifications
You must be signed in to change notification settings - Fork 2.7k
HLS Interstitials Support #6591
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
e88a6a9 to
8490088
Compare
…outside the primary program time range Addresses comment #6591 (comment) (cherry picked from commit ebe6c08)
Thanks for the repro. I've pushed a fix to the scheduler that corrects an assumption that the previous event before the last primary segment must always be the last interstitial event. ef72aa0 // last primary segment
const timelineStart = primaryPosition;
const integratedStart = integratedTime;
const segmentDuration = primaryDuration - primaryPosition;
integratedTime += segmentDuration;
const playoutStart = playoutDuration;
playoutDuration += segmentDuration;
schedule.push({
- previousEvent: interstitialEvents[interstitialEvents.length - 1],
+ previousEvent: schedule[schedule.length - 1].event || null,That caused a lookup here ( hls.js/src/controller/interstitials-controller.ts Line 1530 in 8490088
|
|
Checked it out and your change also fixed a bug where subtitle selection would only fetch the text playlist but not the fragments. See (
_loadFragForPlayback was never called. Although I was running the same stream with the interstitial offset exceeding the main timeline duration so I'm not sure how representable the bug was in general. Nonetheless, it's good to know.
Minor: Thought 1: let's say there's an interstitial at 10, Thought 2: |
…grated duration (cherry picked from commit 161bf44d0186a263bc82299fc09e52b913f2d2f8)
…itialsManager.skip()` (cherry picked from commit 928064edb0d802d1e6513bd509e65ef5c584f2e9)
(cherry picked from commit ffa6612c848033ea913c020e0e5355db710ff431)
(cherry picked from commit 1cc169ce64b26aff31929a510b8ff157558c9bb5)
(cherry picked from commit 34ab0ed5016a3c18e330ab136fd731c3d5c95fcc)
…nterstitials Make criteria for "append in place" more flexible (does not require snapping and allows for resume offset matching duration) (cherry picked from commit 856dfb09aeadc99c5f9788ca5e55310fd8fa4d3d)
(cherry picked from commit 446ef3cee40ab0f7337fe12c905905349f24d8f7)
…ce" mode Improve Interstitial logging and log media transfer and "appendInPlace" details Fix media transfer for Interstitials in "appendInPlace" mode, with abutting timing, and snap-in (cherry picked from commit 9911bc4b8f9d59a4843affd7b889b11aab2c0117)
Fix asset player startPosition with append-in-place timelineOffset Fix issues with item and asset lookup using Array.indexOf when object refererenes are replaced by Live updates Fix cue removal by asset players (cherry picked from commit eb44d8699e4fa48becdba377aa4a82ece6d1f6f3)
(cherry picked from commit c61f5e3f6c480212ea79ed68a511208fe8674b99)
(cherry picked from commit 1b843d5517a658cdbd20bbb5eb02a64bb0839291)
Add comments describing each field in `InterstitialsManager` API markdown (cherry picked from commit bcb2db84d1ffba18befd658b284695fb0a69f7d4)
…outside the primary program time range Addresses comment #6591 (comment) (cherry picked from commit ebe6c08)
df287da to
52cc78e
Compare
…outside the primary program time range Addresses comment video-dev/hls.js#6591 (comment)
This PR will...
Add support for HLS Interstitials parsing, playback, and events.
Design Details
The
InterstitialsControllerhandles HLS and media input and events for the primary HLS asset. It passes date range data to the scheduler to produce an array of Interstitial events and an array of event and primary items called the schedule.InterstitialsControllerhas:InterstitialsSchedulewhich produces Interstitial events and a schedule of items on level update. TheInterstitialsSchedulehasInterstitialEventobjects. Each event contains properties and getters for finding its place on the playback timeline as well as an array of interstitial assetsHLSAssetPlayerinstances call the player queue. EachHLSAssetPlayerwraps a child instance ofHlsused to preload and stream Interstitial assets.InterstitialsControlleradds a loader to the correspondingInterstitialEventwhile loading. The loader is removed and replaced by the asset list response once the request is complete.API Enhancements
Configuration options
interstitialsController. Setting this to null turns off Interstitial parsing and playback.enableInterstitialPlaybacktofalse(allowing for custom playout and ad managers)interstitialAssetListLoadPolicydefines the loading policy of X-ASSET-LIST JSONprimarySessionIdidentifies the parent player session that spawned the asset player (read fromhls.sessionId)assetPlayerIdis used to identify logs from asset playerstimelineOffsetis used to offset MSE appends of Interstitial content (not all Interstitial assets are appended inline at offsets; most require a MediaSource reset)New top-level API on
HlsinstancesbufferedToEndgetter returns a boolean indicating if EOS has been appended (media is buffered from currentTime to end of stream)bufferingEnabledgetter returns a boolean indicating whether fragment loading has been toggled with pauseBuffering() and resumeBuffering()interstitialsManagergetter returns anInterstitialsManager(or null). TheInterstitialsManageris an interface that provides access to Interstitial program and timeline data as well as methods for seeking across items and skipping Interstitial events.latestLevelDetailsgetter returns theLevelDetailsof the most up-to-date HLS variant Playlist datasessionIdgetter returns the session UUID assigned to theHlsinstancesessionIdvalue is used when assigning a _HLS_primary_id query parameter to interstitial requestsstartLoad()now includes a second optional argument to skip seeking on start (otherwise, HLS.js seeks following to the first optionalstartPositionargument on append)hasEnoughToStartgetter returns whether enough is buffered to seek to start position (fix: media buffer is not empty but video element buffer is empty #6571)startPositiongetter returns the resolvedstartPositionthat playback will begin at once media is appendedtransferMedia()method detaches and returns MediaSource and SourceBuffers non-destructivelyurlgetter returns the URL resolved from loadSource(url)Updated top-level API on
HlsinstancesattachMedia()enhancements for transferring MediaSource and SourceBuffers betweenHlsinstancesrecoverMediaError()now seeks to the value ofcurrentTimebefore the source reset is performed (BaseStreamController always honor config.startPosition when attaching(recovering) #6297)New Events for Interstitials
ASSET_LIST_LOADINGwhen a request is made for an X-ASSET-LIST JSON objectASSET_LIST_LOADEDwhen a response is received for an X-ASSET-LIST JSON objectINTERSTITIALS_UPDATEDwhen Interstitials are added, removed, or the schedule is updated following a variant playlist update or updated asset durations from X-ASSET-LIST JSON or asset playlist and media parsingINTERSTITIALS_BUFFERED_TO_BOUNDARYwhen the forward buffer reaches the boundary of the following schedule item (Interstitial event or primary segment)INTERSTITIAL_ASSET_PLAYER_CREATEDwhen an asset player instance is created to stream an Interstitial asset (will always be before attaching media to the asset player)INTERSTITIAL_STARTEDwhen streaming of an Interstitial event containing one or more assets has begun (may occur before X-ASSET-LIST JSON is loaded or playback has started)INTERSTITIAL_ENDEDwhen streaming of an Interstitial event containing one or more assets has ended - before resuming primary or starting the next eventINTERSTITIAL_ASSET_STARTEDwhen streaming of an Interstitial asset has begun (following the beginning of the event or the end of the last asset)INTERSTITIAL_ASSET_ENDEDwhen streaming of an Interstitial asset has ended (before the next asset or the event ending)INTERSTITIAL_ASSET_ERRORwhen an error occurs starting or streaming an Interstitial asset (this can include non-fatal errors such as stalling and errors that will end streaming of the asset, resulting in the schedule advancing to the next asset or fallback to primary)INTERSTITIALS_PRIMARY_RESUMEDwhen playback of primary content has begun or resumed from an Interstitial eventBUFFERED_TO_ENDwhen the last audio and video segments in the playlist have been appended (EOS signaled on all SourceBuffers)AUDIO_TRACK_UPDATEDsimilar to LEVEL_UPDATED fired for any update to audio group playlistsSUBTITLE_TRACK_UPDATEDsimilar to LEVEL_UPDATED fired for any update to subtitle group playlistsUpdated Events
MEDIA_ATTACHING,MEDIA_ATTACHED,MEDIA_DETACHING, andMEDIA_DETACHEDinclude additional information (depending on whether media is being transferred)New Errors for Interstitials
NETWORK_ERRORASSET_LIST_LOAD_ERRORnetwork error loading asset listASSET_LIST_LOAD_TIMEOUTnetwork timeout error loading asset listASSET_LIST_PARSING_ERRORasset list was not valid JSON or missing required dataINTERSTITIAL_ASSET_ITEM_ERRORan issue interrupted or prevented asset playback. This will result in skipping the remainder of the asset or falling back to primary content. The eventerrorwill contain more details. This type of error differs from theINTERSTITIAL_ASSET_ERRORevents forwarded from asset player errors.Build Constants
__USE_INTERSTITALS__build const/directive.Known Issues
Should address before release (in order of priority):
video element requires the autoplay or play() to be called on canplaythough after MediaSource reset from detach/attach for most schedule transitions (whenresolved with e1e515a (thanks to @matvp91 for calling this out)appendInPlaceis false).resolved with 5842cc2InterstitialsManagerprimary,playoutandintegrateddurations are non-finite for Live streams. These should be finite for easier mapping of controls.resolved with 0021cfd e84bc30 2c3c372hls.interstitialsManager.skip()does not skip Interstitial events that do not reset MediaSource (whereInterstitialEventappendInPlaceis true)No plan to address before release:
InterstitialEventappendInPlaceis true). Note that this only applies to Interstitials that overlap and replace primary segments completely which is not the case for most Interstitials. If you have content where this is a concern, please file an issue.seekTothat restrict schedule advancement.appendInPlacemode and allow for single element and timeline playback of breaks independent of the primary player,Asset lists are not being loaded when(decided this is not something we would address as asset-lists should only be loaded when there is clear intent to play the interstitial assets)enableInterstitialPlaybackis set to false. They should be loaded. The schedule needs to reflect the path taken when primary playback is chosen over interstitial playback.Resolves issues:
Checklist