THEOplayer 3.X Demo: Playlist and Caching

This page demonstrates how you can create a playlist and use the Cache API. We have two objectives in this demo:

  1. Create a playlist.
  2. Preload (cache) upcoming content.

The playlist is created through a combination of HTML, CSS, JavaScript and the THEOplayer API. The following events from the API are used:

  • ended: thrown when the current stream ends.
  • playing: thrown when the playback of media starts.

The preloading mechanism is built with the Caching API and the Player API:

  • timeupdate: thrown periodically when currentTime changes. We use this event to compute how much of the current video has already been played. If this exceeds 75%, we cache the upcoming playlist item.
  • CachingTask: a CachingTask can be started to preload content.

The result:

 
   

The HTML code:


<div class="container playlist">
	<div class="video-js vjs-fluid theoplayer theoplayer-skin theo-seekbar-above-controls"><!--42--></div>
	<div class="theoplayer-playlist-holder">
		<div class="theoplayer-playlist-menu"> </div>
		<div class="theoplayer-playlist-button-holder"><span class="fa fa-step-backward" onclick="goPrevious()"> </span> <span class="fa fa-step-forward" onclick="goNext()"> </span></div>
	</div>
</div>
    

The JavaScript code:

// information on setting up THEOplayer and the player object can be found at https://docs.portal.theoplayer.com/docs/docs/getting-started/web/web

var element = document.querySelector('.theoplayer');
var player = new THEOplayer.Player(element, {  
	fluid: true,
	libraryLocation: 'https://cdn.theoplayer.com/dash/theoplayer/'
});

player.autoplay = true;

// configure video playlist items
var playlist = [
	{
		source : {
			sources: {
				src : 'https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny_metadata.m3u8'
			}
		},
		title: 'Big Buck Bunny',
		description: 'Big Buck Bunny',
		poster: 'https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg'
	},
	{
		source : {
			sources: {
				src : 'https://cdn.theoplayer.com/video/star_wars_episode_vii-the_force_awakens_official_comic-con_2015_reel_(2015)/index.m3u8'
			}
		},
		title: 'Star Wars Reel',
		description: 'Star Wars Reel',
		poster: 'https://cdn.theoplayer.com/video/star_wars_episode_vii-the_force_awakens_official_comic-con_2015_reel_(2015)/poster.jpg'
	},
	{
		source : {
			sources: {
				src : 'https://cdn.theoplayer.com/video/tears_of_steel/index.m3u8'
			}
		},
		title: 'Tears of Steel',
		description: 'Tears of Steel',
		poster: 'https://cdn.theoplayer.com/video/tears_of_steel/poster.jpg'
	}
];

// create playlist UI
var listElement = document.createElement('ul');
var li;
for (i = 0; i < playlist.length; i++) {
	li = createPlaylistElement(i);
	listElement.appendChild(li);
}
var playlistMenu = document.querySelector('.theoplayer-playlist-menu');
playlistMenu.innerHTML = "";
playlistMenu.appendChild(listElement);

function createPlaylistElement(trackNumber) {
	var track = playlist[trackNumber];
	var trackLiElement = document.createElement('li');
	var trackNumberElement = document.createElement('span');
	trackNumberElement.className = 'number';
	trackNumberElement.innerText = trackNumber + 1;
	trackLiElement.appendChild(trackNumberElement);
	var trackThumbnail = document.createElement('span');
	trackThumbnail.className = 'thumbnail';
	var trackThumbnailImage = document.createElement('img');
	trackThumbnailImage.setAttribute('src', track.poster);
	trackThumbnail.appendChild(trackThumbnailImage);
	trackLiElement.appendChild(trackThumbnail);
	var trackTitleElement = document.createElement('span');
	trackTitleElement.className = 'title';
	trackTitleElement.innerText = track.title;
	trackLiElement.appendChild(trackTitleElement);
	trackLiElement.onclick = function () {
		player.source = track.source;
		active = trackNumber;
	};
	trackLiElement.setAttribute('id', 'theoplayer-playlist-menu-' + trackNumber);
	return trackLiElement;
}

// set initial item of the playlist
player.source = playlist[0].source;

var active = 0; // Which track from the playlist is now playing
player.addEventListener('ended', onEnded);
player.addEventListener('playing',changeActiveTrack);

// continue with the next item of the playlist when the current video has ended
function onEnded () {
	goNext();
}

// update selected item in the playlist
function changeActiveTrack () {
	var activeElement = document.querySelector('.active');
	if (activeElement) {
		activeElement.classList.remove('active');
	}
	document.querySelector('#theoplayer-playlist-menu-' + active).className = 'active';
}

// go to the previous item in the playlist
function goPrevious () {
	if (active > 0) {
		active -= 1;
		player.source = playlist[active].source;
	}
}

// go to the next item in the playlist
function goNext () {
	if (active + 1 < playlist.length) {
		active += 1;
		player.source = playlist[active].source;
	}
}

// caching logic
function configureCachingOfPlaylist() {
	var cached = []; // var to store which playlist item has already been cached
	player.addEventListener('timeupdate', function() {
	   var videoPercentage = Math.round(player.currentTime/player.duration*100);
	   // check if cache should happen
	   if ((active < (playlist.length - 1)) && !cached[active+1] && videoPercentage >= 75) {
			cached[active+1] = true;
			var task = THEOplayer.cache.createTask(playlist[active+1].source, {amount: '25%'});
			task.start();
	   }
	});
}
configureCachingOfPlaylist();