axlotl
axlotl

Reputation: 1422

VIDEOJS: playing a pre-roll add before each playlist item

I'm using the videojs-playlist plugin along with Google's videojs-ima plugin. Everything works swimmingly except I am only getting a preload ad before the first video. I want one before each video in the playlist. Basic setup is boilerplate, but for reference:

this.player = videojs('currentvideo', { autoplay : true, fluid : true });
this.player.playlist(this.playlist);
this.player.playlist.autoadvance(5);

const skippable_linear = {google's test ad};
const options = {
    id: 'currentvideo',
    adTagUrl: skippable_linear,
    debug : true
};

this.player.ima(
    options
);
this.player.ima.requestAds();

I have tried various ways of manually calling ads from inside an 'ended' event handler, such as calling requestAds again:

const _this = this;
this.player.on( 'ended', function(){
    /* some other stuff */
    _this.player.ima.requestAds();
});

This does play an ad where I want it, but

  1. this breaks playlist's 'autoadvance' setting (next video doesn't start playing when the ad is finished), and
  2. this puts the player into "ad display" mode (scrubber is unavailable, etc).

Is there a simple way to just say, "play an ad now" programmatically? I've tried, without joy, to use all of the seemingly applicable methods exposed by both the ima plugin and the contrib-ads plugin it relies on. I'll admit here that this is the first time I've ever had to deal with videos that run ads, so I'm kind of a noob.

Upvotes: 2

Views: 3340

Answers (3)

OSanchez
OSanchez

Reputation: 1

I could do this successfully with

videojs-ima: 2.2.0
videojs-playlist: 5.1.0

You just have to listen to the beforeplaylistitem

Something like this works:

player.on('beforeplaylistitem', (event, item) => {
    const adtag = 'youradtag';
    player.ima.setContentWithAdTag(item.sources, adtag);
    player.ima.requestAds();
});

Note that requestAds() will only work after ads have been set for the first time, otherwise you'll get requestAds() is undefined.

Upvotes: 0

Piotr Ma'niak
Piotr Ma'niak

Reputation: 828

I ended up forking videojs-playlist, and adding the option to override the player.src method. Feel free to use it:

fw-videojs-playlist

Details on how to use it are all in the github readme (including an example with ima.setContentWithAdTag)

Upvotes: 1

Piotr Ma'niak
Piotr Ma'niak

Reputation: 828

I am trying to do the same thing. Just like you I failed when calling player.ima.requestAds() on events. I dug deeper and the best I could come up with is what I share bellow.

According to the videojs-ima API you have to use the setContentWithAdTag method instead of whatever you are using to switch the player content. In our case it is the player.playlist.next method.

I combined the code found in the videojs-ima examples with the original playlist.next to write my own next.

Then quite brutally I overrode the original plugin method.

Here's the code:

player.playlist(myPlayilst);
player.playlist.autoadvance(2);
player.playlistUi(); //videojs-playlist-ui

player.ima({
    id: 'video5',
    adTagUrl: 'thy adserver request'
});

//override playlist.next
player.playlist.next = function(){

    var nextIndex = 0,
        playlist = this.player_.playlist,
        list = this.player_.playlist();

//everything below is copied directly from the original `next` (except for the "//load with ad")

    // Repeat
    if (playlist.repeat_) {
        nextIndex = playlist.currentIndex_ + 1;
        if (nextIndex > list.length - 1) {
            nextIndex = 0;
        }

    } else {
        // Don't go past the end of the playlist.
        nextIndex = Math.min(playlist.currentIndex_ + 1, list.length - 1);
    }

    // Make the change
    if (nextIndex !== playlist.currentIndex_) {

    //load with ad
        this.player_.playlist.currentItem(nextIndex);
        this.player_.ima.setContentWithAdTag(
            this.player_.playlist.currentItem(),
            null,
            true);

        this.player_.ima.requestAds();
    /////

        return list[playlist.currentItem()];
    }
}

You will probably need to override other methods that change the current playback, like playlist.previous.

I use videojs-playlist-ui so in my case it was neccessary to change the onclick handler called switchPlaylistItem_. I used some good old brute force to do that like this:

videojs.getComponent('PlaylistMenuItem').prototype.switchPlaylistItem_ = function(e){
    this.player_.playlist.currentItem(this.player_.playlist().indexOf(this.item));
    this.player_.ima.setContentWithAdTag(
        this.player_.playlist.currentItem(),
        null,
        true);
    this.player_.ima.requestAds();
};

PlaylistMenuItem's prototype should be changed before initializing the player.

This solution works, but it feels hacky, so if anyone can come up with something cleaner, please share!

Upvotes: 4

Related Questions