Skip to content

Instantly share code, notes, and snippets.

@dmlap
Last active August 29, 2015 14:13
Show Gist options
  • Save dmlap/b70dbdbcaccc6707c531 to your computer and use it in GitHub Desktop.
Save dmlap/b70dbdbcaccc6707c531 to your computer and use it in GitHub Desktop.
Media Playlists

Media Playlists

Goals

  1. Single video plugins are compatible without needing to be playlist-aware
  2. Playlist events provide a consistent and predictable lifecycle for upstream developers

API

// load a playlist into a player
player.playlist([{
  sources: [firstMp4, firstOgv],
  poster: '//example.com/poster.jpg'
}, {
  sources: [secondMp4, secondOgv],
  textTracks: [{
    kind: 'captions'
    language: 'en'
  }]
}]);

// the current item is available
console.assert(player.playlist.item() === 0);
player.playlist.item(7); // change the current item to 7
console.assert(player.playlist[player.playlist.item()].indexOf(player.currentSrc()) >= 0);
console.log(player.playlist[1]); // the media object for playlist item 1
console.log(player.playlist.length); // print the number of items in the playlist

// playlist capabilities
// advance to the next media item in the playlist
player.playlist.next();
// return to the previous media item in the playlist
player.playlist.previous();
// advance to the next media item in the playlist as soon as the current item ends
player.playlist.autoadvance(0);
// advance to the next media item in the playlist 15 seconds after the current item ends
player.playlist.autoadvance(15);
// cancel auto-advance behavior
player.playlist.autoadvance(null);

// when the ended event fires for the last video in a playlist, playlistended fires
player.on('playlistended', function() {
  alert("We're all out of videos! Check back soon.");
});

Autoadvance

Autoadvance is off by default. If autoadvance is set to a negative number, an error is thrown. If autoadvance is set to zero, the next playlist item will be automatically loaded and begin playback when the ended event fires for the current item. If autoadvance is set to a number greater than zero, advancing the playlist and playing the next item will be delayed the specified number of seconds after the ended event. During the period between the firing of the ended event and advancing to the next playlist item, autoadvance behavior can be cancelled by calling the autoadvance method with any argument.

Ads Enhancements

One of the primary challenges with developing a playlist plugin is interacting safely with ad libraries. To simplify this process, we will prefix player events that happend during ad playback. This will ensure that plugins that do not wish to be aware of ads will see an event stream that is consistent with single video playback while still providing the notification to developers who need it.

The ended event will require special handling. It is not always possible for an ad integration to know before ended that a postroll is available and configured. That means contrib-ads may not be able to make the decision to bubble the ended event synchronously. We propose adding another timeout to the end of video playback and delaying the ended event until:

  • the ad integration has played a postroll and called endLinearAdMode()
  • the ad integration has indicated there is no postroll
  • the postroll timeout has expired

After these changes, the playlist plugin can treat playback with and without ads identically and use standard HTML5 video events to manage its state.

Timeline

Playlists should allow the creation of players that include:

  1. Zero or more pre-content segments. This can include advertisements, start slates, or bumpers for instance.
  2. A content video with zero or more interstitial segments. A mid-roll advertisement is an example of an interstitial segment.
  3. Zero or more post-content segments. Post-roll advertisements and end-slates are examples.
  4. An optional autoadvance delay.

Ad Timeline

Representation

Playlists will be accessible through a Javascript API. There will be no DOM representation.

VideoJS Playlist Plugins

@mmcc
Copy link

mmcc commented Jan 22, 2015

So just to play devil/steve's advocate here (we talked about this at lunch), what does the autoadvance delay alone really buy a dev? Thinking about the most basic use-case where someone just sets autoadvance to 15 seconds. The first video ends and the player just...sits there for 15 seconds. That would be pretty confusing UX unless there was some indicator of a timer.

Assuming we didn't have a delay, it doesn't seem like there's much work to implement it. Pseudo code:

player.playlist.on('transition', function() {
  showNeatoTransitionThingy();

  setTimeout(function() {
    player.playlist.next();
  }, 15000);
});

As I was typing that out, I started thinking we should just add a countdown somewhere to the UI and keep the delay and document this as an option. That keeps the developer ease of the default but doesn't leave the user hanging.

@gkatsev
Copy link

gkatsev commented Jan 22, 2015

Personally, I don't think we should be using getters/setters for new API we're building out that isn't trying to mimic native functionality.

@dmlap
Copy link
Author

dmlap commented Jan 23, 2015

Note to self: add a playlistended event

@apadhye
Copy link

apadhye commented Feb 9, 2015

I wish we could make auto-advance behave this way:
autoadvance(0) = plays immediately
autoadvance(positive integer) = plays with those many seconds delay
autoadvance(anything else) = autoadvance(default) = no auto advance

We can throw an error for invalid values for the publisher, so they know what's wrong, but at least this will not adversely affect the viewing experience for the end user.

Also adStart/adEnd is now adModeStart/adModeEnd

@mboles
Copy link

mboles commented Feb 26, 2015

  1. I could foresee a use case where the playlist would repeat. Could that be an option somehow on autoadvance, when the last video in the playlist plays it starts again from first video?
  2. Would it be possible to play an ad just at the beginning and/or just the end of the playlist?

@pcting
Copy link

pcting commented Feb 26, 2015

@dmlap, is there working code for this playlist proposal already? i'm in the middle of implementing a playlist plugin on a heavily modified a forked of videojs-playLists. i'm hoping to conform to this spec.

with regards to @mboles point #1, maybe a new property "loop" can be introduced for toggling between wrapping to the start/end of the playlist:

var nextIndex_ = function(i, len) {
  return Math.min(len - 1, i + 1);
};

var loopNextIndex_ = function(i, len) {
  if (i >= len - 1) {
    return 0;
  } else {
    return nextIndex_(i, len);
  }
};

var previousIndex_ = function(i, len) {
  return Math.max(0, i - 1);
};

var loopPreviousIndex_ = function(i, len) {
  if (i <= 0) {
    return len - 1;
  } else {
    return previousIndex_(i, len);
  }
};

player.playlist.next = function() {
  var func = options.loop ? loopNextIndex_ : nextIndex_;
  setItem_(func(options.index, options.items.length));
  player.trigger('next');
};

player.playlist.previous = function() {
  var func = options.loop ? loopPreviousIndex_ : previousIndex_;
  setItem_(func(options.index, options.items.length));
  player.trigger('previous');
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment