MediaElement.js – a magic unicorn HTML5 video library

I”ve posted before about HTML5 video and based on what I found I released an HTML5 <video> framework and player called MediaElement.js. But I never got around to explaining the logic behind the new library so here it goes:

The Problems with HTML5 <video>

(1) Codecs

It has been well documented that browsers supporting HTML5 <video> don’t support the same codecs. Here’s the current breakdown of proposed(*) codec support including mobile browsers and plugins.

<IE9 IE9 Firefox Safari Chrome Opera Andriod iOS WP7 Flash Silverlight
H.264 X X X X X X X X
OGG X X X
WebM X* X X X X*

(2) Old Browsers

Even if codecs weren’t an issue, older browsers don’t understand the HTML5 <video> tag. This means you have to provide alternatives viewing mechanisms like Flash or Silverlight fallbacks.

(3) Style/UI

Each browser has a different UI for their HTML5 <video> players. You can write a player in JavaScript/CSS to bring consistency, but then older browsers will get a different UI when they fall back to Flash. Here are the native controls (from Opera’s tutorial)

Proposed Solutions

(1) Nested HTML

Video for Everybody from Kroc Camden is a pure HTML way of serving video that works in just about every OS/browser combination.
Pros:

  • No JavaScript requirement:  Video for Everybody is pure HTML with Flash nested inside for browsers that don’t understand the <video> tag.

Cons:

  • A lot of HTML: You’re probably going to need some backend code to help manage this since it’s very unruly to type on your own.
  • Requires multiple files: When a browser like IE8 hits the <video> tag which it doesn’t understand, it just skips it and moves on to the nested <object> tag inside. However, when a browser that does understand <video> comes along, it always ignores the nested code even if it can’t play the provided video file. So, if you try to server an OGG file to Safari or a MP4 to Firefox, you just get a black box with an X. This means you have to provide both MP4 and OGG files.

(2) JavaScript player with Flash fallbacks

This is the solution of every other library. They detect if the browser supports the <video> tag and if the browser can play the given file. If the browser can play the file, then a cool HTML/CSS/JS player is shown. If not, then the JavaScript replaces the <video> tag with an Flash player. You can find a great list of these players from Praegnanz’s HTML5 video list.
Pros:

  • Single Video file: This allows you to use a single H.264/MP4 which will work natively on IE9, Safari, Chrome, WM7, Andriod, and iOS. Firefox, Opera, and older browsers get a Flash player.
  • Same UI for HTML5: All browsers with HTML5 get the same UI instead of the browser default.

Cons

  • Inconsistent interface(s): While HTML5 browsers get the same UI, other browser get a different UI in Flash. If you just want someone to play a video, this isn’t really a problem. But if you need anything beyond basic video buttons, then you’ll have to build the feature twice, once in HTML/CSS (IE9, WebKit) and again for Flash (Opera, FF, <IE9). JW Player pulls this off, but overall this problem makes HTML5 video seem not worth the effort.

MediaElement Solution: Wrap the HTML5 spec around a plugin, then build the player

MediaElement.js goes at the problem a bit differently than the other JavaScript libraries. Instead of falling back to a full-fledged Flash video player for browsers that don’t support <video>, MediaElement inserts a tiny Flash object and wraps it with a JavaScript object that mirrors the HTML5 <video> spec.
This means that developers can write one set of code to MediaElement.js and have it work in every browser regardless of what it supports. And instead of just supporting Flash, there is also a Silverlight plugin that allows you to support more browsers (or avoid Flash on the Mac) and even put old WMV files that you don’t want to encode in a <video> tag.
On top of MediaElement (which is library independent JavaScript) and jQ

uery, I built MediaElementPlayer which is a sample HTML/CSS/JavaScript player that is easily skinnable through CSS and provides the same interface to every browser. Here’s how it works:

And here’s the result:

Pros

  • Single Video file: like the other JavaScript libraries, you can use a single MP4 file for everyone. Also, when Flash starts supporting WebM, you could use that and have Safari use the Flash plugin.
  • Single API: MediaElement gives you a single programming API defined by the W3.
  • Consistent UI: the controls are HTML/CSS even in Flash or Silverlight modes.

Bonus!

  • Double your codecs, double your fun: The Flash and Silverlight fallbacks enable the <video> tag to use additional media types like the older FLV (Flash video) format, Flash RMTP streaming, or even Window Media (WMA, WMV). MediaElement will choose the appropriate playback mechanism (native HTML5, Flash, or Silverlight) for your media and browser, and you’ll still get the same player UI.

Cons

  • Slight API differences: Because JavaScript doesn’t have native get/set properties, I’ve had to implement

    some HTML5 media properties as get/set methods. See http://mediaelementjs.com/ for the main changes [e.g. media.src becomes media.setSrc(url)]

