The <video> and <audio> elements have methods, properties/attributes and events that can be manipulated with JavaScript. Using the DOM API, it's possible to manipulate an audio or video element as a JavaScript object that has:
Methods for controlling the behavior, such as play(), pause(), etc.
Properties (duration, current position, etc.), either in read/write mode (such as volume), or in read-only mode (such as encoding, duration, etc.)
Events generated during the life cycle of the element that can be processed using JavaScript callbacks. It is also possible to send events to control the video player
The set of properties/attributes/methods of the <audio> and <video> elements is called an "API" (Application Programming Interface). For example, we will speak here of the "media API" to talk about the associated API.
Like any HTML element, the <video> element can be manipulated/created using the DOM JavaScript API. Here is an example of programmatically creating a <video> element:
var video = document.createElement('video');
video.src = 'video.mp4';
video.controls = true;
document.body.appendChild(video);
This will create a complete video player for the file "video.mp4", with control buttons, and will add it to the <body> element of the page.
Please look at this interesting example (click on "Edit on CodePen" and get a wider view of the "Result"):
HTML:
<html lang='en'>
<head>
<title>HTML5 Video (by PLH from a 2010 talk: https://www.w3.org/2010/Talks/0430-www2010-plh/video.html)</title>
</head>
<body>
<div class="slide" style="display: block; visibility: visible; position: absolute; border-style: none;">
<h1>HTML5 <video></h1>
<pre><video src='myMovie' id='myVideoElement' />
var vid = document.getElementById("myVideoElement");
<span id='play' onclick="playVideo();" style='cursor: pointer; color: #999;'>vid.play();</span>
<span id='pause' onclick="pauseVideo();" style='cursor: pointer; color: #999;'>vid.pause();</span>
<span id='rewind' onclick="rewindVideo();" style='cursor: pointer; color: black;'>vid.currentTime = 0;</span></pre>
<p style='text-align: left; position: absolute; width: 320px; height:240px; left: 30%; top: 55%; z-index: 2'>
This is a paragraph in HTML on top of the video.
</p>
<p style='text-align: left; position: absolute; width: 320px; height:240px; left: 30%; top: 70%; z-index: 0'>
CSS opacity allows this video to be partially transparent.
</p>
<video style='opacity: 0.5; position: absolute; top: 55%; left: 40%; width: 320px; height:240px; z-index: 1'
src='https://www.w3.org/2008/Talks/26-video-plh/small.ogg' width='360' height='240' id="vid">
<p>This video cannot be displayed.
<br /> No support for HTML5?</p>
</video>
</div>
</body>
</html>
CSS:
/* w3c-blue.css
Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
https://www.w3.org/Consortium/Legal/copyright-documents
https://www.w3.org/Consortium/Legal/copyright-software
*/
@media projection {
html {height: 100%}
}
body
{
margin: 0 0 0 0;
padding: 0 0 0 0;
height: 100%;
font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
font-size: 19px;
}
div.toolbar {
position: fixed; z-index: 200;
top: auto; bottom: 0; left: 0; right: 0;
height: 1.2em; text-align: right;
padding-left: 1em;
padding-right: 1em;
font-size: 60%;
color: red; background: rgb(240,240,240);
}
div.toolbar a { color: red; }
div.toolbar a:visited { color: red; }
div.toolbar a:link { color: red; }
div.toolbar a:active { color: red; }
body {
color: #eeeeff;
background-color: #3d64ac; }
div.slide {
text-shadow: black 1px 1px 1px;
filter: Shadow(Color=#000000, Direction=135, Strength=1);
}
pre {
border-color: #95ABD0;
text-shadow:none;
font-weight:normal;
font-family:Monaco
}
a:visited { color: #FF8 }
a:link { color: #FF8 }
a:hover { color: #FF8; text-decoration: underline }
a:active { color: #FF8; text-decoration: underline }
@media print {
body {
color: black;
background-color: white;
}
}
#head-logo, #head-logo-fallback {
position: absolute;
bottom: 40px;
right: 30px;
height: 84px;
width: 158px;
z-index: -1;
}
#stata-big {
position: absolute;
bottom: 00px;
left: 0px;
height: 231px;
width: 242px;
z-index: -1;
}
div.slide.cover.title a { color: yellow }
/* script sets position property to absolute or relative */
div.slide {
z-index: 20;
position: relative;
margin: 0 0 0 0;
padding: 0;
border-width: 0;
top: 0;
height: 100%;
width: 100%; /* for IE6 */
left: 0;
right: 0;
line-height: 1.2;
background: transparent;
overflow: auto; /* Avoid collapsing of margins outside the slide */
}
/* background div's are not positioned */
div.background {
z-index: 1;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-image: url(stata-small.jpg);
background-repeat: no-repeat;
background-position: left bottom;
}
/* this is a hack to hide property from IE6 and below */
div[class="footer"] { position: fixed }
div[class="background"] { position: fixed }
div.handout {
margin-left: 20px;
margin-right: 20px;
}
/* hide images used for save with content hack */
/* note this means we have to unhide the logo */
div.background img {
display: none;
visibility: hidden;
}
/* force page break before all but the first slide */
div.slide + div[class].slide { page-break-before: always;}
div.slide h1 a {color: #eeeeff; text-decoration: none}
div.slide h1 a:link {color: #eeeeff}
div.slide h1 a:visited {color: #eeeeff}
div.slide h1 a:active {color: red; text-decoration: underline}
div.slide h1 a:hover {color: yellow; text-decoration: underline}
div.slide h1 {
text-align: center;
padding-top: 1em;
padding-bottom: 1em;
font-size: 200%;
font-weight: normal;
}
div.slide.cover.title h1 {
font-size: 300%;
padding-top: 4em;
padding-bottom: 0;
}
div.slide.title h1 {
font-size: 300%;
padding-top: 4em;
padding-bottom: 0;
}
div.slide.title h1 {
color: #ef8645;
}
div.slide.cover.title h1 {
color: #eeeeff;
}
div.slide.cover p.author {
text-align: center;
color: #ef8645;
}
div.slide.cover p.event {
text-align: center;
}
div.slide.cover p.attribution {
position: absolute;
bottom: 1.5em;
left: 242px;
font-size: 50%;
color: black;
}
div.slide.cover p.attribution a {
color: #AAF;
}
div.slide.cover p.attribution img { vertical-align: bottom }
/* this is a hack to hide property from IE6 and below */
/* width set to below 100% to avoid horizontal scrollbar */
div[class="header"] {position: fixed; width: 98%}
div.header p.explanation {
font-style: italic;
}
#centered-photo
{
margin: 0;
margin-top: 7%;
padding: 0;
}
@media print {
body { color: black }
div.slide h1 { color: black }
div.cover div.header {
background: white; color: black;
border-width: thin;
border-style: solid;
border-bottom-width: thick;
border-bottom-color: #95ABD0;
}
div.cover div.header a { color: black }
div.cover div.header p {color: black }
div.cover { background: transparent }
#cover-photo
{
width: 100%;
height: auto;
margin: 0;
margin-top: 20%;
padding: 0;
}
h1, pre { font-size: 60% }
}
div.slide.cover a {
color: #eeeeff;
}
div.slide.cover a:hover, div.slide.cover a:active {
color: yellow; text-decoration: underline;
}
li pre { margin-left: 0; }
blockquote { font-style: italic }
img { background-color: transparent }
p.copyright { font-size: smaller }
.center { text-align: center }
.footnote { font-size: smaller; margin-left: 2em; }
a img { border-width: 0; border-style: none }
div.toc {color: black }
div.toc a:visited {color: black }
div.toc a:link {color: black }
div.toc a:hover {color: black }
div.toc a:active {color: black }
div.toc a {color: black }
div a.toc-heading {color: black}
div.toc a.titleslide { font-weight: bold; font-style: italic }
a {text-decoration: none}
.navbar a:link {color: #eeeeff}
.navbar a:visited {color: red}
.navbar a:active {color: red}
.navbar a:hover {color: red}
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
li { margin-left: 0.5em; margin-top: 0.5em; }
li li { font-size: 85%; font-style: italic }
li li li { font-size: 85%; font-style: normal }
div dt
{
margin-left: 0;
margin-top: 1em;
margin-bottom: 0.5em;
font-weight: bold;
}
div dd
{
margin-left: 2em;
margin-bottom: 0.5em;
}
p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
margin-left: 1em;
margin-right: 1em;
}
p.subhead { font-weight: bold; margin-top: 2em; }
.smaller { font-size: smaller }
.bigger { font-size: 130% }
td,th { padding: 0.2em }
ul {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ol {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
ul li {
list-style: none;
margin: 0.1em 0em 0.6em 0;
padding: 0 0 0 40px;
background: transparent url(bullet.gif) no-repeat 5px 8px;
line-height: 1.4;
}
/* workaround IE's failure to support background on li for print media */
@media print { ul li { list-style: disc; padding-left: 0; background: none; } }
ol > li {
margin: 0.1em 0em 0.6em 1.5em;
padding: 0 0 0 0px;
line-height: 1.4;
list-style-type: decimal;
background: transparent;
}
li ol li, ol li {
margin: 0.1em 0em 0.6em 1.5em;
padding: 0 0 0 0px;
list-style-type: decimal;
background: transparent;
}
li ul li {
font-size: 85%;
font-style: italic;
list-style-type: square;
background: transparent;
padding: 0 0 0 0;
}
li li ul li {
font-size: 85%;
font-style: normal;
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li li li ul li {
list-style-type: circle;
background: transparent;
padding: 0 0 0 0;
}
/*
setting class="outline on ol or ul makes it behave as an
ouline list where blocklevel content in li elements is
hidden by default and can be expanded or collapsed with
mouse click. Set class="expand" on li to override default
*/
ol.outline li:hover { cursor: pointer }
ol.outline li.nofold:hover { cursor: default }
ul.outline li:hover { cursor: pointer }
ul.outline li.nofold:hover { cursor: default }
ol.outline { list-style:decimal; }
ol.outline ol { list-style-type:lower-alpha }
ol.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(nofold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(fold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(unfold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(fold.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(unfold.gif) no-repeat 0px 0.5em;
}
ul.outline li.nofold {
padding: 0 0 0 52px;
background: transparent url(bullet-nofold-dim.gif) no-repeat 5px 8px;
}
ul.outline li.unfolded {
padding: 0 0 0 52px;
background: transparent url(bullet-fold-dim.gif) no-repeat 5px 8px;
}
ul.outline li.folded {
padding: 0 0 0 52px;
background: transparent url(bullet-unfold-dim.gif) no-repeat 5px 8px;
}
ul.outline li.unfolded:hover {
padding: 0 0 0 52px;
background: transparent url(bullet-fold.gif) no-repeat 5px 8px;
}
ul.outline li.folded:hover {
padding: 0 0 0 52px;
background: transparent url(bullet-unfold.gif) no-repeat 5px 8px;
}
li ul.outline li.nofold {
padding: 0 0 0 21px;
background: transparent url(nofold-dim.gif) no-repeat 5px 8px;
}
li ul.outline li.unfolded {
padding: 0 0 0 21px;
background: transparent url(fold-dim.gif) no-repeat 5px 8px;
}
li ul.outline li.folded {
padding: 0 0 0 21px;
background: transparent url(unfold-dim.gif) no-repeat 5px 8px;
}
li ul.outline li.unfolded:hover {
padding: 0 0 0 21px;
background: transparent url(fold.gif) no-repeat 5px 8px;
}
li ul.outline li.folded:hover {
padding: 0 0 0 21px;
background: transparent url(unfold.gif) no-repeat 5px 8px;
}
img.withBorder {
border: 2px solid #c60;
padding: 4px;
}
pre {
font-size: 80%;
font-weight: bold;
line-height: 1.2;
padding-top: 0.2em;
padding-bottom: 0.2em;
padding-left: 1em;
padding-right: 1em;
border-style: solid;
border-left-width: 1em;
border-top-width: thin;
border-right-width: thin;
border-bottom-width: thin;
}
li pre { margin-left: 0; }
/* for Bert as an ardent user of the old W3C slidemaker tool */
div.comment { display: none; visibility: hidden }
@media print { div.comment { display: block; visibility: visible } }
div.slide.clip {
overflow: hidden;
}
JavaScript:
let vid = null;
let play = null;
let pause = null;
let rewind = null;
window.onload = init;
function init() {
vid = document.getElementById("vid");
play = document.getElementById("play");
pause = document.getElementById("pause");
rewind = document.getElementById("rewind");
}
function playVideo() {
vid.play();
play.style.color='black';
pause.style.color='#999';
rewind.style.color='#999';
}
function pauseVideo() {
vid.pause();
play.style.color='#999';
pause.style.color='black';
rewind.style.color='#999';
}
function rewindVideo() {
vid.currentTime = 0;
play.style.color='#999';
pause.style.color='#999';
rewind.style.color='black';
}
Note that in order to play the video, you must click on the "vid.play()" text. To pause it, you click on the "vid.pause()" text, and so on. Notice the text at the top of the video, as well as the transparency. The text can be selected, since all the elements displayed are pure DOM objects. You can zoom the page in and out, etc. This was not possible with the Flash technology.
Conclusion: you can very easily change the look and feel of the standard video player by using custom CSS and designing your own control widgets. We can find many examples of such video players that offer extended functionalities on the Web. We will present some of them later in the course, but before that, let's see a little more of what we can do using the JavaScript API of the <video> element (it will be an identical approach for the <audio> element, since it shares the same API by a very small margin).