Using HTML5 Video

By Brian Henderson on 2012-11-30

This Thanksgiving, Fragment joined small ad agency of the year Baldwin& to develop a very unique web experience. The idea was to create an seamless full-screen, interactive, video-driven site to be the home and final resting place of a fictional Thanksgiving character aptly named "The Thanksgiver."

You can visit him here: http://TheThanksgiver.com

The site, which would require heavy use of resizable high-definition video, seemed like a project fit for development in Flash. Initial ideation called for interactive elements/controls, hundreds of loadable video clips pulled at random or by unique ID, directed art and design for the entire interface, dynamic and animated text titles, some modern styling/visual effects, and a very friendly integration with Facebook's share function. Similar web applications are beautifully developed in flash and actionscript, offering a plethora of advantages and consistent experience to any flash-enabled browser (namely http://www.oldspicesavestheworld.com/). That is, of course, if your device supports flash.

This is where we decided to think differently.

Current methods of integrating the HTML 5 video element are less than elegant, but the results of toiling over its intricacies are simply beautiful. Many highly visual or aesthetically focused sites are beginning to use HTML5 video in some incredible installations (see: http://www.welcometothebathtub.com/, http://blacknegative.com/, http://thewildernessdowntown.com/). It's easy to assert that the full-bleed video experience is engaging? it produces some stunning results and is completely styleable with CSS. Combine this with the ease of developing user interfaces in HTML/CSS/Javascript, the video element's Javascript API and libraries like jQuery and you've got a slam dunk in terms of development.

The truly remarkable part of it all is the efficiency and image quality retention of HTML5 video-ready compression codecs, but (in its current state) this is also the bane of developing and integrating it.

Much like the specificity of CSS3 prefixes, each major browser prefers a different file type and compression. Fortunately, the big five browsers can all be satisfied with just three different files for each video (just three?!). This can present a substantial hurdle in development when dealing with a large quantity of clips if you don't have the encoding automation and capacity of vimeo or the like. For those less familiar with HTML5 video, a great breakdown of compression and file type support by browser can be found here: http://diveintohtml5.info/video.html#what-works.

Essentially, we were looking to stretch the boundaries of front-end development in crafting an accessible, interactive, and seamless video experience on the web without the use of plugins or browser add-ons.

Some major features of the site include the following:

  • All video display was handled with the video element.
  • Major animations such as cross-fading video clips and other fades were accomplished with jQuery.
  • Minor animations and transitions were achieved with CSS3 keyframes declarations, transition property, and the transform property.
  • Dynamic content (such as fetching new videos and their associative information) was of course handled with Ajax, JSON and MySQL.
  • Maintaining a seamless web experience meant eliminating page refreshes entirely. However, generating shareable URLs and dynamic open graph data for scraping involved a creative URL rewriting convention and Javascript-readable URI hashes (more on this below).

Staging a constant supply of video clips.

Since the entire site would be built around displaying 720p video, mitigating load times and delays was a top priority. After process mapping and strategizing, we began building functionality that would handle fetching, staging and transitioning video between two video DOM elements.

Much like an img element, the source(s) of video can be changed via jQuery, while the DOM element itself remains relatively unaffected. To perform automatic AJAX fetching of new video information from the database, an interval was set to query the video's currentTime (playhead position) and when it reached 10% of the duration of the video, a new video clip was fetched and staged in the inactive video container and a new interval was created to listen on that video element once it began playing.

The original site experience design included automatic crossfades to loopable interstitial clips. The function to execute this was largely the same? an interval was set on the loaded video clip (A) that, at the specified playhead position, would load the second video clip (B) in the lower z-Indexed video container, .hide() it, z-index it above the currently playing video (A) and before the end of clip (A), .play() clip (B) and .fadeIn(). The result was a 1-second crossfade transition between clips?blending them seamlessly. .load() was called on the video clip being staged behind the scenes near the beginning of the currently playing clip, thus allowing it to preload in the background while the active clip is played.

Using this method, the site can continuously load video new video clips by slotting them in video containers in an alternating pattern.

Dynamic open graph data and routing via URI hashes.

A huge component of the site was its ability to serve custom descriptions, titles and URLs for each individual 'thank' video in the open graph data. This became an opportunity for some creative (and challenging) URL rewriting strategy. As a user progresses through videos on the site, the URI hash is changed via Javascript to indicate the video ID that corresponds to the video that you just watched. When a user shares this URL with someone, the server (naturally) ignores the hash information, but the Javascript checks for a hash in the URI and if it's present, fetches the corresponding video and plays it first. However, this URL convention presented a problem when sharing via Facebook's share function.

When a Facebook user shares a URL, a bot scrapes the page at the URL for open graph data via PHP (with absolutely no Javascript). So, providing the the corresponding open graph data for a particular video meant using pretty URLs and passing the video's ID as a GET variable through URL rewrites. The site's PHP could then print the appropriate open graph data in the meta elements when the Facebook bot scraped the site. Furthermore, as each video plays, the open graph data on the page is replaced via jQuery and the 'Share this Thank' button is populated with a slug-type link. Thus, when sharing the link via the provided button, the Facebook preview is dynamically populated with the corresponding video's title, description and URL.

So what if someone visits the site with a slug-type link? The Javascript checks for that also and serves them the video identified in the URL if it's present. Voilá! Users never see a page refresh as each individual 'thank' video includes custom description copy, title and a shareable URL.

Adding dynamic graphic overlays.

The next fun component of the site was generating dynamic titles of each thank video that fade and zoom in. As each clip was played, the reusable #titler element was populated with the 'thank' title, given a CSS3 transition-duration equal to 45% of the duration of the video itself (so the animation would finish approximately half way through the clip), and scaled down [transform: scale(0.4)] while still hidden.

After a brief delay, the #titler element was faded in slowly and a new transform: scale(1) property was declared to scale the #titler to its full proportions for the duration we previously set.

Note: the original animation began at scale(1) and ended at scale(2.5), but this yielded pixelated text since the text was originally rendered at its original size and then effectively 'zoomed' to a larger size. By declaring an original scale of 0.4 and scaling up to 1, we can maintain the text's visual integrity throughout the animation.

In retrospect.

The project was a great fit for HTML5 video and jquery interactivity, but could have benefitted from a MVVM like knockout.js. If you're looking to dive into integrating HTML5 video, be sure to read up on file-type support, encoding specifications and device support for higher resolutions and bitrates. There's a lot of interactivity potential with such an accessible JS API and since video elements are styleable with CSS as well, the possibilities are endless stylish. As more features and attribute support is rolled out in browsers, I think we'll see a lot more use of HTML5 video in some fantastic installations.

For more information, I found these resources particularly helpful:

(1) http://www.w3.org/2010/05/video/mediaevents.html

(2) http://dev.opera.com/articles/view/introduction-html5-video/

(3) http://diveintohtml5.info/video.html