Plug-In Free Streaming Video
PLUG-IN FREE SERIES - Tutorial 3
Streaming video is something that has been around for many years. Oddly enough, as ubiquitous as sites like YouTube are, the HTML specification never supported streaming video prior to version 5. That meant in order to watch streaming video, you had to install a third-party plug-in. By far the most popular plug-in was Flash. But now, with HTML5, there is full support for streaming video without the need for additional plug-ins. An HTML5-compatible browser, such as Internet Explorer 9 and above, can handle streaming video directly.
Of course, this means your site needs to be coded with it. To this end, let's build an HTML5 streaming video player. The idea itself is quite simple, so we'll include a few extra HTML5 goodies to make it more than just a video player.
Before we dive in, however, let's look at the technology a bit, just so we're clear on what we're dealing with. There are several video formats available, but only a few work with the HTML5 specification. Certainly the most popular format is MPEG, the most recent version of which is MPEG-4 AVC. Internally, this format uses a form of compression called H.264, and together the format is known as H.264/MPEG-4 AVC. This format is available in Internet Explorer. Chrome, Safari, iOS, and Android. Other formats have been discussed by the HTML5 standards committee, and several open source formats were recommended. But this is the one that has been implemented almost universally-with one notable exception: Firefox. Firefox does not support this format natively. However, this is easily overcome, as you'll see in the code; we'll just specify multiple videos with different formats and the browser will choose the right one.
For our example here, we'll just link to a video, and initially you will want to use a touch version of Internet Explorer for these examples, if possible. (For example, if you have access to a Microsoft Surface or Surface Pro, that would be ideal.)
Some Simple HTML
At a minimum, HTML5 introduces a new element called video that lets you specify the URL of the video right in the HTML code. Here's a complete, fully functional HTML5 application:
<!DOCTYPE html> <html> <body> <video id="Video1" autoplay="autoplay" controls="controls" style="height:100%; width:100%; border:none;"> <source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.ogv" type='video/ogg; codecs="theora, vorbis"' /> <source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.webm" type='video/webm; codecs="vp8, vorbis"' /> <source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' /> </video> </body>
The video tag simply displays the video with the URL specified in the source elements. I included the style tags to show the video at full screen by setting 100% width and height; however, the video will maintain its aspect ration and display at a maximum width of 100%, with space filled vertically if necessary.
To simply include a video, that's all it takes. The browser will look at the source elements and pick the video that has the format the browser understands. But, we can do much more.
For the next part of this tutorial, let's use JavaScript to add a few more features. Specifically, we'll add a couple buttons that can start and stop the video, and then we'll add the ability to track some gestures.
Manipulating the Video Element with JavaScript
We can get the video element through getElementById then we can call any of the video object's methods.
One such method is called play. Here's some code that will automatically play the video when the page loads:
<!DOCTYPE html>
<html>
<body>
<video id="Video1" autoplay="autoplay" controls="controls"
style="height:100%; width:100%; border:none;">
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.ogv"
type='video/ogg; codecs="theora, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.webm"
type='video/webm; codecs="vp8, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.mp4"
type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
</video>
<script>
var video = document.getElementById('Video1');
video.play();
</script>
</body>
Although this has the same effect as turning on the autoplay attribute we originally included, this time we're doing it programmatically to demonstrate how you can access the video through code.
Next, let's add some buttons. We'll bring in jQuery to help make it even easier. All we need are a couple of buttons. Then we can add some event handlers to the buttons that call up the video object's methods. Here's the code:
<!DOCTYPE html>
<html style="height:100%">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body style="height:100%; overflow:hidden">
<div style="width:100%; height:100%; border:5px solid red; overflow:auto;">
<video id="Video1"
style="height:100%; width:100%; border:none;">
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.ogv"
type='video/ogg; codecs="theora, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.webm"
type='video/webm; codecs="vp8, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.mp4"
type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
</video>
</div>
<div style="position:absolute; left:10px; top:10px;z-index:9999">
<button id="StartButton">Start</button>
<button id="PauseButton">Pause</button>
</div>
<script>
var video = document.getElementById('Video1');
$('#StartButton').on('click', function() {
video.play();
});
$('#PauseButton').on('click', function() {
video.pause();
});
</script>
</body>
</html>
I put the buttons in their own div so we can make them appear in front in the upper left. Then, I removed the controls attribute of the video tag, which has the effect of removing the controls from the video player itself.
Adding Swiping Gestures
For people using mobile devices, your requirements might vary, but in the case of a video, typically you might not want them to do the usual "problem" of web pages that were clearly built for a desktop computer - load the web page, and then it appears as a full desktop webpage shrunk down to the size of a phone's screen, with a tiny little video that they need to zoom in to. Instead, you might want a video that takes up almost the entire screen, and maybe some controls at the bottom.
Quick note about the iPhone: On the iPhone, regardless of what controls you might add to your page, when the user loads your page, the video will be clickable; when the user then touches the video, it will open in a separate video app, using the iPhone's built-in app for showing a video. That means that anything you add to your HTML page won't be displayed while the video is showing, and any events you hope to grab through JavaScript won't happen either. Instead, you'll get a basic video viewer with the usual play, start, and stop controls, which in turn means that your the controls you create on your HTML page won't be functional.
Microsoft has provided us with some best practice for gestures.
When you're programming a native app (such as in C#), then you have access to a library of functions to help with the gestures. In the case of HTML5 and JavaScript, such a library isn't built into the browser as per the standards; however Internet Explorer does actually have support for gestures through vendor-specific CSS. This is actually pretty cool, and we can hope that the other browser vendors will want to implement the same thing. (Just as an FYI, vendors are free to include their own CSS styles; they start with a hyphen followed by a name describing the vendor, followed again by a hyphen. Microsoft-specific styles start with -ms; Mozilla-specific styles (such as for Firefox) start with -moz-; and Webkit-specific styles (such as in Chrome) start with -webkit-.)
Typically, the way JavaScript programmers now deal with browser differences is by using the native features when available, and when they are not, by re-implementing the features through JavaScript code. In our case, there are some libraries available, which I'll point you to shortly. But first, let's try out a bit of the Microsoft-specific gestures. Specifically, we'll give our user the ability to zoom in and out of the video by pinching on a touch surface such as the Microsoft Surface Pro.
The code is actually pretty easy to do; we just create a div tag and put our video element inside it. We then turn on the pinch-zoom feature using CSS.
Here's the style:
-ms-content-zooming: zoom;
Easy enough. But before we try it out, here's something to consider: We won't be zooming in on the video itself. Instead, we'll be zooming in and out on the div containing the video. That will cause the video inside the div to grow or shrink accordingly. But if it grows beyond the borders of the div, the parts that extend outside the div will be hidden.
To zoom in, we make the image bigger, thus showing a smaller part of the image stretched to the full size of the div. See how that works? Then to zoom out, we shrink the picture. (Imagine you're zooming out from the Earth: You ride in a space ship and get farther and farther from the Earth, looking down at the Earth as it appears to get smaller and smaller. Zooming out, therefore, means shrinking the picture, and zooming in means making it bigger.
To turn on the pinch-zoom capabilities, we simply add the -ms-content-zooming: zoom; style to the outer div. Internet Explorer will then grow or shrink the contents of the div automatically as the user pinches two fingers. But we can also set the upper and lower limit, like so:
-ms-content-zoom-limit-min: 10%; -ms-content-zoom-limit-max: 1000%;
The -ms-content-zoom-limit-min number is the minimum size, in this case 10% of the original. That's for zooming out. The -ms-content-zoom-limit-max number is the maximum size, which is for zooming in. This might seem backwards as we think of zooming in as looking at a smaller area, but it is what it is. If they did the numbers any other way, that would probably feel backwards too.
Here's the code, then. But remember, this only works in Internet Explorer; and further, to really try it out, you'll need a touch device such as the Surface Pro. (Next we'll revise it to work across browsers.)
<!DOCTYPE html>
<html style="height:100%">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<style>
.zoomElement {
-ms-content-zooming: zoom;
-ms-content-zoom-limit-min: 10%;
-ms-content-zoom-limit-max: 1000%;
}
</style>
</head>
<body style="height:100%; overflow:hidden">
<div style="width:100%; height:100%; border:5px solid red; overflow:auto;"
class="zoomElement" id="zoombox">
<video id="Video1"
style="height:100%; width:100%; border:none;">
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.ogv"
type='video/ogg; codecs="theora, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.webm"
type='video/webm; codecs="vp8, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.mp4"
type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
</video>
</div>
<div style="position:absolute; left:10px; top:10px;z-index:9999">
<button id="StartButton">Start</button>
<button id="PauseButton">Pause</button>
</div>
<script>
var video = document.getElementById('Video1');
$('#StartButton').on('click', function() {
video.play();
});
$('#PauseButton').on('click', function() {
video.pause();
});
</script>
</body>
</html>
This works wonderfully in IE 10. But what about other browsers? Let's take a different approach. Although we could build the code ourselves, there's a handy library on GitHub called hammer.js that handles touch and gestures for different browsers.
Using this library, we can insert some very handy JavaScript code that will respond to the gestures and manually resize the video inside the div element. Just one caveat: This library doesn't detect IE 10, and doesn't make use of the existing features. So we'll add code manually for that. However, detecting the user agent isn't as clear-cut as a lot of people think it is.
The problem is that if we check the browser name for IE 10, then what about IE 11 on up? And what if other browsers in the future decide to support the same gestures IE does? Instead, we'll use a more accurate approach: We'll check for the existence of the feature itself. If it's there, we use it; if not, then we use the library. We'll include the CSS regardless; browsers that don't support it will just ignore it. Microsoft has included just that feature for us in IE 10: We check for the existence of an object called msPointerEnabled. If it exists, we can use the MS touch features. If not, we'll fall back on the hammer.js library. Here's the if-statement we'll use:
if (!window.navigator.msPointerEnabled) {
// Add the hammer code here
}
And now we're ready to add the code. The hammer.js library includes an event handling system that works very much like jQuery; but instead of calling jQuery (or dollar, $), we call Hammer to get the element. The events we want to track are touch and pinch. When the touch starts, we note the current zoom size, and save it. When the pinching occurs, we get a decimal value noting the amount that was pinched. For example, .90 means the user pinched inward 90% of the starting point. A value of 2.00 would mean the user touched two fingers and spread them out twice as far as they started. So we take that percentage that is pinched, multiply it by the current zoom level, and set the new zoom level. Here's the final code:
<!DOCTYPE html>
<html style="height:100%">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="./hammer/hammer.js"></script>
<style>
.zoomElement {
-ms-content-zooming: zoom;
-ms-content-zoom-limit-min: 10%;
-ms-content-zoom-limit-max: 1000%;
}
</style>
</head>
<body style="height:100%; overflow:hidden">
<div style="width:100%; height:100%; border:5px solid red; overflow:auto;"
class="zoomElement" id="zoombox">
<video id="Video1"
style="height:100%; width:100%; border:none;">
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.ogv"
type='video/ogg; codecs="theora, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.webm"
type='video/webm; codecs="vp8, vorbis"' />
<source src="http://playground.html5rocks.com/samples/html5_misc/chrome_japan.mp4"
type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
</video>
</div>
<div style="position:absolute; left:10px; top:10px;z-index:9999">
<button id="StartButton">Start<button>
<button id="PauseButton">Pause</button>
</div>
<script>
var video = document.getElementById('Video1');
$('#StartButton').on('click', function() {
video.play();
});
$('#PauseButton').on('click', function() {
video.pause();
});
if (!window.navigator.msPointerEnabled) {
var startscale = 1.0;
var currentscale = 1.0;
Hammer($('#Video1')[0]).on('touch transform', function(ev) {
if (ev.type == 'touch') {
startscale = currentscale;
}
else {
currentscale = ev.gesture.scale * startscale;
$('#Video1').css('height', currentscale * 100 + '%');
$('#Video1').css('width', currentscale * 100 + '%');
}
});
}
</script>
</body>
</html>
Conclusion
Although we've looked at quite a bit of code, in reality there isn't a lot to it: We started with a video element; we set the sources for the videos; and we added some controls to start and stop the video. Then we brought in gestures. For touch-IE support, there's no JavaScript needed. But for other browsers, we need to add in a third-party library. What's next? Here's what I recommend: Take a look at the hammer.js page, and note the "Fake Multitouch" code that it includes in the documentation. That adds support for multitouch in the desktop computers that use a mouse. Try it out, and see if you can now add full zoom support for your desktop browsers. Have fun!
About the Author
Jeff Cogswell has nearly 25 years of experience as both a software engineer and a professional writer. He has worked on development teams, doing everything from low-level C programming on Unix up to high-level web development. In the past decade he has focused his work primarily on web development, including mastering such technologies as server-side programming with C#, and client-side programming such as HTML, XML, JavaScript, and Adobe tools, and now HTML5. He has authored numerous books, including C++ All-in-One for Dummies. He writes regular columns for SourceForge and SlashDot, including columns on parallel programming and development.











A Lap Around HTML5: HTML5 Graphics