Future Work

One gotcha with HTML5 video is the issue of fullscreen support. HTML5 video does not have a consistent way to do true fullscreen video (in fact, the HTML5 spec discourages it). You can expand the video to fill the browser, but currently only Safari provides a JavaScript API to do real fullscreen video (Chrome has the API, but it’s not implemented yet). Firefox can do fullscreen, but users must select it in a context menu. Also, Flash and Silverlight do not allow you to trigger fullscreen through the JavaScript API.
Also, I’d like to provide some example skins that mimic popular players like YouTube and Vimeo and a default theme that’s a little prettier.

Implementations

MediaElementPlayer

If you want a full-fledged player that just works, here’s the code:

<!-- requirements -->
<script src="jquery.js"></script>
<script src="mediaelement.js"></script>
<script src="mediaelementplayer.js"></script>
<link rel="stylesheet" href="mediaelementplayer.css" />
<!-- video tag -->
<video id="v1" src="myvideo.mp4" width="320" height="240"></video>
<!-- startup -->
<script>
$('video').mediaelementplayer();
// OR
new MediaElementPlayer('#v1');
</script>

MediaElement

If you want to build your own player using MediaElement and your own JavaScript, here’s a sample:

<!-- requirements -->
<script src="mediaelement.js"></script>
<!-- video tag -->
<video id="v1" src="myvideo.mp4" width="320" height="240"></video>
<!-- startup -->
<script>
var v = document.getElementsByTagName("video")[0];
new MediaElement(v, {success: function(media) {
	media.play();
}});
</script>

References

See Also

Hope you like it. GPL and MIT.

