cwallenpoole
cwallenpoole

Reputation: 82048

Google DAI mid-roll events not triggering with videojs

I am trying to get HLS video to work with videojs and Google mid-roll ads. Fortunately, I can get the video mid-roll working. Unfortunately, I don't get the ad started or ad ended events.

Below is a combination of the videojs-http-streaming example and the Google DAI example.

This is the markup I'm using.

<script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
<video-js id="my_video_1" class="vjs-default-skin"
  muted controls preload="auto" width="640" height="268">
</video-js>

<div id="click"></div>
<script src="https://unpkg.com/video.js/dist/video.js"></script>
<script src="https://unpkg.com/@videojs/http-streaming/dist/videojs-http-streaming.js"></script>

And this is the script:

var player = videojs('my_video_1');
var TEST_ASSET_KEY = "sN_IYUG8STe1ZzhIIE_ksA";
var videoElement = document.getElementsByTagName('video')[0];
var streamManager = new google.ima.dai.api.StreamManager(videoElement);
var clickElement = document.getElementById('click');
streamManager.setClickElement(clickElement);
streamManager.addEventListener([
    google.ima.dai.api.StreamEvent.Type.LOADED,
    google.ima.dai.api.StreamEvent.Type.ERROR,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED
], function(t){console.log(t);
   if(t.type == 'loaded') {
       player.src(t.getStreamData().url);
       player.play();
   }
}, false);
var streamRequest = new google.ima.dai.api.LiveStreamRequest();
streamRequest.assetKey = TEST_ASSET_KEY;
streamRequest.apiKey = '';
streamManager.requestStream(streamRequest);

I expect the console to output:

{type: "loaded", ...
{type: "adBreakStarted", ...

but all I see is the {type: "loaded", event.

How do I get all of the events to show up?

Upvotes: 0

Views: 1031

Answers (1)

cwallenpoole
cwallenpoole

Reputation: 82048

Credit where credit is due. I figured this out thanks to this repository.

So, in order for Google to produce the expected events, it needs to be informed of the status of the video metadata. Specifically, it needs access to the ID3 tag from the video stream.

Unfortunately, it doesn't have a way to get this with the native HTMLVideoElement. Instead, it needs to be informed of the information. In the case of jwplayer and hls.js it's simple (see below for the examples), but in the case of videojs it's a little less straightforward. You need to listen to the metadata track.

// I placed this right above player.src(t.getStreamData().url); above
// basically, you're looking at all of the tracks as they're added
player.textTracks().on('addtrack', function (e) {

  // find out if the new track is metadata
  var track = e.track;
  if (track.kind === 'metadata') {

    // a cuechange event fires when the player crosses over an ID3 tag
    track.on('cuechange', function () {
      let elemTrack = track.activeCues[0];

      if (elemTrack && elemTrack.value.data) {

        var metadata = {};

        metadata[elemTrack.value.key] = elemTrack.value.data;
        metadata["duration"] = Infinity;
        streamManager.onTimedMetadata(metadata);
      }

    });
  }
});

If you are using JWPlayer, it's a little simpler:

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

And hls.js is also pretty basic

hls.on("hlsFragParsingMetadata",
  function(event, data) {
    if (streamManager && data) {
      data.samples.forEach(function(sample) {
        streamManager.processMetadata('ID3', sample.data, sample.pts);
      });
    }
  }
);

Upvotes: 3

Related Questions