Skip to content

Essk/vjs10-ads

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vjs10-ads

Ad state management for Video.js 10. Despite the aspirational title, it's just a learning exercise in building custom features for the VJS 10 architecture, not a proposal. However, if the implementation here can help anyone else figure their solution out, so much the better.

The state machine and integration API are modelled after videojs-contrib-ads. It's a hands-on exploration of how custom features, media element mixins, and store-driven state fit together in VJS 10.

What it does

  • Tracks the ad lifecycle (preroll, midroll, postroll) via a finite state machine
  • Intercepts play requests at the media element level so preroll ads can run before content
  • Provides a positioned ad container element for ad SDKs to render into
  • Exposes state actions (startLinearAdMode, endLinearAdMode, etc.) that ad integrations call to drive transitions
  • Dispatches DOM events (readyforpreroll, readyforpostroll) on the media element so integrations know when to act

Architecture

The library is split into three pieces, all created through a single createAds() factory:

AdVideo -- A custom media element that wraps <video> via CustomVideoElement and registers with the player via MediaAttachMixin. Overrides play() to block playback when the state machine requires it (e.g., waiting for a preroll). The store sees it as a normal media element.

adsFeature -- A VJS 10 store feature that owns the ad state machine. Exposes actions like startLinearAdMode() and endLinearAdMode() on the store. Subscribes to state changes in attach to dispatch DOM events and control playback.

AdContainer -- A simple custom element positioned over the video. Ad SDKs (IMA, FreeWheel, etc.) render their UI into this element.

Usage

import { createAds } from 'vjs10-ads';
import { createPlayer, MediaElement } from '@videojs/html';
import { videoFeatures } from '@videojs/core/dom';

const { adsFeature, AdVideo, AdContainer } = createAds({ debug: true });

const { ProviderMixin } = createPlayer({
  features: [...videoFeatures, adsFeature],
});

class MyPlayer extends ProviderMixin(MediaElement) {
  static readonly tagName = 'my-player';
}

// Definition order matters: provider first, then media element, then consumers
customElements.define('my-player', MyPlayer);
customElements.define('ad-video', AdVideo);

await import('@videojs/html/media/container');
await import('@videojs/html/video/skin');

customElements.define('ad-container', AdContainer);
<my-player>
  <video-skin>
    <ad-video src="video.mp4" playsinline></ad-video>
  </video-skin>
  <ad-container></ad-container>
</my-player>

Integration API

An ad integration listens for events on the media element and calls actions on the store:

const adVideo = document.querySelector('ad-video');
const player = document.querySelector('my-player');

// The feature dispatches this when the state machine enters adBreak(preroll, waiting)
adVideo.addEventListener('readyforpreroll', () => {
  // Load and start your ad
});

// Tell the state machine what's happening
player.store.state.startLinearAdMode();  // ad playback started
player.store.state.endLinearAdMode();    // ad playback finished
player.store.state.skipLinearAdMode();   // ad was skipped or timed out
player.store.state.nopreroll();          // signal no preroll before play
player.store.state.nopostroll();         // signal no postroll

State machine

States: beforePreroll -> adBreak -> content -> done

The adBreak state is parameterised by ad type (preroll, midroll, postroll) and phase (waiting, active). There's also a separate stitchedContent / stitchedAdBreak path for server-side ad insertion.

See src/stateMachine.ts for the full transition table.

Options

createAds({
  timeout: 5000,         // default timeout for ad breaks
  prerollTimeout: 5000,  // override for preroll
  postrollTimeout: 5000, // override for postroll
  stitchedAds: false,    // enable stitched ad flow
  debug: false,          // log state transitions to console
});

Demo

The demo/ directory has a working example using Google IMA3 with preroll and simulated midroll. To run it:

npm install
npm run dev

Status

This is a work in progress and a learning exercise. Things that are not yet implemented:

  • Postroll flow (the state machine supports it, but nothing triggers contentended yet)
  • Timeouts (options are accepted but no timers are started)
  • Stitched ad flow (states exist but are untested)
  • Tests
  • contentchanged handling for source switches

AI

AI Contribution

I relied on AI heavily for research, design against the VJS10 framework and trouble shooting, but kept control of design descions and most of the actual code was written by hand.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors