DEV Community

HLS Interstitials in Safari

Introduction

As mentioned in our previous post HLS interstitials doesn't work natively in Safari or in any other HTML5 player, but that doesn't mean that it can't work.

"Interstitial playback on Apple devices is accomplished using two players"(GettingStartedWithHLSInterstitials.pdf, p.3)

This is a common technique used in may AVOD services today, albeit without the ads being part of the HLS manifest, the client creates two <video /> elements and puts them on top of each other and simply switch between which <video /> element is visible.

This means that the only thing we are limited by is our ability to read the HLS interstitials from the manifest.

In this post we will focus on how to achieve this in Safari and in a future post we will show how to accomplish this using the excellent hls.js library.

Reading the manifest

Since HLS interstitials are added using the existing EXT-X-DATERANGE tag we can use the built-in browser APIs to read them.
In Safari they have achieved this using the TextTrack interface

// listen to the `addtrack` event to detect when a texttrack is added to the video element
video.textTracks.addEventListener('addtrack', ({ track }: TrackEvent) => {
  // check if the track is of kind "metadata", this is where Safari adds any EXT-X-DATERANGE information
  if (track && track.kind === "metadata") {
    // by default the track is disabled, set it to "hidden" to allow it to start parsing any EXT-X-DATERANGE
    track.mode = "hidden";
    // track.cues will now be populated with all available EXT-X-DATERANGES in the entire manifest!
    track.addEventListener("cuechange", async (evt) => {
      // if this event is dispatched the `track.activeCues` property will contain the active EXT-X-DATERANGE
    });
  }
});
Enter fullscreen mode Exit fullscreen mode

The EXT-X-DATERANGEs will show up in the cues/activeCues field of the metadata text track as DataCue, the specification for those cues are just in draft so they are subject to change. The relevant part for HLS interstitials is the following

 {
     value:
     {
         key: "X-ASSET-LIST",
         data: "<url to X-ASSET-LIST>"
     },
     startTime: 55,
     ...
 }
Enter fullscreen mode Exit fullscreen mode

Note that each X-* attribute of the daterange will show up as separate cues, so if you want full support for HLS interstitials you need to read from multiple cues to get a complete HLS interstitial configuration.

Using this technique we were able to create this simple PoC demo show-casing how HLS interstitials can look today in Safari.
The demo contains a preroll and two midrolls, one at 20s and one at 1m 40s.

Learnings

When implementing this little PoC we discovered two specific things that one needs to workaround to get this to work.

The metadata track becomes disabled.

When the interstitial video is playing the master video will disable the metadata track, which means that we can no longer read the EXT-X-DATERANGEs from the manifest.
Luckily the browser does dispatch the "onchange" event on the textTracks so we can force enable it if needed.

Safari reads a PDT of 0 as false

If you set the PDT of the HLS to #EXT-X-PROGRAM-DATE-TIME:1970-01-01T00:00:00.000Z Safari will not set the startTime field of the EXT-X-DATERANGE cue correctly, it will set all startTime fields to 0. A simple workaround if you control the HLS is to set it to 1 eg. #EXT-X-PROGRAM-DATE-TIME:1970-01-01T00:00:00.001Z

About Eyevinn Technology

Eyevinn Technology is an independent consultant firm specialized in video and streaming. Independent in a way that we are not commercially tied to any platform or technology vendor.

At Eyevinn, every software developer consultant has a dedicated budget reserved for open source development and contribution to the open source community. This give us room for innovation, team building and personal competence development. And also gives us as a company a way to contribute back to the open source community.

Want to know more about Eyevinn and how it is to work here. Contact us at work@eyevinn.se!

Discussion (0)