The HTML5 video element is now included in Firefox, Safari & Chrome, and on its way in Opera. By using JavaScript to access the media elements API it’s easy to build your own custom controls for it; in this article I’m going to show how I built a (very) basic control interface.
A quick disclaimer: my JavaScript is a little rusty, so may not use best practice throughout; if you can see a way my code could be better, don’t hesitate to let me know.
Anyway, here’s the finished demo.
Getting started
First you must include the video
element. There are a number of attributes available, but for our purposes we need define only the Update: changed the markup to use the more correct src
, which is the URI of our video filesource
elements inside video
.
<video> <source src="filename.mp4"> <source src="filename.webm"> <source src="filename.ogg"> </video>
The video has been encoded twice, once in Theora and once in H264, to cater for different browsers; Kroc Camen’s Video for Everybody explains the reasons behind this (and how to make a bulletproof player). Update: added WebM support.
Having marked up a few controls with HTML (I’ve used id
attributes on all of them to make this demo easier), the next step is to write the JavaScript to access the API (which is well explained in this article at the Mozilla Developer Center) for the controls.
The first and most important control is the play/pause button; for this I’ve written a function which checks so see if the paused
attribute is true or false, and triggers the play()
or pause()
methods accordingly:
play.addEventListener('click',playControl,false); function playControl() { if (video.paused == false) { video.pause(); this.firstChild.nodeValue = 'Play'; pauseCount(); } else { video.play(); this.firstChild.nodeValue = 'Pause'; startCount(); } }
You’ll notice that it also updates the control text to indicate the action that the control will perform. There are also two function calls – pauseCount()
and startCount()
– which control the timer shown next to the play button.
The timer uses the currentTime
and duration
attributes (although the latter doesn’t seem to be currently supported by Chrome). To get the current time I’ve used setInterval
to create a loop:
function startCount() { t = window.setInterval(function() { if (video.ended != true) { timer.firstChild.nodeValue = Math.round(video.currentTime + 1); } else { play.firstChild.nodeValue = 'Play'; window.clearInterval(t); } },1000); }
First it uses an if...else
statement on the ended
attribute to check that the video has not finished playing; if it hasn’t, it updates the timer with currentTime
(plus a little maths). If the video HAS finished, it uses clearInterval
to stop the loop; this is also used in a function to pause the timer if the pause control is used:
function pauseCount() { window.clearInterval(t); }
To complete the controls we have functions to increase and decrease the volume. Both are very similar:
vUp.addEventListener('click',volUp,false); function volUp() { if (video.volume < 1) { video.volume = Math.round((video.volume + 0.1)*10)/10; volume.firstChild.nodeValue = Math.round(video.volume*10); } }
First they check that the minimum/maximum limits have not been reached, and increase/decrease the volume
attribute if not. Volume is on a scale of 0 to 1, and this function changes that value in increments of 0.1. The on-screen volume counter is also changed accordingly.
There are a number of small details elsewhere in the script, so feel free to have a dig through to see what else I've done; here's another link to the finished demo.
Further steps
I've obviously used a little CSS to tidy the controls up, but a lot more could be done; using images instead of text, for example, or perhaps using something like jQuery's user interface library to make more dynamic controls.
This article was intended only to show how easy it is to get started; what will be exciting is to see how these techniques can be expanded upon.
Update: If you found this article useful, you may be interested to know that I returned to this subject in a later post, Building a better HTML5 video player with Glow.
Hey I have a player in BETA and I still have problems with the seeking, how much has been played (buffer-bar, progress-time)
Thanks.
ps how do i do this?
(video.duration ? video.currentTime) ? 100; /* = “1.0002151”; */
jamesm [April 25th, 2010, 03:14]
Hi James, take a look at my follow-up tutorial, Building A Better HTML5 Video Player With Glow, for more information about this.
As for your second question, I’m not sure what the question marks mean in your example but if I understood it correctly it looks like you want to use Math.Round():
Math.round((video.duration ? video.currentTime) ? 100)
Hope that helps.
Peter [April 25th, 2010, 11:10]
[…] it might be interesting to me if I get deeper into HTML5 especially by using the <video> tag. I’ve read it comes to live in combination with […]
Basic HTML 5 videoplayer with playlist « Poppecast [June 20th, 2010, 09:15]
Very thanks .. I like make my own apps =)
Adrian Romero [December 17th, 2010, 06:38]
[…] year Peter Gasston wrote a post (Building HTML5 video controls with JavaScript) introducing the HTML5 Media Elements API and demonstrating a simple set of controls for playing […]
12 Brilliant HTML5 Video Players « The Creative Project [December 28th, 2010, 05:23]
Brilliant job Peter!!!
shahid karim [November 24th, 2011, 13:27]
I’m curious if you have to have any specific AddTypes to the htaccess file? I’m using the same video types on my project and I cant get the video to play in my Android 2.0 browser. When I go to to the demo however linked on this page it plays fine.
I have added ogv, webm and mv4 to my htaccess and when I try to play my videos on my server it says cannot play.
Jamie [January 22nd, 2012, 11:39]
i am trying to create a video player that i can watch live video and mark points of interest. How can i log a point of interest while video feed is coming in?
aj [February 14th, 2012, 04:37]
In case that video is allready playing, what should i do to inicialize this correcly? Currently it will only work if i click play/pause…
thanks
john [March 13th, 2012, 23:10]
How would one stop the video and start it again at the beginning?
I don’t want to pause where it is, I want to reset the position to the beginning.
Jason Browr [March 30th, 2012, 07:46]
hello,
This solution doesn’t work with Firefox 11 but with Chrome, it works ;)
help me please –‘
my code source :
play.addEventListener(‘click’,playControl,false);
var video = document.getElementById(‘videohead’);
function playControl() {
if (video.paused == false) {
video.pause();
document.getElementById(‘playpause’).src =’./images/play.png’;
document.getElementById(‘li_playpause’).title = ‘Play’;
}
else {
video.play();
document.getElementById(‘playpause’).src=’./images/pause.png’;
document.getElementById(‘li_playpause’).title = ‘Pause’;
}
}
rem [April 17th, 2012, 10:53]
Actually i’m facing a bit of problem in this i don’t really know whats causing this error..
Kiefer [April 30th, 2012, 15:24]
I have been asked to create a branded video player for a UofT childrens animated book. I was given a mock up with a play/stop button, a mute button and a volume contols (all would be images in a cartoon-esque theme.
How do I bind these buttons with the players functionality? Is there an example of this somewhere?
Thanks,
Luis
Luis DP [May 14th, 2012, 19:20]
very good job peter i am trying to create a video player that i can watch live video and mark points of interest.can i make a video player which fulfill this
zavera [June 25th, 2012, 02:00]
@REM, It seems that firefox requires the properties to be called as a function for the video element. So basically
if (video.paused == false)
needs to beif (video.paused() == false)
but subsequently, this breaks Chrome/Safari (most likely in the rendering engine Webkit).Jacob [July 19th, 2012, 22:48]