question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unexpected invocation to startLinearAdMode

See original GitHub issue

Hi, there is a bug with the PlayerWrapper class.

The bug occurs when you try to load a pre-roll ad that takes more than the time specified in the prerollTimeout setting to load.

The problem is that when the adtimeout event is triggered and then the adsready event is triggered, the pre-roll ad is displayed but UI is not updated to reflect that. For example, the vjs-ad-playing is not added to the player and the content playback is not resumed after pre-roll is ended.

The bug is caused because in the method onAdBreakStart the videojs-contrib-ads startLinearAdMode function is called, even if the adtimeout event was fired before.

This causes a WARN: ‘Unexpected startLinearAdMode invocation (Preroll)’, so this is an unexpected behavior for videojs-contrib-ads.

An easy way to reproduce this is set prerollTimeout in contribAdsSettings to a small value like 10.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:17 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
cdatehortuabcommented, Jul 22, 2019

Hi, @GavinThompson. In my case I can fix my specific problem adding this workaround to my code. Check it out! I could be good for you, too.

/* Work around (started pre-roll after timeout event) */
const AD_PLAYING_CLASS = 'vjs-ad-playing';
const EVENTS = {
  AD_STARTED: 'ads-ad-started',
  ADS_READY: 'adsready',
  AD_TIMEOUT: 'adtimeout'
};

const onAdCompleted = () => {
  player.removeClass(AD_PLAYING_CLASS);
};

const onAdStarted = () => {
  player.addClass(AD_PLAYING_CLASS);
  player.ima.addEventListener([
    imaSdk.AdEvent.Type.COMPLETE,
    imaSdk.AdEvent.Type.SKIPPED
  ], onAdCompleted);
  player.off(EVENTS.AD_STARTED, onAdStarted);
};

const onAdsReady = () => {
  player.on(EVENTS.AD_STARTED, onAdStarted);
  player.off(EVENTS.ADS_READY, onAdsReady);
};

const onAdTimeout = () => {
  player.on(EVENTS.ADS_READY, onAdsReady);
  player.off(EVENTS.AD_TIMEOUT, onAdTimeout);
};

player.on(EVENTS.AD_TIMEOUT, onAdTimeout);
/* End work around */
1reaction
renandecarlocommented, Aug 24, 2019

I’ve managed to get it working in two ways.

  1. Downgrading videojs-contrib-ads to version 6.0.0. I can confirm this problem started happening somewhere between 6.0.1 and 6.1.0.

  2. I’ve also managed to get it working by adding a check on SdkImpl.prototype.onPlayerReadyForPreroll to check if the player is not in resuming state, as it seems videojs-contrib-ads ask for it now, and also implicitly calling a resume/play function on videojs-contrib-ads endLinearAdMode() functions. However, this last option wouldn’t play ads if they loaded after the player was already resuming (unless you increased your prerollTimeout). And it seemed to happen quite a lot, so I stick with the first method.

There was also a secondary problem which seemd to happen. When the HLS was resuming from ads, it seemed to get stuck on loading sometimes. The main .m3u8 playlist was being fetched, but not the .ts segments.

I’ve managed to fix it by adding a play event on adend. As such:

player.on('adend', function(e) {
    player.play();
})`

Workaround 1: Use https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-ads/6.0.0/videojs-contrib-ads.js instead.

Workaround 2 (recent versions):

In videojs.ima.js, change:

SdkImpl.prototype.onPlayerReadyForPreroll = function () {
  if (this.autoPlayAdBreaks) {

To

SdkImpl.prototype.onPlayerReadyForPreroll = function () {
  if (this.autoPlayAdBreaks && !player.ads.inAdBreak() && !player.ads.isContentResuming()) {

In videojs-contrib-ads.js, wherever there is a endLinearAdMode() function, add this to the end:

var _this = this;
  this.afterLoadStart(function () {
  _this.resumeAfterNoPreroll(player);
});

You may want to increase your prerollTimeout in player.ima options too.

Read more comments on GitHub >

github_iconTop Results From Across the Web

videojs-contrib-ads - GitHub Pages
startLinearAdMode () (METHOD) – Invoke this method to start an ad break. For a preroll ad, you can invoke startLinearAdMode after the readyforpreroll...
Read more >
java - JMockit - Unexpected invocation - Stack Overflow
This happened because your hasDiscussion method was creating a new instance of Discussion class, and in this case, you can't mock it.
Read more >
Advertising with the IMA3 Plugin v3
Invoking this method creates a new IMA adManager which means that any previous ad response information (for instance, a postroll ad returned in ......
Read more >
JavaScript video js.log Examples
isContentResuming()) { videojs.log.warn('Unexpected nopreroll event (Preroll)'); } ... Ad plugin invoked startLinearAdMode, the ad break starts now.
Read more >
unexpected invocation: httpServletRequest.setAttribute
AssertionError: unexpected invocation: httpServletRequest.setAttribute("test", test) expectations: allowed, already invoked 1 time: httpServletRequest.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found