Introduction

Webshim's mediaelement feature implements the base features to view and control video and audio elements using HTML5 markup and DOM properties/methods. It also implements flv and streaming capabilities including youtube playback in all browsers.

This document does not describe how to use those native/polyfilled features. It only describes the extensions build on top of the standard.

Custom video controls for video and audio elements

Custom controls for audio/video elements can controlled through the replaceUI option. This option can be set to true, false or "auto". If the string "auto" was used the custom controls are only loaded and replaced for devices with some CSS3 support (i.e.: not IE8) and where the following media query matches: (min-device-width: 719px) (i.e. not smartphones, but tablets).


webshim.setOptions('mediaelement', {replaceUI: 'auto'});
webshim.polyfill('mediaelement');

The controls are only added inside elements with a class .mediaplayer (This can be configured through the selector option).. While webshims might load basic styling for the custom controls. The basic styling of this wrapper element including the video element itself has to be done in the normal stylesheet:


<style>
	/* add basic styles */
	.mediaplayer {
		position: relative;
		height: 0;
		width: 100%;
		padding-bottom: 56.25%; /* 16/9 */
	}

	.mediaplayer video,
	.mediaplayer .polyfill-video {
		position: absolute;
		top: 0;
		left: 0;
		height: 100%;
		width: 100%;
	}

	.touchevents .mediaplayer,
	.touch .mediaplayer {
		font-size: 24px;
	}

	@media (pointer:coarse), (touch-enabled), (-moz-touch-enabled), (-webkit-touch-enabled) {
		.mediaplayer {
			font-size: 24px;
		}
	}
</style>

<script>
	webshim.setOptions('mediaelement', {replaceUI: 'auto'});
	webshim.polyfill('mediaelement');
</script>

<div class="mediaplayer">
	<video poster="poster.jpg" controls="" preload="none">
		<source src="my-video.mp4" type="video/mp4" />
		<source src="my-video.webm" />
	</video>
</div>

Configure the controlbar

All controls option can be configured thorugh the jme option object (spelled Jamie = jQuery mediaelement).

For exmaple the .mediaplayer selector can be changed through the selector option.


webshim.setOptions('mediaelement', {
	jme: {
		selector: '.myplayer' //.mediaplayer
	}
	replaceUI: 'auto'
});
webshim.polyfill('mediaelement');

While the controls are fully styleable through CSS, the markup can be controlled by changing the barTemplate option:

Add overlays to the mediaplayer

Adding new overlays to a mediaplayer, for example to add share buttons (like, twitter), a logo or title and credits for a given video or audio source is easy without writing any JS code.


<style>
	.mediaplayer .logo {
		position: absolute;
		top: 5px;
		right: 5px;
		transition: all 400ms;
		opacity: 0;
		visiblity: hidden;
		/* add z-index, if needed */
	}
	.mediaplayer[data-state="idle"] .mylogo {
		opacity: 1;
		visibility: visible;
	}
</style>
<div class="mediaplayer">
	<video poster="poster.jpg" controls="" preload="none">
		<source src="my-video.mp4" type="video/mp4" />
		<source src="my-video.webm" />
	</video>
	<img src="mylogo.jpg" class="logo" />
</div>

Here is a simple example creating a title and a social bookmark/share menu:

Creating new Plugins and Controls

Creating new plugins/controls for the jme mediaplayer is quite easy using the $.jme.registerPlugin method. Due to the fact, that jme is loaded async, the plugin registration has to be wrapped inside a webshim.ready('jme', function(){}); call.

Let's create a control, which jumps the timeline by 10 seconds forward:

First we will create a simple plugin and in the second step we will add it to the controlbar.


webshim.setOptions('mediaelement', {
	replaceUI: 'auto'
});
webshim.polyfill('mediaelement');

webshim.ready('jme', function(){
	//register a plugin named 'jump-10'
	$.jme.registerPlugin('jump-10', {
		_create: function($control, $media, $base){
			$control.on('click', function(){
				$media.prop('currentTime', $media.prop('currentTime') + 10);
			});
		}
	});
});

The _create method of the plugin gets automatically passed your control element, the video/audio element and the .mediaplayer wrapper element. JME will automatically detect all elements with this class inside your mediaplayer and runs your create method on them. This means the code above will let your write the following HTML:


<style>
	.jump-10 {
		position: absolute;
		top: 10px;
		left: 10px;
		background: #000;
		color: #fff;
		z-index: 99;
		cursor: pointer;
	}
</style>
<div class="mediaplayer videoplayer ratio-16-9">
	<button type="button" class="jump-10">jump</button>
	<video controls preload="none" poster="/assets/media/sintel/sintel-trailer.jpg" style="height: 100%;">
		<source src="/assets/media/sintel/sintel-trailer.m4v" type="video/mp4" />
		<source src="/assets/media/sintel/sintel-trailer.webm" type="video/webm" />
	</video>
