Timed Metadata in the IMA HTML5 DAI SDK

The HTML5 DAI SDK presents a simple and straightforward way of integrating with ad-enabled streams. However, you need to pay special attention to your handling of timed metadata.

Metadata basics

For live event streams, the stream needs some way of informing the SDK that an ad break is coming up or ending. In the IMA DAI SDK, this is done through timed metadata. Timed metadata is carried as part of the DAI stream content and carries ad break timing information used by the SDK to track ad breaks.

The SDK needs to receive data and timestamps from user-defined text information frames (TXXX frames) in the stream. There are two ways to pass this information to the SDK, depending on the way your video player parses metadata:

  1. StreamManager.onTimedMetadata()
  2. StreamManager.processMetadata()

onTimedMetadata()

onTimedMetadata() takes one parameter, a dictionary of processed timed metadata. This dictionary has a TXXX key that has the frame's data as the value.

Example

Object {"TXXX": "google_5913701834492172562"}

This method also expects your player to manage the timing of these calls, so onTimedMetadata() must be called when it is time to act on a piece of metadata's timestamp. So if your player has a metadata listener, you can call this method there. This works with players like JWPlayer:

JWPlayer example

jwplayer().on('meta', function(e) {
    if (streamManager && e.metadata) {
      streamManager.onTimedMetadata(e.metadata);
    }
});

processMetadata()

If your player provides access to unprocessed timed metadata, use processMetadata(). This method takes three arguments:

  1. The string,ID3
  2. A byte array of the ID3 tag itself
  3. The presentation timestamp (PTS) of the ID3 tag

You should see data TXXX frames where the data begins with 'google_' in a working DAI stream. This method can be called at any time, as the IMA SDK handles the resultant metadata timing based on the timestamps provided. We recommend calling processMetadata() as you receive metadata from your player. This approach works with players like hls.js and the Chromecast player.

hls.js example

var hls = new Hls();
hls.on(Hls.Events.FRAG_PARSING_METADATA, function(event, data) {
  if (streamManager && data) {
    // For each ID3 tag in the metadata, pass in the type - ID3, the
    // tag data (a byte array), and the presentation timestamp (PTS).
    data.samples.forEach(function(sample) {
      streamManager.processMetadata('ID3', sample.data, sample.pts);
    });
  }
});

Chromecast example

host.processMetadata = function(type, data, timestamp) {
  self.streamManager_.processMetadata(type, data, timestamp);
};

Troubleshooting

If you see AD_BREAK_STARTED and AD_BREAK_ENDED events firing in your video player during a live stream, you're passing timed metadata to the SDK correctly.

If you see google.ima.dai.api.StreamEvent.Type.ERROR events, you're passing in metadata that can't be parsed by processMetadata().