28 thoughts on “MediaElement.js – a magic unicorn HTML5 video library

  1. Wow, John, this is great. Besides the usual "hey this is broken" stuff, is there anything in particular I can help with for testing?

  2. Hi John – excellent work and most comprehensive I’ve found around. I’m testing your player inside our intranet for use with apple devices and so far its working like a charm! One thing I don’t see you address is the ability to point to a streaming server from the player. I wasn’t able to get it to work by simply changing the src to our rtmp URL. Any insights? By the way, any testing you would like me to do I’d be more than happy to do!

    1. first of all love it!
      secondly I did some testing with wmv files and found that when you set the type=”video/wmv” it works. this took me a while however since the browser actually returns ‘video/x-ms-wmv’ as the mime type for wmv files. I originally put type=”video/x-ms-wmv” which did not work. I am not really sure about how to make contributions to open source porjects so I thought Id put it here.
      me-namespace.js just needs to add ‘video/x-ms-wmv’ for silverlight
      http://support.microsoft.com/kb/288102

  3. Great work on the plugin! This is exactly what I was looking for last night for a site I’m building! I remembered John Saddington tweeting about the possibility of a plugin, so I’m happy you were able to get it put together.
    Is there a way to use the plugin to play content based on a user’s request? The site I’m putting together is http://CommuterBible.com and what I’m interested in being able to do is quickly play the audio MP3 of the ESV verse. It’s early in development (just did some work on it yesterday, that’s it). Based on some of your projects I think you’ll like the idea.

  4. I’ve got a small bug(?) with the setup at CommuterBible.com. The player doesn’t appear on the two Android phones I checked (Samsung Mystique I think). I’m just streaming audio. Anyone else having an issue with Android?

  5. Android does support the video tag, but strangely not the audio tag. It also fails to correctly report the video codecs it supports. But I’ll check and see if there’s a way to make it work with audio.

  6. Kevin,
    What are you using to test Palm Pre?
    I’m not sure what it’s capacities are. Theoretically, MediaElement should check for (1) native HTML5 media, (2) codec support, (3) Flash, (4) Silverlight.
    If all of those fail, then it should dump a link to the audio.

  7. Hi John
    is the flash video player for the fallback based on a framework or have you done it on your own?

  8. Thank you for this work. I have been trying to figure out the secret to universal video. I feel like this is getting me close. I installed this via the wordpress plugin and I had to make some edits to get it to work. In the file mediaelement-js-wp.php, the WP_PLUGIN_URL was pointing to a different location from where the plugin was actually installed. Second, if I used the mp4= attribute instead of src= I kept getting an error in the player. I found that looking in the generated page source that the type attribute of the source element was not formed correctly. It looked like this: type=’video/mp4"’. I edited that part of the script as well to eliminate the single quotes and add a leading double quote and that solved that problem.
    BTW this was wordpress 2.9.2.
    My video is an mp4 encoded using h264 (qt). I tried this on mac/safari, mac/firefox, win/chrome, win/ie8, win/firefox.
    Once I had the player working, I have a couple of other issues. The "click to start" seems to always show on the video even while it is playing. Other than that it seems to work okay in safari and chrome. On firefox (win and mac) I see the player window but clicking does nothing.
    On IE8 it plays okay, although the "click to start" text is bunched up at the top of the player window and only shows partially. Plus, IE is showing one of those little media icons in the upper left corner of the player window. I had two win/ie8 systems and one of them played the video and audio and the other was video only. Not sure what the difference was between them. Both had installed flash 10 plugin.
    I know that sounds like a lot but I’m not complaining. Just hoping that either I am doing something wrong, or else able to provide you with a useful bug report.
    The page I am testing is http://b2600ev.org/video-test-2.html in case you want to take a look. This is a temporary test page so I will be changing it as I experiment with the video formats and eventually take it down.
    Thanks for reading.

  9. Dario,
    I’m not too familiar with AAC streaming, but if that works in Flash, then you could force MediaElement to use Flash and then you’d be all set.

  10. Great plugin – I have only one problem…
    I am trying to get the audio player to work and then to skin it. The file will play but the time-handle, time-rail and time code do not update. Am I missing something?
    This is the page I am working on: http://www.millswilliams.co.uk/?p=33
    Also, how do you get iPhone and iPad to default to the CSS Skin?
    I would absolutely be prepared to help on a default skin revamp in exchange for your support.

  11. Hi,
    We have been searching for a universal Audio Player for a while, and are very interested in your WordPress PLug-in implementation. But we are having the same issues as Nathan Monk. The player does not update in the time rail. When you "pause" and play again it does, but now loops the previous instance…
    We have tested this on both PC and Mac and various browser.
    BTW, this also happens with the audio player on the mediaelements web page…

  12. Hi John,
    Very nice job. It’s cool to hear music on my ipad finally! 🙂
    I have installed the wordpress plugin yesterday and it works fine except the bugs mentioned above – especially the double play (perhaps this may help: http://stackoverflow.com/questions/2737162/html5-firefox-playing-duplicate-videos-after-jquery-insert)
    Additionaly I have found a bad behavior that seems to be due to the HTML5 implementation in the browsers (Chrome etc…) : [b]even if the "preload" of the media file is set to "false", the browser does load the media.[/b]
    This is very uncool (for bandwidth, slow computers…) if there are several players in the same HTML page. I have found this trick: http://forums.macrumors.com/showthread.php?t=916983
    but I’m not good at Javascript enough to modify your code in such a way.
    What is your advice to solve this problem ? Wait for a better implementation of HTML5 in all the browsers or by-passing the problem by implementing the trick above?
    Thanks for your support!
    Regards,
    Simon

  13. Hey John,
    The mp3 on your page seems to work now? Did you fix it?
    Is this fix available yet in the WordPress Plug-in download? I noticed that your page says that you’re at 1.03, but the WP Plug-in is 1.01…
    Thanks!
    Suny

  14. I forgot to mention, that I was working with the wordpress plugin too. It does appear that the wordpress plugin is 1.0.1 whilst the stand-alone is at 1.0.3 – will the wordpress plugin be updated?

  15. Great start — and a much-needed solution to the iPhone dilemma. But I can’t get MediaElement up and running. Mediaelementplayer.js and mediaelementplayer.css are showing up as inactive in WP 3.0.1’s plugin edit window. I suspect it’s the location issue mentioned by Joe, but I’m not code-savvy enough to fix it.
    Still, looking forward to the next revision and wanted to get my email address in for updates.
    Thanks!

  16. Very nice framework, John. Thank you SO much for putting it together.
    I have one issue with the iPad implementation… It’s looking like the .mep-container and its attending divs and classes aren’t getting wrapped around the <video> element on the iPad version. They’re just not there. Is there a logic behind that? It’s difficult because I have the .mep-container targeted for all of my CSS positioning, which blows all the CSS out on the iPad version only.

  17. hi this works nice for me on desktop – This may seem a newby question but what are the core folders and files I should upload to my website? The whole package is around 30mb but im thinking thats mostly the demo stuff so wont upload that

  18. You’ve probably figured this out by now, John, but I also wondered which of the files from GitHub would get things up and running. I was reluctantly deciding that it was time for me to learn this “build script” stuff when I took one more look at the code.
    In case anyone else is still wondering, build/mediaelementplayer.min.css and build/mediaelement-and-player.min.js will get you up and running. If you look at the source of the demos in the demo folder, you can see that it links to files in the build folder.

  19. I am trying to get your player to output the src of the current video being played by the mediaelement player and cannot get it to output. Any insite would be great. Thanks again for the this great player.
    player.setSrc(‘_video/MP4/myvideo.mp4’);
    alert(player.src()); // does not output anything
    alert(player.src); // outputs undefined

Comments are closed.