</div>

To add your new control to the JME's controlbar, simply extend the barTemplate with your new named JME plugin.


webshim.setOptions('mediaelement', {
	replaceUI: 'auto',
	jme: {
		barTemplate: '<div class="play-pause-container">{{play-pause}}</div>' +
		//here is your new jump-10 plugin:
		'<div class="jump-container">{{jump-10}}</div>' +
		'<div class="playlist-container"><div class="playlist-box">{{playlist-prev}}{{playlist-next}}</div></div>' +
		'<div class="currenttime-container">{{currenttime-display}}</div>' +
		'<div class="progress-container">{{time-slider}}</div>' +
		'<div class="duration-container">{{duration-display}}</div>' +
		'<div class="mute-container">{{mute-unmute}}</div>' +
		'<div class="volume-container">{{volume-slider}}</div><div class="subtitle-container">' +
		'<div class="subtitle-controls">{{captions}}</div></div>' +
		'<div class="fullscreen-container">{{fullscreen}}</div>'
	}
});

webshim.polyfill('mediaelement');

webshim.ready('jme', function(){
	$.jme.registerPlugin('jump-10', {
		//in most cases you also want to control the marup inside your controlbar
		//therefore you need to add the 'structure' option:
		structure: '<button class="{%class%}" type="button">&gt;&gt;</button>',
		_create: function($control, $media, $base){
			$control.on('click', function(){
				$media.prop('currentTime', $media.prop('currentTime') + 10);
			});
		}
	});
});

Here you find the full featured running example for a JME controlbar plugin:

Activating existing plugins

Webshim also comes with some predefined plugins. All plugins can be loaded/activated thourgh the plugins option, which takes an array of plugins to be automatically loaded.


webshim.setOptions('mediaelement', {
	replaceUI: 'auto',
	//request playlist plugin
	plugins: ['playlist', 'alternate-media']
});

//start loading mediaelement including plugins
webshim.polyfill('mediaelement');

In case a mediaplayer plugin adds some JS APIs, the code using those has to be wrapper inside a webshim.ready('plugin-name', function(){});


webshim.setOptions('mediaelement', {
	replaceUI: 'auto',
	plugins: ['plugin-name']
});

//start loading mediaelement including plugins
webshim.polyfill('mediaelement');

//wait until plugin-name is ready
webshim.ready('plugin-name', function(){
	//call ``pluginMethod``
	$('.mediaplayer').jmeFn('pluginMethod');
});

Creating a playlist

Webshims fully implements the mediaelement API, so that a developer can dynamically change the src property of a video element (using $.prop/$.attr) or create new source elements after the ended event has occurred.

But Webshim also comes with a great playlist plugin, which makes it easy to create multiple playlist for a mediaplayer.

Activating the playlist is simple:


webshim.setOptions('mediaelement', {
	replaceUI: 'auto',
	//request playlist plugin
	plugins: ['playlist']
});

//start loading mediaelement including plugins
webshim.polyfill('mediaelement');

To create a new playlist for a mediaplayer simply call $.jmeFn('addPlaylist') on the mediaplayer object.

The addPlaylist method requires at least a valid data source and an optional option object and returns the generated playlist instance:


webshim.ready('playlist', function(){
	$('.mediaplayer').jmeFn('addPlaylist',
		[
			{
				"title": "Only mp4 item",
				"srces": "play-item.mp4"
			},
			{
				"title": "Only mp4 item",
				"srces": {"src": "play-item.mp4", "type": "video/mp4"}
			},
			{
				"title": "Only mp4 item",
				"srces": {"src": "play-item.mp4", "type": "video/mp4"}
			}
		]
	);
});

Another example:


webshim.setOptions('mediaelement', {
	replaceUI: 'auto',
	//request playlist plugin
	plugins: ['playlist']
});

//start loading mediaelement including plugins
webshim.polyfill('mediaelement');

//wait until the playlist feature + DOM is ready
webshim.ready('playlist', function(){
	/**
	* Adding a playlist is done through the jmeFn's 'addPlaylist' method
	* addPlaylist receives two arguments:
	* 1. The list, which is either a) an array of play items, b) a string/URL to a valid data source or c) a DOM node or jQuery object, of a playlist with child elements, that are treated as playlist items
	* 2. Some options
	*
	* and returns the constructed playlist
	*
	* var playlist = $('.mediaplayer').eq(0).jmeFn('addPlaylist', 'path-to-rss-feet.xml', {showcontrols: true, autoplay: true});
	*/

	//The Playlist in this site is done with the following code:
	var playlist = $('.mediaplayer')
		.eq(0)
		.jmeFn('addPlaylist', 'mediaelement/playlist.json', {
			showcontrols: true,
			autoplay: true,
			ajax: {dataType: 'json'}
		})
	;

	playlist.render(function($playlist, $player){
		$playlist.insertAfter($player);
	});

});