#jQuery seeThru - HTML5 video with alpha channel transparencies#
This jQuery plugin adds support for the lacking alpha channel in HTML5 <video>
elements.
The original data will simply be re-rendered into a canvas-element, therefore adding support for alpha information that can either be included in the source file for the video element or in a seperate <img>
-element.
##Direct Download## Click here to download the current version.
##Table of contents##
- Video Setup
- Basic Plugin Usage
- Options
- Additional methods
- Examples
- Too much jQuery?
- What about
requestAnimationFrame
? - CrossDomain issues with canvas elements
- Binding mouse events to your video
- Mobile devices & tablets
- Browser support
- Preparing video sources in Adobe After Effects
- tl;dr
- Changelog
- Licensing
##Video setup##
In default configuration the plugin assumes that the alpha information is added underneath the original video track (in the exact same dimensions, therefore a video of 400x300 target dimensions will have a 400x600 source file). The alpha information should be a black and white image with white being interpreted as fully opaque and black being fully transparent (colored information will be averaged).
For optimal results the color channel should be un-premultiplied. (see the Wikipedia article on Alpha Compositing for more info on what that is all about). If you need a tool to un-premultiply your imagery you can use Knoll Unmult which is available for quite a lot of packages.
For a basic introduction of how to encode and embed video for HTML5 pages see the great Dive into HTML5
###Example image:###
Note the jagged edges in the color channel(s) due to un-premultiplying:
put over a greenish/blueish background results in
Live Demo
###Static Mask###
It is also possible to source the alpha information from an <img>
-element not incorporated into the video. The plugin lets you use either the luminance information of the RGB channels (i.e. the image) or the image's alpha channel (see options for how to choose). In case the image does not fit your video's dimensions it will be stretched to those.
Live Demo
##Basic plugin usage## Basic HTML5 video markup should look something like this:
<video id="myVideo">
<source src="src.mp4" type="video/mp4" />
<source src="src.ogg" type="video/ogg" />
....
</video>
In case you are planning to have your video set to autoplay or loop you can do this when initializing the plugin. The lack of a loop option in Firefox will also be fixed when doing that.
To make the magic happen you just have to do the following:
Include jQuery (I built the plugin with 1.7.1 but it should be working with older versions down to 1.4 as well) and the plugin in your <head>
:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="jquery-seeThru.0.9.7.min.js"></script>
and then call the following jQuery method on your video (preferrably on $(document).ready
):
$(document).ready(function(){
$('#myVideo').seeThru();
});
If you specify dimension-attributes in your markup they will be considered, in case not the dimensions of the source file will be used (video with alpha included will of course turn out to be halved in height). To avoid flickering on pageload I'd recommend setting your video to display:none;
in your CSS.
In case you want to style the generated canvas elements, the generated markup (you don't have to add this portion - the plugin does this) looks like this:
<video style="display:none;">...</video><!-- video is hidden -->
<canvas height="XXX" width="XXX" class="seeThru-display"></canvas><!-- this is the actual "video" -->
<canvas height="XXX" width="XXX" class="seeThru-buffer" style="display: none;"></canvas><!-- this is just a helper element -->
If you just want to give the plugin a test-drive without having to prepare your own video you can download and use the example videos in the repo's media folder (also included in the zipped download).
##Options## There are a few options you can pass when calling the plugin:
fps
expects a number specifying the frame rate that will be used for rendering the video. It defaults to25
and should be adjusted to the frame rate of your source file for best results. If you are concerned about performance issues you can try decreasing the frame rate and therefore reduce the rendering effort the browser has to handle.start
defines the video's behavior on load. It defaults to'autoplay'
which will automatically start the video as soon as possible. Other options are'clicktoplay'
which will display the first frame of the video until it is clicked or'external'
which will just display the first frame of the video and wait for external JS calls (so you can build your own interface or something - note that although the<video>
is hidden it is still playing and controls the rendered image).end
defines the video's behavior when it has reached its end. It defaults to'loop'
which will loop the video. Other possibilities are'stop'
(it will just stop), or'rewind'
which will jump back to the first frame and stop. If you usestart:'clicktoplay'
along with'rewind'
or'end'
the video will be clickable again when finished.mask
lets you use the content of an<img>
node as alpha information (also black and white). The parameter expects a CSS selector (preferrably ID) that refers directly to an image tag, like'#fancyMask'
. In case it returns a collection (class passed), the first element is used - in case the selector matches nothing or a non-image node the option is ignored. Defaults to an empty string, so video information is used for the alpha.alphaMask
specifies if the plugin uses either the black and white information (i.e.false
) or the alpha information (i.e.true
) of the element specified in themask
parameter. Defaults tofalse
.height
can be used to control the height of the rendered canvas. Overrides the attributes of the<video>
-elementwidth
can be used to control the width of the rendered canvas. Overrides the attributes of the<video>
-elementforceRendering
is a flag used to control if the browser will stop rendering the canvas elements when they are scrolled out of the viewport (therefore not visible). This is set to false by default as it greatly improves performance (especially with more than one video on a single page), yet if it messes with something you want to do with the canvas elements you can always set the option to true and the canvas will be forced to update all the time.
This might look like this:
$('#myVideo').seeThru({fps : 12 , start : 'autoplay' , end : 'stop'});
or
$('#myVideo').seeThru({mask : '#imageWithAlpha', alphaMask: true});
##Additional methods##
Apart from init
, these methods are available:
updateMask
lets you swap the alpha source for a video that uses static alpha information. Has to be used along with a new selector asmask
parameter, the value foralphaMask
will be kept from init.revert
will revert the<video>
element back to its original state, remove the<canvas>
elements, all attached data and event listeners/handlersplay
andpause
can be used to control the playback of the video - basically the same as$('#video')[0].play()
, but still chainable
This might look like:
/* sets mask to element with id "newMask" */
$('#myVideo').seeThru('updateMask', {mask : '#newMask'});
or
/* destroys seeThru functionality and adds class "plainOldVideo" */
$('#myVideo').seeThru('revert').addClass('plainOldVideo');
or
/* pauses video and binds click handler to resume playback */
$('#myVideo').seeThru('pause').one('click', function(){
$(this).seeThru('play');
});
or
/* makes video play only on hover */
$('#myVideo').seeThru({start : 'external'}).hover(function(){
this.play(); //we can use the DOM element's methods here as well as `this` is the video
}, function(){
this.pause(); //we can use the DOM element's methods here as well as `this` is the video
});
##Examples##
Moving alpha
Static alpha
Swapping alpha sources
Video listening to external JS calls
Video playing on hover
##Too much jQuery?## If you do not want to use jQuery, but still think transparent video is nice, here's a gist showing how the basic principle works.
##What about requestAnimationFrame
?##
Although the requestAnimationFrame-API seems to be a great idea worth pushing, I am not too sure if this is of any help here (it will always aim for a 60fps frame rate which is way too high for 99% of all videos). Yet, I have built a branch that uses this API for testing purposes, outcome unknown (testing very welcome). In case someone reading this has any input or experience regarding this I'd be happy to hear from you!
##Cross Domain issues with canvas-elements##
Please note that JavaScript's canvas-methods are subject to cross domain security restrictions, so please be aware that the video source files have to be coming from the same domain (i.e. if the document that is calling seeThru
is on www.example.net
the video files have to be requested from www.example.net
as well), otherwise you will get a DOM Security Exception. Please also note that this also applies to subdomains, therefore you shouldn't mix www and non-www-URLs (an easy way to avoid this would be using relative pathes, btw).
##Binding mouse events to your video## To mimic a behavior as if the original video was still visible it will echo all mouse events fired by the canvas representation. This means that you can still do sth like:
$('#myVideo').seeThru(); // the <video> is hidden
$('#myVideo').click(function(){ //this is still working as a click on the `.seeThru-display`-<canvas> will be echoed by the video`
alert('But I thought I was hidden?');
});
The events that are echoed are: mouseenter mouseleave click mousedown mouseup mousemove mouseover hover dblclick contextmenu focus blur
##Mobile devices & tablets##
As most mobile devices and tablets (iPad I'm looking at you) use external video players to handle HTML5-video this plugin is not working on mobile Webkit / Safari / Android Browser (yet). This is definitely on our to-do-list (wishlist rather), although outcome is uncertain.
Apparently Android 3.1+ will play <video>
inline, but I do not have any experience regarding using it as a canvas source yet.
##Browser support##
Tested on Chrome, Firefox, Safari, Opera 11 and IE 9.0+
(the browser has to support <video>
and <canvas>
of course)
See caniuse.com for browsers that support <canvas>
and <video>
If you are looking for a tool to detect these features you should have a look at modernizr
##Preparing video sources in Adobe After Effects##
Put your animation with alpha in a composition:
Double the composition's height:
Duplicate your footage layer, align them, and use the second instance as Alpha Track Matte for a white solid:
Make sure you are using an unmultiplied (straight) version of your color source:
##tl;dr##
Put a black-and white alpha channel right underneath your <video>
source (in the same file), load jQuery and let the plugin do magical things:
$('#myRadVideoNeedsTransparencies').seeThru();
Voila! Here's an example. Ready to ?
##Changelog##
- v0.9.7: the original video will now echo mouse events triggered by the canvas represenation, so you can still "use" the hidden video element to bind events for user interaction, faster
- v0.9.6: elements that are not visible in the viewport will stop rendering to lower CPU usage, added the
forceRendering
option - v0.9.5: added simple video playback control methods:
play
andpause
- v0.9.4: fixed canvas updating issues when listening to external interfaces
- v0.9.3: added the
revert
method andwidth
andheight
options, fixed even more chaining issues, proper event namespacing - v0.9.2: added support for
alphaMask
, added the possibility to swap static masks viaupdateMask
, improved interpretation of colored images as black and white mask, improved performance, properly namespaced (seeThru
-prefix) the applied classes, fixed chaining issues, added error messages, nicer example pages - v0.9.1: added the
mask
option that enables the use of a static image as alpha information, also some minor improvements in overall perfomance - v0.9.0: first version
Older versions (< 0.9.6) are available at Google Code
##Licensing## This plugin is licensed under the MIT License, demo content, video and imagery is CC-BY-SA 3.0
##Thank you## Thanks to Jake Archibald, who had the original idea for this approach, Kathi Käppel who designed the lovely Mr. Kolor from the demo and Sebastian Lechenbauer for making fun of my git dyslexia.