Vous êtes sur la page 1sur 72

Safari HTML5 Audio and

Video Guide

Contents

About HTML5 Audio and Video 6


At a Glance 7
Create the HTML5 Media Elements 7
Take Control Using JavaScript 9
Set the Style with CSS3 10
Prerequisites 10
See Also 10

Audio and Video HTML 11


Basic Syntax 11
Working with Attributes 13
Resizing the Video 13
Enabling the Controller 13
Preloading 13
Showing a Poster 14
Providing Multiple Sources 14
Specifying Multiple Media Formats 15
Specifying Multiple Delivery Schemes 16
Multiple Data Rate Sources 17
Specifying Fallback Behavior 17
Fall Back to the QuickTime Plug-in 18
Fall Back to Any Plug-In 19

iOS-Specific Considerations 21
Optimization for Small Screens 21
User Control of Downloads Over Cellular Networks 21
Default Height and Width on iOS 22
iPhone Video Placeholder 22
Media Playback Controls 22
Supported Media 22
Multiple Simultaneous Audio or Video Streams 23
Volume Control in JavaScript 23
Playback Rate in JavaScript 23
Loop Attribute 24

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

Contents

Playing Sounds with the Web Audio API 25


Setting Up the Audio Context 25
Fetching and Buffering Sounds 26
Synthesizing Sounds 27
Playing Sounds 28
Routing and Mixing Sounds 29
Exploring More Possibilites 30

Controlling Media with JavaScript 37


A Simple JavaScript Media Controller and Resizer 37
Using DOM Events to Monitor Load Progress 39
Replacing a Media Source Sequentially 41
Syncing Multiple Media Elements Together 42
Using JavaScript to Provide Fallback Content 43
Handling Playback Failure 45
Resizing Movies to Native Size 47
Taking Video Full Screen 48
Taking Your Custom Controls Full Screen 49
Full-Screen Event and Properties 50
Resizing Enclosed Video 50
Full-Screen Video with Custom Controls Example 51

Adding CSS Styles 53


Changing Styles in Response to Media Events 54
Adding CSS Styles to Video 57
Example: Setting Opacity 58
Using WebKit Properties 58

Document Revision History 71

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

Figures, Tables, and Listings

Audio and Video HTML 11


Table 1-1
Listing 1-1
Listing 1-2
Listing 1-3
Listing 1-4
Listing 1-5
Listing 1-6
Listing 1-7

Attributes of the <audio> and <video> elements 11


Creating a simple movie player 12
Showing a poster 14
Specifying multiple audio sources 15
Specifying multiple delivery schemes 16
Adding simple fallback behavior 17
Falling back to the QuickTime plug-in 18
Falling back to a plug-in for IE 19

iOS-Specific Considerations 21
Figure 2-1
Listing 2-1

The iPhone video placeholder 22


Backward-compatible looping audio 24

Playing Sounds with the Web Audio API 25


Figure 3-1
Table 3-1
Listing 3-1

A simple synthesizer and audio spectrum visualizer 31


Types of periodic waveforms 27
A simple synthesizer and audio spectrum visualizer 31

Controlling Media with JavaScript 37


Listing 4-1
Listing 4-2
Listing 4-3
Listing 4-4
Listing 4-5
Listing 4-6
Listing 4-7
Listing 4-8
Listing 4-9

Adding simple JavaScript controls 38


Installing DOM event listeners 39
Summing a TimeRanges object 41
Replacing media sequentially 41
Testing for playability using JavaScript 44
Testing for failure using JavaScript 45
Resizing movies programmatically 47
Using webkitEnterFullscreen() 48
Full-screen video with custom controls 51

Adding CSS Styles 53


Figure 5-1
Figure 5-2
Figure 5-3

Page with movie paused 54


Page with movie playing 55
CSS filters on a video 59

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

Figures, Tables, and Listings

Figure 5-4
Figure 5-5
Figure 5-6
Figure 5-7
Listing 5-1
Listing 5-2
Listing 5-3

Reflection with mask image 65


Mask image 65
Reflection with gradient mask and color stop 67
Video in mid-rotation 70
Dim the lights 55
Applying CSS filters to HTML elements 60
3D rotation with perspective 68

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

About HTML5 Audio and Video

If you embed audio or video in your website, you should use HTML5.
HTML5 is the next major version of HTML, the primary standard that determines how web content interacts
with browsers. HTML5 supports audio and video playback natively in the browser, without requiring a plug-in.
With HTML5, you can add media to a webpage with just a line or two of code.
The HTML5 media elements provide simple fallback for browsers that still need to use plug-ins, so you can
update your website to HTML5 today and still be compatible with older browsers.
When you use HTML5, you can create your own customized media controllers for rich interactivity using
web-standard CSS and JavaScript.
The HTML5 <audio> and <video> tags make it simple to add media to your website. Just include the <audio>
or <video> element, use the src attribute to identify the media source, and include the controls attribute.
<video src="mymovie.mp4" controls></video>

There are no plug-ins to install or configure. The audio or video downloads and plays in your webpage with
built-in controls.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

About HTML5 Audio and Video


At a Glance

In Safari, the built-in video controls include a play/pause button, volume control, and a time scrubber. In Safari
5.0 and later on the desktop and on iOS 4.2 on the iPad, the controls also include a full-screen playback toggle
on the lower right. The controls automatically fade out when the video is playing and fade in when the user
hovers over the video or touches it.
If you want to provide your own media controller on the desktop or iPad, just leave out the controls attribute.
HTML5 media elements expose a full set of methods, properties, and events to JavaScript for interactivity, and
because the media elements are HTML, they can be styled using CSS to create exactly the look and feel you
want.
In Safari 5.1 and later, you can choose any HTML element and expand it to fill the screen, allowing you to use
your own custom controls while playing video in full-screen mode.

At a Glance
Safari supports the <video> and <audio> media elements on iOS 3.0 and later and in Safari 3.1 and later on
the desktop (Mac OS X and Windows). Support for these media elements allows Safari and other
HTML5-compliant browsers to play the indicated source media without using a plug-in.
To get the most out of HTML5 audio and video, you should first learn to create the HTML media elements,
then learn how to control them using JavaScript, and finally learn to apply CSS styles to media elements and
modify styles dynamically using JavaScript.

Create the HTML5 Media Elements


Relevant Chapter: Audio and Video HTML (page 11)

To use HTML5 audio or video, start by creating an <audio> or <video> element, specifying a source URL for
the media, and including the controls attribute.
<video src="http://example.com/path/mymovie.mp4" controls></video>

Add Optional Attributes


You can set additional attributes to tell Safari that the media should autoplay or loop, for example, or specify
a video height and width. You set boolean attributes such as controls or autoplay by including or omitting
themno value is required.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

About HTML5 Audio and Video


At a Glance

<video src="mymovie.mp4"
controls autoplay height="480" width="640">
</video>

For more information, see Working with Attributes (page 13).

Provide Alternate Sources


Not all browsers can play all media sources. Some browsers are able to play MPEG-4 or MP3 files, while others
play only files compressed using codecs such as Ogg Vorbis. Desktop computers can typically play media using
a wider assortment of compressors than mobile devices. Safari supports streaming delivery using HTTP Live
Streaming, while some other browsers support only HTTP download. To provide the best experience for
everyone, you can provide multiple versions of your media. List the sources in order of preference using separate
<source> tags. The browser iterates through the list and plays the first source that it can.
<audio controls>
<source src="http://example.com/mysong.aac">
<source src="mysong.oga">
</audio>

You dont have to rely on the file extension and delivery scheme to tell Safari about the media file. The <source>
tag accepts attributes for MIME type and codecs as well. For details, see Providing Multiple Sources (page
14).

Fall Back in Good Order


Browsers that dont support HTML5 ignore the <audio> and <video> tags, and HTML5-savvy browsers ignore
anything between the opening and closing tags except <source> tags, so its easy to specify fallback behavior
for older browsers. Just put the fallback HTML between the opening and closing <audio> or <video> tags
(after any <source> tags).
<video src="mymovie.mov" controls>
<!-- fallback -->
<p>Your browser does not support HTML5 video.</p>
</video>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

About HTML5 Audio and Video


At a Glance

Your fallback can be an <object> tag for a browser that needs a plug-in to play your media, a redirect to
another page, or a simple error message telling the user what the problem is.
For more information, including examples of how to use a plug-in as a fallback, see Specifying Fallback
Behavior (page 17).

Take Control Using JavaScript


Relevant Chapter: Controlling Media with JavaScript (page 37)

HTML5 media elements expose methods, properties, and events to JavaScript. There are methods for playing,
pausing, and changing the media source URL dynamically. There are propertiessuch as duration, volume,
and playback ratethat you can read or set (some properties are read-only). In addition, there are DOM events
that notify you, for example, when a media element is able to play through, begins to play, is paused by the
user, or completes.
For a complete list of methods, properties, and events that Safari supports, see HTMLMediaElement Class
Reference , HTMLVideoElement Class Reference , and HTMLAudioElement Class Reference .
You can use JavaScript with HTML5 media elements to:

Create your own interactive audio or video controllerfor an example, see A Simple JavaScript Media
Controller and Resizer (page 37).

Display a progress indicator that shows how much of the media has downloadedfor an example, see
Using DOM Events to Monitor Load Progress (page 39).

Load another audio or video when the current one finishes playingfor an example, see Replacing a
Media Source Sequentially (page 41).

Slave multiple audio and/or video elements to a master controller to ensure your media elements are
always synchronizedfor an example, see Syncing Multiple Media Elements Together (page 42).

Test whether Safari can play the specified media type or filefor examples, see Using JavaScript to Provide
Fallback Content (page 43) and Handling Playback Failure (page 45).

Enter full-screen video modefor examples, see Taking Video Full Screen (page 48) and Taking Your
Custom Controls Full Screen (page 49).

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

About HTML5 Audio and Video


Prerequisites

Set the Style with CSS3


Relevant Chapter: Adding CSS Styles (page 53)

Because the <audio> and <video> elements are standard HTML, you can customize them using CSSset
the background color, control opacity, add a reflection, move the element smoothly across the screen, or even
rotate it in 3D. You can combine CSS with JavaScript to change media properties dynamically, in response to
user input or movie events.
You can also change the CSS properties of other parts of your webpage in response to media events. For
example, you could darken the background and reduce the opacity of the rest of the pageeffectively dimming
the lightswhen a movie is playing, or highlight the title of the currently-playing song in a playlist.
For more information, see Changing Styles in Response to Media Events (page 54) and Adding CSS Styles
to Video (page 57).
For code examples, see Example: Setting Opacity (page 58), Adding a Mask (page 60), Adding a
Reflection (page 62), and Rotating Video in 3D (page 67).

Prerequisites
You should be familiar with HTML and JavaScript. Familiarity with CSS is helpful. To create image masks, you
should be able to work with transparency (alpha channels).

See Also

Safari DOM Additions Reference DOM events, JavaScript functions and properties added to Safari to
support HTML5 audio and video, touch events, and CSS transforms and transitions.

Safari CSS Visual Effects Guide How to use CSS transitions and effects in Safari.

Safari CSS Reference Complete list of CSS properties, rules, and property functions supported in Safari,
with syntax and usage.

Safari HTML Reference The HTML elements and attributes supported by different Safari and WebKit
applications.

WebKit DOM Programming Topics How to get the most out of using DOM events in Safari.

iOS Human Interface Guidelines User interface guidelines for designing webpages and web applications
for Safari on iOS.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

10

Audio and Video HTML

In their simplest form, the <audio> and <video> tags require only a src attribute to identify the media,
although you generally want to set the controls attribute as well. Safari allocates space, provides a default
controller, loads the media, and plays it when the user clicks the play button. Its all automatic.
There are optional attributes as well, such as autoplay, loop, height, and width.

Basic Syntax
The attributes for the <audio> and <video> tags are summarized in Table 1-1 (page 11). The only difference
between the <audio> and <video> tag attributes is the option to specify a height, width, and poster image
for video.
Table 1-1

Attributes of the <audio> and <video> elements

Attribute

Value

Description

preload

none | metadata |
auto

noneSafari should not preload media data.

This attribute was


formerly named
autobuffer, and was
boolean.

metadataSafari should preload only media

metadata.
automaticSafari should preload all media

data.

autoplay

Booleanany value sets


this to true

If present, asks the browser to play the media


automatically.

controls

Booleanany value sets


this to true

If present, causes the browser to display the


default media controls.

height (video only)

pixels

The height of the video player.

loop

Booleanany value sets


this to true

If present, causes the media to loop indefinitely.


This attribute is supported in iOS 5.0 and later.

poster (video only)

url of image file

If present, shows the poster image until the first


frame of video has downloaded.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

11

Audio and Video HTML


Basic Syntax

Attribute

Value

Description

src

url

The URL of the media.

width (video only)

pixels

The width of the video player.

Important: Several of the attributes are boolean. No value is required. Set the attribute true by including
it; set it false by omitting it. Although boolean attributes can be set to false using JavaScript, any value
in the HTML tag sets them to true. Controls="controls", for example, is the same as controls=true
or simply controls. Even controls=false sets controls to true in HTML.
The preload attribute is a hint to the browser, telling it your preferences. There is no guarantee that you will
get the behavior that you prefer. Safari does not support all preferences on all devices, and does not currently
support the Metadata preference on any device. For more information, see iOS-Specific Considerations (page
21).
Listing 1-1 shows an HTML page that autoplays a video at a specified height and width with the built-in user
controls.
Listing 1-1

Creating a simple movie player

<!doctype html>
<html>
<head>
<title>Simple Movie Player</title>
</head>
<body>
<video src="http://example.com/path/mymovie.mov"
controls
autoplay
height="270" width="480">
</video>
</body>
</html>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

12

Audio and Video HTML


Working with Attributes

Working with Attributes


There are several ways you can control media playback directly in HTML by setting attributes appropriately.

Resizing the Video


In Safari on iOS, the native size of the video is unknown until the user initiates a download. If no height or
width is specified, a default size of 150 x 300 pixels is allocated in the webpage. On iPad, the video currently
plays in this default space. On iPhone or iPod touch, the video plays in fullscreen mode once the user initiates
it, and the default space is allocated to a placeholder on the webpage.
In Safari on the desktop, the movie metadata is downloaded automatically whenever possible, so the native
video size is used as the default. If only the height or width parameter is specified, the video is scaled up or
down to that height or width while maintaining the native aspect ratio of the movie. If both height and width
are specified, the video is presented at that size. If neither is specified, the video is displayed at its native size.

Enabling the Controller


In Safari, the default video controller is slightly translucent and is overlaid on the bottom of the video. The
controller is not normally visible when the movie is playingit appears only when the movie is paused, when
the user touches the video, or when the mouse pointer hovers over the playing movie. In cases where it is
crucial that the bottom of the video never be obscured, omit the controls attribute. (You cannot set the
attribute to false explicitly in HTMLyou set it to false implicitly by leaving the attribute out.)
If you do not set the controls attribute, you must either set the autoplay attribute, create a controller using
JavaScript, or play the movie programmatically from JavaScript. Otherwise the user has no way to play the
movie.
Warning: To prevent unsolicited downloads over cellular networks at the users expense, embedded
media cannot be played automatically in Safari on iOSthe user always initiates playback. A controller
is automatically supplied on iPhone or iPod touch once playback in initiated, but for iPad you must
either set the controls attribute or provide a controller using JavaScript.

Preloading
If you set the preload attribute to auto, it tells Safari you want the specified media file to start buffering
immediately, making it more likely that it will begin promptly and play through smoothly when the user plays
it.
If you have multiple movies on the page, you should set the preload attribute to none, to prevent all the
movies from downloading at once.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

13

Audio and Video HTML


Providing Multiple Sources

Safari does not currently support the metadata setting.


Note: The preload attribute is supported in Safari 5.0 and later. Safari on iOS never preloads.

Showing a Poster
Setting a poster image normally has a transitory effectthe poster image is shown only until the first frame
of the video is available, which is typically a second or two. On iOS, however, the first frame is not shown until
the user initiates playback, and a poster image is recommended, as shown in Listing 1-2.
Listing 1-2

Showing a poster

<!doctype html>
<html>
<head>
<title>Movie Player with Poster</title>
</head>
<body>
<video src="http://example.com/path/mymovie.mov"
controls
height=340 width=640
poster="http://example.com/path/poster.jpg">
</video>
</body>
</html>

Providing Multiple Sources


Not all types of audio and video can play on all devices and browsers. Fortunately, the <audio> and <video>
elements allow you to list as many <source> elements as you like. The browser iterates through them until
it finds one it can play or runs out of sources. Instead of using the src attribute in the media element itself,
follow the <audio> or <video> tag with one or more <source> elements, prior to the closing tag.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

14

Audio and Video HTML


Providing Multiple Sources

Specifying Multiple Media Formats


List the alternate media sources in the order of most desirable to least desirable. The browser chooses the first
listed source that it thinks it can play. For example, if you have an AAC audio file, an Ogg Vorbis audio file, and
a WAVE audio file, listed in that order, Safari plays the AAC file. A browser that cannot play AAC but can play
Ogg plays the Ogg file. A browser that can play neither Ogg nor AAC might still be able to play the WAVE file.
Listing 1-3 is a simple example of using multiple sources for an audio file.
Listing 1-3

Specifying multiple audio sources

<!doctype html>
<html>
<head>
<title>Multi-Source Audio Player</title>
</head>
<body>
<audio controls autoplay >
<source src="http://example.com/path/MyAudio.m4a">
<source src="http://example.com/path/MyAudio.oga">
<source src="http://example.com/path/MyAudio.wav">
</audio>
</body>
</html>

The <source> element can have a type attribute, specifying the MIME type, to help the browser decide
whether or not it can play the media without having to load the file.
<audio controls>
<source src="mySong.aac" type="audio/mp4">
<source src="mySong.oga" type="audio/ogg">
</audio>

The type attribute can take an additional codecs parameter, to specify exactly which versions of which codecs
are needed to play this particular media.
<audio controls>
<source src="mySongComplex.aac" type="audio/mp4; codecs=mp4a.40.5">

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

15

Audio and Video HTML


Providing Multiple Sources

<source src="mySongSimple.aac" type="audio/mp4; codecs=mp4a.40.2">


</audio>

Notice that you dont have to know which browsers support what formats, and then sniff the user agent string
for the browser name to decide what to do. Just list your available media, preferred format first, second choice
next, and so on. The browser plays the first one it can.
Currently, most browsers support low-complexity AAC and MP3 audio and basic profile MPEG-4. Most browsers
that do not support these formats support Theora video and Vorbis audio using the Ogg file format. Generally
speaking, if you provide media in MPEG-4 (basic profile) and Ogg formats, your media can play in browsers
that support HTML5.
Note: Safari on iOS supports low-complexity AAC audio, MP3 audio, AIF audio, WAVE audio, and
baseline profile MPEG-4 video. Safari on the desktop (Mac OS X and Windows) supports all media
supported by the installed version of QuickTime, including any installed third-party codecs.

Specifying Multiple Delivery Schemes


You can also use multiple source elements to specify different delivery schemes. Lets say you have a large
real-time video streaming service that uses RTSP streaming, and you want to add support for Safari on iOS,
including iPad, using HTTP Live Streaming, along with a progressive download for browsers that cant handle
either kind of streaming. As shown in Listing 1-4, with HTML5 video its quite straightforward.
Listing 1-4

Specifying multiple delivery schemes

<!doctype html>
<html>
<head>
<title>Multi-Scheme Video Player</title>
</head>
<body>
<video controls autoplay >
<source src="http://HttpLiveStream.m3u8">
<source src="rtsp://LegacyStream.3gp">
<source src="http://ProgressiveDownload.m4v">
</video>
</body>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

16

Audio and Video HTML


Specifying Fallback Behavior

</html>

Again, the browser picks the first source it can handle. Safari on the desktop plays the RTSP stream, while Safari
on iOS plays the HTTP Live stream. Browsers that support neither m3u8 playlists nor RTSP URLs play the
progressive download version.

Multiple Data Rate Sources


HTML5 does not support selection from multiple sources based on data rate. If you supply multiple sources,
the browser chooses the first it can play based on scheme, file format, profile, and codecs. Bandwidth is not
tested. To provide multiple bandwidths, you must provide a src attribute that specifies a source capable of
supporting data rate selection itself.
For example, if one of your sources is an HTTP Live Stream, the playlist file can specify multiple streams, and
Safari selects the best stream for the current bandwidth dynamically as network bandwidth changes. For more
information, see HTTP Live Streaming Overview .
Similarly, if the source is a QuickTime reference movie, it can include alternate sources at different data rates,
and Safari chooses the best source for the current bandwidth when the video is first requested (though it does
not dynamically switch between sources if available bandwidth subsequently changes). For more information,
see Technical Note TN2266 "Creating Reference MoviesMakeRefMovie"

Specifying Fallback Behavior


Its easy to specify fallback behavior for browsers that dont support the <audio> or <video> elementsjust
put the fallback content between the opening and closing media tags, after any <source> elements. See
Listing 1-5.
Listing 1-5

Adding simple fallback behavior

<!DOCTYPE html>
<html>
<head>
<title>Simple Movie Player with Trivial Fallback Behavior</title>
</head>
<body>
<!-- opening tag -->
<video src="mymovie.mov" controls>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

17

Audio and Video HTML


Specifying Fallback Behavior

<!-- fallback content -->


Your browser does not support the video element.

<!-- closing tag -->


</video>
</body>
</html>

Browsers that dont support the <audio> or <video> tags simply ignore them. Browsers that support these
elements ignore all content between the opening and closing tags (except <source> tags).
Note: Browsers that understand the <audio> and <video> tags do not display fallback content,
even if they cannot play any of the specified media. To provide fallback content in case no specified
media is playable, see Using JavaScript to Provide Fallback Content (page 43).

Fall Back to the QuickTime Plug-in


There is a simple way to fall back to the QuickTime plug-in that works for nearly all browsersdownload the
prebuilt JavaScript file provided by Apple, ac_quicktime.js, from HTML Video Example and include it in
your webpage by inserting the following line of code into your HTML head:
<script src="ac_quicktime.js" type="text/javascript"></script>

Once youve included the script, add a call to QT_WriteOBJECT() between the opening and closing tags of
the <audio> or <video> element, passing in the URL of the movie, its height and width, and the version of
the ActiveX control for Internet Explorer (just leave this parameter blank to use the current version). See Listing
1-6 for an example.
Listing 1-6

Falling back to the QuickTime plug-in

<!doctype html>
<html>
<head>
<title>Simple Movie Player with QuickTime Fallback</title>
<script src="ac_quicktime.js" type="text/javascript"></script>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

18

Audio and Video HTML


Specifying Fallback Behavior

</head>
<body>
<video controls>
<source src="myMovie.mov" type="video/quicktime">
<source src="myMovie.3gp" type="video/3gpp">
<!-- fallback -->
<script type="text/javascript">
QT_WriteOBJECT('myMovie.mov' , '320', '240', '');
</script>
</video>
</body>
</html>

You can pass more than twenty additional parameters to the QuickTime plug-in. For more about how to work
with the QuickTime plug-in and the ac_quicktime.js script, see HTML Scripting Guide for QuickTime .

Fall Back to Any Plug-In


Since most browsers now support the <audio> and <video> elements, you can simplify the process of coding
for plug-ins by including only the version of the <object> tag that works with Internet Explorer as your fallback
for HTML5 media.
Listing 1-7 uses HTTP Live Streaming for browsers that support it, MPEG-4 and Ogg Vorbis by progressive
download for browsers that support those formats, and falls back to a plug-in for versions of Internet Explorer
that dont support HTML5.
Listing 1-7

Falling back to a plug-in for IE

<!doctype html>
<html>
<head>
<title>Simple Movie Player with Plug-In Fallback</title>
</head>
<body>
<video controls>
<source src="HttpLiveStream.m3u8" type="vnd.apple.mpegURL">
<source src="ProgressiveDowload.mp4" type="video/mp4">

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

19

Audio and Video HTML


Specifying Fallback Behavior

<source src="OggVorbis.ogv" type="video/ogg">


<!-- fallback -->
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab"
height="320"
width="240">
<param name="src" value="ProgressiveDownload.mp4">
</object>
</video>
</body>
</html>

Listing 1-7 uses the QuickTime plug-in. To use a different plug-in, change the CLASSID and CODEBASE
parameters to those of your preferred plug-in and provide the PARAM tags the plug-in requires.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

20

iOS-Specific Considerations

There are a handful of device-specific considerations you should be aware of when embedding audio and
video using HTML5.

Optimization for Small Screens


Currently, Safari optimizes video presentation for the smaller screen on iPhone or iPod touch by playing video
using the full screenvideo controls appear when the screen is touched, and the video is scaled to fit the
screen in portrait or landscape mode. Video is not presented within the webpage. The height and width
attributes affect only the space allotted on the webpage, and the controls attribute is ignored. This is true
only for Safari on devices with small screens. On Mac OS X, Windows, and iPad, Safari plays video inline,
embedded in the webpage.
Note: Prior to iOS 4.0, iPhone and iPod touch did not play audio inline. Audio was presented in
full-screen mode. Audio plays inline on iOS 4.0 and later, on all devices.

User Control of Downloads Over Cellular Networks


In Safari on iOS (for all devices, including iPad), where the user may be on a cellular network and be charged
per data unit, preload and autoplay are disabled. No data is loaded until the user initiates it. This means the
JavaScript play() and load() methods are also inactive until the user initiates playback, unless the play()
or load() method is triggered by user action. In other words, a user-initiated Play button works, but an
onLoad="play()" event does not.
This plays the movie: <input type="button" value="Play" onclick="document.myMovie.play()">
This does nothing on iOS: <body onload="document.myMovie.play()">

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

21

iOS-Specific Considerations
Default Height and Width on iOS

Default Height and Width on iOS


Because the native dimensions of a video are not known until the movie metadata loads, a default height and
width of 150 x 300 is allocated on devices running iOS if the height or width is not specified. Currently, the
default height and width do not change when the movie loads, so you should specify the preferred height
and width for the best user experience on iOS, especially on iPad, where the video plays in the allocated space.

iPhone Video Placeholder


On iPhone and iPod touch, a placeholder with a play button is shown until the user initiates playback, as shown
in Figure 2-1. The placeholder is translucent, so the background or any poster image shows through. The
placeholder provides a way for the user to play the media. If the iOS device cannot play the specified media,
there is a diagonal bar through the control, indicating that it cannot play.
Figure 2-1

The iPhone video placeholder

On the desktop and iPad, the first frame of a video displays as soon as it becomes available. There is no
placeholder.

Media Playback Controls


Controls are always supplied during fullscreen playback on iPhone and iPod touch, and the placeholder allows
the user to initiate fullscreen playback. On the desktop or iPad, you must either include the controls attribute
or provide playback controls using JavaScript. It is especially important to provide user controls on iPad because
autoplay is disabled to prevent unsolicited cellular download.

Supported Media
Safari on the desktop supports any media the installed version of QuickTime can play. This includes media
encoded using codecs QuickTime does not natively support, provided the codecs are installed on the users
computer as QuickTime codec components.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

22

iOS-Specific Considerations
Multiple Simultaneous Audio or Video Streams

Safari on iOS (including iPad) currently supports uncompressed WAV and AIF audio, MP3 audio, and AAC-LC
or HE-AAC audio. HE-AAC is the preferred format.
Safari on iOS (including iPad) currently supports MPEG-4 video (Baseline profile) and QuickTime movies encoded
with H.264 video (Baseline profile) and one of the supported audio types.
iPad and iPhone 3G and later support H.264 Baseline profile 3.1. Earlier versions of iPhone support H.264
Baseline profile 3.0.

Multiple Simultaneous Audio or Video Streams


Currently, all devices running iOS are limited to playback of a single audio or video stream at any time. Playing
more than one videoside by side, partly overlapping, or completely overlaidis not currently supported on
iOS devices. Playing multiple simultaneous audio streams is also not supported. You can change the audio or
video source dynamically, however. See Replacing a Media Source Sequentially (page 41) for details.

Volume Control in JavaScript


On the desktop, you can set and read the volume property of an <audio> or <video> element. This allows
you to set the elements audio volume relative to the computers current volume setting. A value of 1 plays
sound at the normal level. A value of 0 silences the audio. Values between 0 and 1 attenuate the audio.
This volume adjustment can be useful, because it allows the user to mute a game, for example, while still
listening to music on the computer.
On iOS devices, the audio level is always under the users physical control. The volume property is not settable
in JavaScript. Reading the volume property always returns 1.

Playback Rate in JavaScript


You can set the audio or video playbackRate property to nonzero values to play media in slow motion (values
>0 and <1) or fast forward (values >1) in Safari on the desktop. Setting playbackRate is not currently supported
on iOS.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

23

iOS-Specific Considerations
Loop Attribute

Loop Attribute
You can set the audio or video loop attribute in Safari on the desktop and on iOS 5.0 and later to cause media
to repeat endlessly. To loop audio or video in a manner compatible with earlier versions of iOS, use JavaScript
to install the play() method as an event listener for the "ended" event. This technique is illustrated in Listing
2-1.
Listing 2-1

Backward-compatible looping audio

<!doctype html>
<html>
<head>
<title>Looping Audio</title>
<script type="text/javascript">
function init() {
var myAudio = document.getElementById("audio");
myAudio.addEventListener('ended', loopAudio, false);
}
function loopAudio() {
var myAudio = document.getElementById("audio");
myAudio.play();
}
</script>
</head>
<body onload="init();">
<audio id="audio" src="myAudio.m4a" controls></audio>
</body>
</html>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

24

Playing Sounds with the Web Audio API

Note: The Web Audio API is available on Safari 6 and later, and Safari on iOS 6 and later.

In Audio and Video HTML (page 11), you learned how to stream audio using the <audio> HTML5 element.
While the <audio> tag is suitable for basic needs such as streaming and media playback, another option called
the Web Audio API offers a more comprehensive audio-based toolkit. The Web Audio API is a JavaScript interface
that features the ability to:

Play a sound at a precise moment in time.

Synthesize aural tones and oscillations.

Mix sound effects with filters.

Access the raw bits of audio data.

Some use cases of the Web Audio API include supplementing HTML5 games with sound effects, controlling
DJ-style music players, and visualizing music in new, innovative ways. Harness the power of the Web Audio
API to create new web experiences that are augmented with sound.
In this chapter youll learn how to start using the Web Audio API in your web apps.
Note: Details of specific class references can be found at the W3C Web Audio API specification.

Setting Up the Audio Context


Before you can play any sounds, you must first create an audio context from which the sound can play. Similar
to how HTML5 canvas requires a context on which lines and curves are drawn, Web Audio requires an audio
context on which sounds are played and manipulated. This context will be the parent object of further audio
objects to come.
if('webkitAudioContext' in window) {
var myAudioContext = new webkitAudioContext();
}

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

25

Playing Sounds with the Web Audio API


Fetching and Buffering Sounds

Your audio context is typically created when your page initializes and should be long-lived. You can play
multiple sounds coming from multiple sources within the same context, so it is unnecessary to create more
than one audio context per page.
Note: In Safari, the audio context has a prefix of webkit for backward-compatibility reasons. Since
the Web Audio API is a work in progress, specification details may change.

Fetching and Buffering Sounds


Once an audio context has been instantiated, fetch your sounds from the disk or from a server. Load all the
sounds upfront that you anticipate could play to avoid a delay caused by network transmission. Then, buffer
the sounds so that theyre ready to be played at a moments notice. The buffer is essentially a nonpersistent
cache that allows you to replay sounds repeatedly without needing to reload the resource.
You load sounds with an asynchronous XMLHttpRequest. Set the response type of the request to
arraybuffer, which interprets the audio file as binary data. Add an event listener on the request to capture
the sound buffer as soon as it loads.
request = new XMLHttpRequest();
request.open('GET', 'explosion.aiff', true);
request.responseType = 'arraybuffer';
request.addEventListener('load', bufferSound, false);
request.send();

When the resource loads, pass the response of the AJAX request to the createBuffer() function on your
audio context. Below is the bufferSound() callback function that is referred to above in the event listener.
var mySource;
function bufferSound(event) {
var request = event.target;
var source = myAudioContext.createBufferSource();
source.buffer = myAudioContext.createBuffer(request.response, false);
mySource = source;
}

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

26

Playing Sounds with the Web Audio API


Synthesizing Sounds

Instead of calling createBuffer() directly, you can create a buffer by using the decodeAudioData()
function on your audio context. The decodeAudioData() function provides an optional third parameter you
can use to catch errors.
If you want to pull the audio of an <audio> or <video> element thats already on the page, you can bypass
both the XMLHttpRequest creation and manual buffering steps by calling your audio contexts
createMediaElementSource() function. Pass a reference to your desired media element to return a buffered
source. This can be used, for example, to change the pitch of the videos sound dynamically while the video
plays.

Synthesizing Sounds
Instead of loading a preexisting audio file, you can generate sounds with the Oscillator object. Oscillators are
great for creating beeps and single notes. Create an oscillator with the createOscillator() constructor,
and assign a waveform to its type property. Acceptable values for the type property are listed in Table
3-1 (page 27).
Table 3-1

Types of periodic waveforms

Type

Waveform

Sine wave

Square wave

Sawtooth wave

Triangle wave

var source = myAudioContext.createOscillator();


source.type = 0; // sine wave

You can also assign a custom waveform to the oscillator by creating a wave table. In the following example, a
waveform is created by using sine and cosine waves:
var curveLength = 100;
var curve1 = new Float32Array(curveLength);
var curve2 = new Float32Array(curveLength);
for (var i = 0; i < curveLength; i++)

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

27

Playing Sounds with the Web Audio API


Playing Sounds

curve1[i] = Math.sin(Math.PI * i / curveLength);

for (var i = 0; i < curveLength; i++)


curve2[i] = Math.cos(Math.PI * i / curveLength);

var waveTable = myAudioContext.createWaveTable(curve1, curve2);


source.setWaveTable(waveTable);

Oscillators produce tonal sounds. You can adjust the sound of the emitted tones in the same fashion as adjusting
any source, as further described in, Routing and Mixing Sounds (page 29).

Playing Sounds
Now that you have your source buffered or synthesized, for sound to emit from your speakers you need to
connect your source to a destination. You can route your source through a complex graph of nodes (which is
covered in the next section, Routing and Mixing Sounds (page 29)), but for now, connect it directly to the
destination of your audio context. You can do this by passing the destination property of your audio context
to the connect() function of your source.
source.connect(myAudioContext.destination);

Connecting a source to a destination is like hooking up an electric guitar to an amplifier: the input needs to
connect to the output in order to create an audible sound. The destination property always correlates to
the default hardware output of sound, whether its through speakers, attached headphones, or a Bluetooth
headset.
To play the sound immediately, call the noteOn(0) function on your source object.
// play right now (0 seconds from now)
source.noteOn(0);

To stop playing the sound immediately, call noteOff(0) on your source. Instead of 0, you can also pass the
currentTime property of your audio context.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

28

Playing Sounds with the Web Audio API


Routing and Mixing Sounds

Note: noteOn() and noteOff() may not be issued multiple times for a given source.

By specifying a time, you can schedule a precise beat or rhythm for your sounds to start playing. If the beat is
steady and consistent, you can choose to call noteOn(0) in a setInterval() with the interval of your choice.
Otherwise, you can calculate when the sounds will play in the future, and call noteOn() in a loop with the
relative playtimes as the argument.
// play 8 notes evenly spaced over the course of a half-second
for (var i = 0; i < 8; i++) {
var rest = i / 16;
source.noteOn(myAudioContext.currentTime + rest);
}

Routing and Mixing Sounds


The beauty behind the Web Audio API is that you can insert a graph of audio nodes between your source and
destination to alter the voice of the sound. This concept mimics a guitarists pedal board. Electric guitarists
pass their raw audio input through pedals, or audio filter effects, before the sound plays as audible output.
This gives them finer control to transmogrify their audio output. Just like how a musician can string together
a chain of pedals, you can create an intricate network of multiple audio sources and filters to modify your
produced sound.
The example below routes the input source through a compressor, then a reverberation modifier, and then a
volume control, before the sound is played.
var compressor = myAudioContext.createDynamicsCompressor();
var reverb = myAudioContext.createConvolver();
var volume = myAudioContext.createGainNode();

// connect source through a series of filters


source.connect(compressor);
compressor.connect(reverb);
reverb.connect(volume);
volume.connect(myAudioContext.destination);

source.noteOn(0);

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

29

Playing Sounds with the Web Audio API


Exploring More Possibilites

Imagine a guitar thats hooked up to a chain of pedals, which then feeds into an amp. The connect() function
is metaphorically a cable connecting audio equipment together.
There are many filter effects from which to choose; one of the most commonly used and most helpful to include
in your virtual pedal board is a compressor. Compressors boost soft tones and diminish loud tones, normalizing
the audio output so that there are no parts that are extremely quiet or extremely loud. This creates a more
pleasant listening experience and prevents strain on the listeners ears. While this effect is beneficial in the
majority of cases, there are some instances when a compressor would not be desiredfor example, someone
listening to classical music would want to hear every subtle pianissimo and grand fortissimo.
You can also mix several sources together to play out of the same destination. This is useful for crossfading
between two tracks: with one set of controls, you can manage two separate sources simultaneously. Just
instantiate a new source as described in Fetching and Buffering Sounds (page 26) or Synthesizing
Sounds (page 27), and connect it to the same destination.
Note: Make sure that your last filter is connected to your destination before you call noteOn().

Exploring More Possibilites


Access the raw data of the audio output by routing your sound through a real-time analyser node. Use your
imagination and creativity to come up with interfaces for playing and visualizing sound.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

30

Playing Sounds with the Web Audio API


Exploring More Possibilites

Listing 3-1 (page 31) selects a sound at random, passes the sound through audio filters, and loops the sound
while the audio spectrum is drawn on an HTML5 canvas, as shown in Figure 3-1 (page 31). It also provides
controls for adjusting filter properties and pausing a playing sound.
Figure 3-1

A simple synthesizer and audio spectrum visualizer

Listing 3-1

A simple synthesizer and audio spectrum visualizer

<!doctype html>
<html>
<head>
<title>mySynth</title>
<script>
const PATH = '/System/Library/Sounds/',
SOUNDS = ['Basso', 'Blow', 'Bottle', 'Frog', 'Funk', 'Glass', 'Hero',
'Morse', 'Ping', 'Pop', 'Purr', 'Sosumi', 'Submarine',
'Tink'];
var myAudioContext, myAudioAnalyser,
myBuffers = {}, mySource,
myNodes = {},

mySpectrum,

isPlaying = false;

function init() {

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

31

Playing Sounds with the Web Audio API


Exploring More Possibilites

if('webkitAudioContext' in window) {
myAudioContext = new webkitAudioContext();
// an analyser is used for the spectrum
myAudioAnalyser = myAudioContext.createAnalyser();
myAudioAnalyser.smoothingTimeConstant = 0.85;
myAudioAnalyser.connect(myAudioContext.destination);

fetchSounds();
}
}

function fetchSounds() {
var request = new XMLHttpRequest();
for (var i = 0, len = SOUNDS.length; i < len; i++) {
request = new XMLHttpRequest();
// the underscore prefix is a common naming convention
// to remind us that the variable is developer-supplied
request._soundName = SOUNDS[i];
request.open('GET', PATH + request._soundName + '.aiff', true);
request.responseType = 'arraybuffer';
request.addEventListener('load', bufferSound, false);
request.send();
}
}

function bufferSound(event) {
var request = event.target;
var buffer = myAudioContext.createBuffer(request.response, false);
myBuffers[request._soundName] = buffer;
}

function selectRandomBuffer() {
var rand = Math.floor(Math.random() * SOUNDS.length);
var soundName = SOUNDS[rand];

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

32

Playing Sounds with the Web Audio API


Exploring More Possibilites

return myBuffers[soundName];
}

function routeSound(source) {
myNodes.filter = myAudioContext.createBiquadFilter();
myNodes.panner = myAudioContext.createPanner();
myNodes.volume = myAudioContext.createGainNode();
// var compressor = myAudioContext.createDynamicsCompressor();

// set node values to current slider values


var highpass = document.querySelector('#highpass').value;
var panX = document.querySelector('#pan').value;
var volume = document.querySelector('#volume').value;

myNodes.filter.type = 1; // highpass
myNodes.filter.frequency.value = highpass;
myNodes.panner.setPosition(panX, 0, 0);
myNodes.volume.gain.value = volume;

// pass source through series of nodes


source.connect(myNodes.filter);
myNodes.filter.connect(myNodes.panner);
myNodes.panner.connect(myNodes.volume);
myNodes.volume.connect(myAudioAnalyser);

return source;
}

function playSound() {
// create a new AudioBufferSourceNode
var source = myAudioContext.createBufferSource();
source.buffer = selectRandomBuffer();
source.loop = true;
source = routeSound(source);
// play right now (0 seconds from now)

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

33

Playing Sounds with the Web Audio API


Exploring More Possibilites

// can also pass myAudioContext.currentTime


source.noteOn(0);
mySpectrum = setInterval(drawSpectrum, 30);
mySource = source;
}

function pauseSound() {
var source = mySource;
source.noteOff(0);
clearInterval(mySpectrum);
}

function toggleSound(button) {
if(!isPlaying) {
playSound();
button.value = "Pause sound";
isPlaying = true;
}
else {
pauseSound();
button.value = "Play random sound";
isPlaying = false;
}
}

function drawSpectrum() {
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;
var bar_width = 10;

ctx.clearRect(0, 0, width, height);

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

34

Playing Sounds with the Web Audio API


Exploring More Possibilites

var freqByteData = new Uint8Array(myAudioAnalyser.frequencyBinCount);


myAudioAnalyser.getByteFrequencyData(freqByteData);

var barCount = Math.round(width / bar_width);


for (var i = 0; i < barCount; i++) {
var magnitude = freqByteData[i];
// some values need adjusting to fit on the canvas
ctx.fillRect(bar_width * i, height, bar_width - 2, -magnitude +
60);
}
}

function sliderChange(slider) {
if(myAudioContext.activeSourceCount > 0) {
if(slider.id == 'highpass') {
var highpass = slider.value;
myNodes.filter.frequency.value = highpass;
}
else if(slider.id == 'pan') {
var panX = slider.value;
myNodes.panner.setPosition(panX, 0, 0);
}
else if(slider.id == 'volume') {
var volume = slider.value;
myNodes.volume.gain.value = volume;
}
}
}
</script>
<style>
input { display: block; }
</style>
</head>
<body onload="init()">
<input id="play" onclick="toggleSound(this)" type="button" value="Play random
sound" />

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

35

Playing Sounds with the Web Audio API


Exploring More Possibilites

<span>Highpass:</span>
<input id="highpass" onchange="sliderChange(this)" type="range" min="0"
max="1024" step="1" value="512" />
<span>Pan:</span>
<input id="pan" onchange="sliderChange(this)" type="range" min="-3" max="3"
step="0.01" value="0" />
<span>Volume:</span>
<input id="volume" onchange="sliderChange(this)" type="range" min="0" max="1"
step="0.01" value="1" />

<canvas width="300" height="200"></canvas>


</body>
</html>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

36

Controlling Media with JavaScript

Because the <audio> and <video> elements are part of the HTML5 standard, there are JavaScript methods,
properties, and DOM events associated with them.
There are methods for loading, playing, pausing, and jumping to a time. There are also properties you can set
programmatically, such as the src URL and the height and width of a video, as well as read-only properties
such as the videos native height. Finally, there are DOM events you can listen for, such as load progress, media
playing, media paused, and media done playing.
This chapter shows you how to do the following:

Use JavaScript to create a simple controller.

Change the size of a movie dynamically.

Display a progress indicator while the media is loading.

Replace one movie with another when the first finishes.

Keep the playback of multiple media elements in perfect sync.

Provide fallback content using JavaScript if none of the media sources is playable.

Enter and exit full-screen mode.

Take your custom video player and controls into full-screen mode.

For a complete description of all the methods, properties, and DOM events associated with HTML5 media, see
Safari DOM Additions Reference . All the methods, properties, and DOM events associated with
HTMLMediaElement, HTMLAudioElement, and HTMLVideoElement are exposed to JavaScript.

A Simple JavaScript Media Controller and Resizer


Listing 4-1 creates a simple play/pause movie control in JavaScript, with additional controls to toggle the video
size between normal and doubled. It is intended to illustrate, in the simplest possible way, addressing a media
element, reading and setting properties, and calling methods.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

37

Controlling Media with JavaScript


A Simple JavaScript Media Controller and Resizer

Any of the standard ways to address an HTML element in JavaScript can be used with <audio> or <video>
elements. You can assign the element a name or an id, use the tag name, or use the elements place in the
DOM hierarchy. The example in Listing 4-1 uses the tag name. Since there is only one <video> element in the
example, it is the 0th item in the array of elements with the video tag name.
Listing 4-1

Adding simple JavaScript controls

<!doctype html>
<html>
<head>
<title>Simple JavaScript Controller</title>
<script type="text/javascript">
function playPause() {
var myVideo = document.getElementsByTagName('video')[0];
if (myVideo.paused)
myVideo.play();
else
myVideo.pause();
}
function makeBig() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.height = (myVideo.videoHeight * 2 ) ;
}
function makeNormal() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.height = (myVideo.videoHeight) ;
}
</script>
</head>
<body>
<div class="video-player" align="center">
<video src="myMovie.m4v" poster="poster.jpg" ></video>
<a href="javascript:playPause();">Play/Pause</a> |
<a href="javascript:makeBig();">2x Size</a> |
<a href="javascript:makeNormal();">1x Size</a>
</div>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

38

Controlling Media with JavaScript


Using DOM Events to Monitor Load Progress

</body>
</html>

The previous example gets two read-only properties: paused and videoHeight (the native height of the
video). It calls two methods: play() and pause(). And it sets one read/write property: height. Recall that
setting only the height or width causes the video to scale up or down while retaining its native aspect ratio.
Note: Safari on iOS version 3.2 does not support dynamically resizing video on the iPad.

Using DOM Events to Monitor Load Progress


One of the common tasks for a movie controller is to display a progress indicator showing how much of the
movie has loaded so far. One way to do this is to constantly poll the media elements buffered property, to
see how much of the movie has buffered, but this is a waste of time and energy. It wastes processor time and
often battery charge, and it slows the loading process.
A much better approach is to create an event listener that is notified when the media element has something
to report. Once the movie has begun to load, you can listen for progress events. You can read the buffered
value when the browser reports progress and display it as a percentage of the movies duration.
Another useful DOM event is canplaythrough, a logical point to begin playing programmatically.
You can install event listeners on the media element or any of its parents, up to and including the document
body.
Listing 4-2 loads a large movie from a remote server so you can see the progress changing. It installs an event
listener for progress events and another for the canplaythrough event. It indicates the percentage loaded
by changing the inner HTML of a paragraph element.
You can copy and paste the example into a text editor and save it as HTML to see it in action.
Listing 4-2

Installing DOM event listeners

<!doctype html>
<html>
<head>
<title>JavaScript Progress Monitor</title>
<script type="text/javascript">
function getPercentProg() {

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

39

Controlling Media with JavaScript


Using DOM Events to Monitor Load Progress

var myVideo = document.getElementsByTagName('video')[0];


var endBuf = myVideo.buffered.end(0);
var soFar = parseInt(((endBuf / myVideo.duration) * 100));
document.getElementById("loadStatus").innerHTML =

soFar + '%';

}
function myAutoPlay() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.play();
}
function addMyListeners(){
var myVideo = document.getElementsByTagName('video')[0];
myVideo.addEventListener('progress', getPercentProg, false);
myVideo.addEventListener('canplaythrough', myAutoPlay, false);
}
</script>
</head>
<body onload="addMyListeners()">
<div>
<video controls
src="http://homepage.mac.com/qt4web/sunrisemeditations/myMovie.m4v">
</video>
<p id="loadStatus">MOVIE LOADING...</p>
</div>
</body>
</html>

Note: On the iPad, Safari does not begin downloading until the user clicks the poster or placeholder.
Currently, downloads begun in this manner do not emit progress events.

The buffered property is a TimeRanges object, essentially an array of start and stop times, not a single value.
Consider what happens if the person watching the media uses the time scrubber to jump forward to a point
in the movie that hasnt loaded yetthe movie stops loading and jumps forward to the new point in time,
then starts buffering again from there. So the buffered property can contain an array of discontinuous ranges.
The example simply seeks to the end of the array and reads the last value, so it actually shows the percentage

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

40

Controlling Media with JavaScript


Replacing a Media Source Sequentially

into the movie duration for which there is data. To determine precisely what percentage of a movie has loaded,
taking possible discontinuities into account, iterate through the array, summing the seekable ranges, as
illustrated in Listing 4-3
Listing 4-3

Summing a TimeRanges object

var myBuffered = document.getElementsByTagName('video')[0].buffered;


var total = 0;
for (var i = 0, len = myBuffered.length; i < len; i++) {
total += (seekable.end(i) - seekable.start(i));
}

The buffered, played, and seekable properties are all TimeRanges objects.

Replacing a Media Source Sequentially


Another common task for a website programmer is to create a playlist of audio or videoto put together a
radio set or to follow an advertisement with a program, for example. To do this, you can provide a function
that listens for the ended event. The ended event is triggered only when the media ends (plays to its complete
duration), not if it is paused.
When your listener function is triggered, it should change the medias src property, then call the load method
to load the new media and the play method to play it, as shown in Listing 4-4.
Listing 4-4

Replacing media sequentially

<!doctype html>
<html>
<head>
<title>Sequential Movies</title>
<script type="text/javascript">
// listener function changes src
function myNewSrc() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.src = "http://homepage.mac.com/qt4web/myMovie.m4v";
myVideo.load();
myVideo.play();

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

41

Controlling Media with JavaScript


Syncing Multiple Media Elements Together

}
// add a listener function to the ended event
function myAddListener(){
var myVideo = document.getElementsByTagName('video')[0];
myVideo.addEventListener('ended', myNewSrc, false);
}
</script>
</head>
<body onload="myAddListener()">
<video controls
src="http://homepage.mac.com/qt4web/A-chord.m4v">
</video>
</body>
</html>

The previous example works on both Safari on the desktop and Safari on iOS, as the load() and play()
methods are enabled even on cellular networks once the user has started playing the first media element.

Syncing Multiple Media Elements Together


Until the advent of media controllers, ensuring that two or more videos played at precisely the same time was
a challenging endeavor. Media controllers let you group any number of audio and/or video elements so that
they can be managed by a universal set of controls, and also so that they can be kept in perfect sync, even if
a network hiccup occurs.
To create a media controller, simply add the mediagroup attribute to all of the elements you wish to sync
together. The value you choose to assign to mediagroup is up to youas long as the value is the same for
each slaved element, a media controller will be created implicitly.
<video src="video.m4v" width="960" height="600"
mediagroup="masterController"></video>

Most of the same functions, attributes, and events available to audio and video elements are also available to
media controllers. Instead of calling play() or pause() directly on the video itself, you call them on the
media controller.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

42

Controlling Media with JavaScript


Using JavaScript to Provide Fallback Content

var myVideo = document.querySelector('video');


var mediaController = myVideo.controller;
mediaController.play();

Note: Two attributes that arent supported by media controllers are loop and autoplay.

Accessing the controller object on any of the slaved media elements will return a controller of the grouped
elements. You can also create a media controller entirely in JavaScript without needing to modify the attributes
of your HTML:
var myVideos = document.querySelectorAll('video');
var mediaController = new MediaController();
myVideos[0].controller = mediaController;
myVideos[1].controller = mediaController;
mediaController.play();

If one video stalls or stutters, the other videos will automatically pause to wait for the lagging video to catch
up. When the video buffers and is ready to play, the remaining videos will resume in sync.

Using JavaScript to Provide Fallback Content


Its easy to provide fallback content for browsers that dont support the <audio> or <video> tag using HTML
(see Specifying Fallback Behavior (page 17)). But if the browser understands the tag and cant play any of
the media youve specified, you need JavaScript to detect this and provide fallback content.
To test whether the browser can play any of the specified media, iterate through your source types using the
canPlayType method.
Important: The HTML5 specification has changed. Browsers conforming to the earlier version of the
specification, including Safari 4.0.4 and earlier, return no if they cannot play the media type. Browsers
conforming to the newer version return an empty string () instead. You need to check for either response,
or else check for a positive rather than a negative response.
If the method returns no or the empty string () for all the source types, the browser knows it cant play any
of the media, and you need to supply fallback content. If the method returns maybe or probably for any
of the types, it will attempt to play the media and no fallback should be needed.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

43

Controlling Media with JavaScript


Using JavaScript to Provide Fallback Content

The following example creates an array of types, one for each source, and iterates through them to see if the
browser thinks it can play any of them. If it exhausts the array without a positive response, none of the media
types are supported, and it replaces the video element using innerHTML. Listing 4-5 displays a text message
as fallback content. You could fall back to a plug-in or redirect to another page instead.
Listing 4-5

Testing for playability using JavaScript

<!doctype html>
<html>
<head>
<title>JavaScript Fallback</title>
<script type="text/javascript">
function checkPlaylist() {
var playAny = 0;
myTypes = new Array ("video/mp4","video/ogg","video/divx");
var nonePlayable = "Your browser cannot play these movie types."
var myVideo = document.getElementsByTagName('video')[0];
for (var i = 0, len = myTypes.length; i < len; x++) {
var canPlay = myVideo.canPlayType(myTypes[i]);
if ((canPlay == "maybe") || (canPlay == "probably"))
playAny = 1;
}
if (playAny == 0)
document.getElementById("video-player").innerHTML = nonePlayable;
}
</script>
</head>
<body onload="checkPlaylist()" >
<div id="video-player" align=center>
<video controls height="200" width="400">
<source src="myMovie.m4v" type="video/mp4">
<source src="myMovie.oga" type="video/ogg">
<source src="myMovie.dvx" type="video/divx">
</video>
</div>
</body>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

44

Controlling Media with JavaScript


Handling Playback Failure

</html>

Handling Playback Failure


Even if a source type is playable, thats no guarantee that the source file is playablethe file may be missing,
corrupted, misspelled, or the type attribute supplied may be incorrect. If Safari 4.0.4 or earlier attempts to
play a source and cannot, it emits an error event. However, it still continues to iterate through the playable
sources, so the error event may indicate only a momentary setback, not a complete failure. Its important to
check which source has failed to play.
Changes in the HTML5 specification now require the media element to emit an error only if the last playable
source fails, so this test is not necessary in Safari 5.0 or later.
The example in Listing 4-5 iterates through the source types to see if any are playable. It saves the filename of
the last playable source. If there are no playable types, it triggers a fallback. If there are playable types, it installs
an error event listener. The event listener checks to see if the current source contains the last playable filename
before triggering a failure fallback. (The currentSrc property includes the full path, so the test is for inclusion,
not equality.)
Notice that when adding a listener for the error event you need to set the capture property to true, whereas
for most events you set it to false.
Listing 4-6

Testing for failure using JavaScript

<!doctype html>
<html>
<head>
<title>JavaScript Fallback</title>
<script type="text/javascript">
var lastPlayable,
myTypes = new Array("video/mp4", "video/ogg", "video/divx"),
mySrc = new Array("myMovie.mp4", "myMovie.oga", "myMovie.dvx");

function errorFallback() {
var errorLast = "An error occurred playing ";
var myVideo = document.getElementsByTagName('video')[0];
if (myVideo.currentSrc.match(lastPlayable)) {
errorLast = errorLast + lastPlayable;

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

45

Controlling Media with JavaScript


Handling Playback Failure

document.getElementById("video-player").innerHTML = errorLast;
}
}

function checkPlaylist() {
var noPlayableTypes = "Your browser cannot play these movie types";
var myVideo = document.getElementsByTagName('video')[0];
var playAny = 0;
for (var i = 0, len = myTypes.length; i < len; i++) {
var canPlay = myVideo.canPlayType(myTypes[i]);
if ((canPlay == "maybe") || (canPlay == "probably")) {
playAny = 1;
lastPlayable = mySrc[i];
}
}
if (playAny == 0)
document.getElementById("video-player").innerHTML = noPlayableTypes;
else
myVideo.addEventListener('error', errorFallback, true);
}
</script>
</head>
<body onload="checkPlaylist()">
<video controls >
<source src="myMovie.mp4" type="video/mp4">
<source src="myMovie.oga" type="video/ogg">
<source src="myMovie.dvx" type="video/divx
</video>
</body>
</html>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

46

Controlling Media with JavaScript


Resizing Movies to Native Size

Resizing Movies to Native Size


If you know the dimensions of your movie in advance, you should specify them. Specifying the dimensions is
especially important for delivering the best user experience on iPad. But you may not know the dimensions
when writing the webpage. For example, your source movies may not be the same size, or sequential movies
may have different dimensions. If you install a listener function for the loadedmetadata event, you can resize
the video player to the native movie size dynamically using JavaScript as soon as the native size is known. The
loadedmetadata event fires once for each movie that loads, so a listener function is called any time you
change the source. Listing 4-7 shows how.
Listing 4-7

Resizing movies programmatically

<!doctype html>
<html>
<head>
<title>Resizing Movies</title>
<script type="text/javascript">
// set height and width to native values
function naturalSize() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.height = myVideo.videoHeight;
myVideo.width = myVideo.videoWidth;
}
// register listener function on metadata load
function myAddListener(){
var myVideo = document.getElementsByTagName('video')[0];
myVideo.addEventListener('loadedmetadata', naturalSize, false);
}
</script>
</head>
<body onload="myAddListener()">
<video src="http://homepage.mac.com/qt4web/myMovie.m4v" controls>
</video>
</body>
</html>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

47

Controlling Media with JavaScript


Taking Video Full Screen

Taking Video Full Screen


Safari 5.0 and later, and iOS 3.2 and later on iPad, include a fullscreen button on the video controller, allowing
the user to initiate full-screen video mode.
Safari 5.0 and iOS 4.2 and later add JavaScript properties and DOM events that your scripts can use to determine
when the browser has entered or exited full-screen video mode, as well as the methods to enter and exit
full-screen video mode programatically. See HTMLMediaElement Class Reference for a full description of the
full-screen DOM events, properties, and methods.
The following example, Listing 4-8, adds a button that puts Safari into full-screen video mode. The Boolean
property webkitSupportsFullscreen is tested to verify that the current media is capable of being played
in full-screen mode. Audio-only files cannot be played in full-screen mode, for example. The Full-screen button
is hidden until the test is performed.
Note: The webkitSupportsFullscreen property is not valid until the movie metadata has loaded.
You can detect when the metadata is loaded by installing an event listener for the loadedmetadata
event.

Important: The webkitEnterFullscreen() method can be invoked only in response to a user action,
such as clicking a button. You cannot invoke webkitEnterFullscreen() in response to a load event,
for example.

Listing 4-8

Using webkitEnterFullscreen()

<!doctype html>
<html>
<head>
<title>Fullscreen Video</title>
<script type="text/javascript">
var vid;
function init() {
vid = document.getElementById("myVideo");
vid.addEventListener("loadedmetadata", addFullscreenButton, false);
}
function addFullscreenButton() {
if (vid.webkitSupportsFullscreen) {

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

48

Controlling Media with JavaScript


Taking Your Custom Controls Full Screen

var fs = document.getElementById("fs");
fs.style.visibility = "visible";
}
}
function goFullscreen() {
vid.webkitEnterFullscreen();
}
</script>
</head>
<body onload="init()"
<h1>Fullscreen Video</h1>
<video src="myMovie.m4v" id="myVideo" autoplay controls>
</video>
<input type="button" id="fs" value="Fullscreen" onclick="goFullscreen()"
style="visibility:hidden">
</body>
</html>

Taking Your Custom Controls Full Screen


In Safari 5.1 and later for OS X and Windows, you can not only take your video into full-screen mode, you can
take any HTML element into full-screen mode. If you enclose a video and custom controls inside a div element,
for example, you can take the div element and all its contents into full-screen mode by calling
myDiv.webkitRequestFullscreen().
iOS Note: On iOS, full-screen videos can only display the default controls.

Use the following functions to take any element into and out of full-screen mode:

myElement.webkitRequestFullscreen()

document.webkitExitFullscreen()

When you enter full-screen mode programatically, it is important to remember that the user can exit full-screen
mode at any time by pressing the Esc key.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

49

Controlling Media with JavaScript


Taking Your Custom Controls Full Screen

Important: The webkitRequestFullscreen() method can be invoked only in response to a user action,
such as clicking a button. You cannot invoke webkitRequestFullscreen() in response to a load event,
for example.

Full-Screen Event and Properties


Safari emits a webkitfullscreenchange event when an element enters or exits full-screen mode. Listen for
this event to detect changes.
You can test the document.fullscreenEnabled property to see whether Safari has most recently entered
or exited full-screen mode. The property is true when in full-screen mode.
The document.webkitFullScreenElement property contains the element that is in full-screen mode. Use
this property if you have more than one element that could be in full-screen mode.

Resizing Enclosed Video


When a video element alone is taken into full-screen mode, the video is automatically scaled to fill the screen.
When other elements are taken full screen, however, they are not necessarily resized. Instead, normal HTML
rules are followed, so a div element and its children retain their height and width. If your video is inside an
element that you take full screen, you are responsible for resizing the video when Safari enters and exits
full-screen mode.
An easy way to resize video automatically is to define a full-screen pseudo-class in CSS for the element
enclosing the video. With this pseudo-class, you can specify a set of CSS styles that are only applied in
fullscreen mode. For example, if the ID of the div you are taking full-screen is video-player this CSS snippet
expands the enclosed video when the div element is in full-screen mode:
#video-player:-webkit-full-screen {
width: 100%;
}

A key advantage to using CSS is that it expands the video when its parent is in full-screen mode, then returns
the video to its normal size when its parent leaves full-screen mode.
It can be tricky to expand a video to use the full screen while preserving its aspect ratio. Here are some guidelines:

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

50

Controlling Media with JavaScript


Taking Your Custom Controls Full Screen

If your video aspect ratio is 16 x 9, setting the width to 100% usually works best without setting the height
explicitlyyour video is scaled to the correct width, and the height is scaled to preserve the aspect ratio.
Most displays are 4 x 3, 16 x 9, or slightly taller, so there is normally enough display height to prevent
clipping.

If your video aspect ratio is 4 x 3, setting the width to 75% gives the maximum image size for screens with
16 x 9 aspect ratios, while still using most of a 4 x 3 display. (Setting the width to 100% clips off the top
and bottom of the image on widescreen displays.) Alternatively, you can use JavaScript to read the screen
height and width, then set the width to 100% on 4 x 3 displays and 75% on wider displays.

If your video is taller than it is wide, setting the height to 100% and leaving the width unset gives you the
maximum image size on any landscape display.

If your controls appear under the video, instead of floating on top of the video, reduce the width or height
setting by 10% or so to leave room for the controls.

Full-Screen Video with Custom Controls Example


The example in Listing 4-9 creates a div element enclosing a video and a simple Play/Pause control. Beneath
the div element is a full-screen control. When the full-screen control is clicked, the example takes the div
element enclosing the video and Play/Pause control into full-screen mode.
CSS styles are used to expand the div element itself to 100% of the screen width and height, and to expand
the enclosed video element to 100% of the div elements width. Only the videos width is specified, so that
the video scales up while retaining its native aspect ratio. The example also gives the div element a black
background when in fullscreen mode.
More elaborate CSS could be used to hide the controls while in fullscreen mode and reveal them when the
user touches or hovers over the video. For more about styling video controllers using CSS, see Adding CSS
Styles (page 53).
Listing 4-9

Full-screen video with custom controls

<!doctype html>
<html>
<head>
<title>Fullscreen JavaScript Controller</title>
<style>
#video-player:-webkit-full-screen {
width: 100%;
height: 100%;
background-color: black;

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

51

Controlling Media with JavaScript


Taking Your Custom Controls Full Screen

}
#video-player:-webkit-full-screen video {
width: 100%;
}
</style>
<script type="text/javascript">
function playPause() {
var myVideo = document.querySelector('video');
if (myVideo.paused)
myVideo.play();
else
myVideo.pause();
}
function goFullscreen() {
var myPlayer = document.getElementById('video-player');
myPlayer.webkitRequestFullscreen();
}
</script>
</head>
<body>
<div id="video-player">
<video src="myMovie.m4v"></video>
<p><a href="javascript:playPause();">Play/Pause</a></p>
</div>
<a href="javascript:goFullscreen();">Full-screen</a>
</body>
</html>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

52

Adding CSS Styles

Because the <video> element is standard HTML, you can modify its appearance and behavior using CSS styles.
You can modify the opacity, add a border, position the element dynamically on the page, and much more.
You can also use CSS styles to enhance elements that interact with audio or video, such as custom controllers
and progress bars. In addition, you can listen for media events in JavaScript and change the properties of other
website elements in response.
Note: You may want to create your own stylish movie controllerincluding a progress bar and a
time scrubberthat slides smoothly out of the way when not in use. To see an example of just that,
download the ConcertDemo sample code from
http://developer.apple.com/safari/library/samplecode/HTML5VideoPlayer/index.html.
The sample code contains complete HTML, JavaScript, CSS, and video.

This chapter illustrates some methods of adding CSS styles to video, as well as how to modify the style of
non-video elements in response to media events. For more information on using CSS styles in Safari, see Safari
CSS Visual Effects Guide , Safari Graphics, Media, and Visual Effects Coding How-To's , and Safari CSS Reference .

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

53

Adding CSS Styles


Changing Styles in Response to Media Events

Changing Styles in Response to Media Events


You can use JavaScript to modify the style of website elements in response to media events. For example, you
could update a music playlist and highlight the name of the song currently being played. The example in
Listing 5-1 (page 55) changes the webpage styles when a movie is playingdarkening the background and
fading the rest of the webpage by making it partly transparentthen restores things when the movie is paused
or completes. Figures III-1 and III-2 show the webpage with the movie playing and paused.
Figure 5-1

Page with movie paused

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

54

Adding CSS Styles


Changing Styles in Response to Media Events

Figure 5-2

Page with movie playing

The example listens for the playing, pause, and ended events. When the playing event fires, a function
stores the current background color, sets the background color to black, and sets the opacity of the rest of the
page to 0.25. When the pause or ended event fires, a second function restores the background color and sets
the opacity to 1.
Note that the <style> section of the page sets the webkit-transition-property and
webkit-transition-duration for the background color and opacity, so these properties change smoothly
over a few seconds instead of changing abruptly. The background color and opacity change work in any
HTML5-compliant browser, but the gradual state change happens only in Safari and other WebKit-based
browsers.
Alternatively, you could set a JavaScript timer and darken the background and reduce the page opacity
incrementally over several steps.
Listing 5-1

Dim the lights

<!doctype html>
<html>
<head>
<title>Dim the Lights</title>
<script type="text/javascript">

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

55

Adding CSS Styles


Changing Styles in Response to Media Events

var restoreColor;
function dimLights() {
restoreColor = document.body.style.backgroundColor;
var theBody = document.body;
theBody.style.backgroundColor = "black";
var theRest = document.getElementById("restofpage");
theRest.style.opacity = 0.25;
}
function lightsUp() {
var theBody = document.body;
theBody.style.backgroundColor = restoreColor;
var theRest = document.getElementById("restofpage");
theRest.style.opacity = 1;
}
function addListener() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.addEventListener('playing', dimLights, false);
myVideo.addEventListener('pause', lightsUp, false);
myVideo.addEventListener('ended', lightsUp, false);
}
</script>
<style>
body {
background-color: #888888;
color: #ffdddd;
text-shadow: 0.1em 0.1em #333;
-webkit-transition-property: background-color;
-webkit-transition-duration: 4s;
}
#restofpage {
color: #ffffff;
width: 640px;
-webkit-transition-property: opacity;
-webkit-transition-duration: 4s;

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

56

Adding CSS Styles


Adding CSS Styles to Video

}
</style>
</head>
<body onload="addListener()">
<div align="center">
<h1>Dim the Lights, Please</h1>
<video id="player" controls
src="http://homepage.mac.com/qt4web/myMovie.m4v">
</video>
<div id="restofpage">
<h3 style="color:#ffdddd;" >
This webpage uses HTML5 video, JavaScript, DOM events, and CSS.
</h3>
<p>
When the video starts playing, a DOM event is fired, and a JavaScript
function "dims the lights" by fading the webpage background color
to black and lowering the opacity of the rest of the page.
</p>
<p>
When the video pauses or ends, another event is fired and a second
JavaScript function brings the lights back up.
</p>
<p>
Try it!
</p>
</div>
</div>
</body>
</html>

Adding CSS Styles to Video


You can use CSS to apply styles to the video element itself. For example, you can change the video opacity,
position the video on top of another element, or add a border.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

57

Adding CSS Styles


Adding CSS Styles to Video

Example: Setting Opacity


To allow elements under the video to show through, set the opacity of the video. Opacity has a range from 0
(completely transparent) to 1 (completely opaque). You can set opacity directly in CSSapplying it to video
generally, or to a class of video, or to a particular video element:
Declaring the opacity of the video element: video { opacity: 0.5 }
Declaring the opacity of a class: .seeThroughVideo { opacity: 0.3 }
Declaring the opacity of an element using its ID: #theVideo { opacity: 0.7 }
To change video opacity dynamically, use JavaScript. You can address the video element by ID or tag name,
and you can set the opacity property either directly or by changing the elements class name to a class with a
style applied to it.
The following code snippet declares the opacity of a class. The snippet then defines a JavaScript function that
sets a video elements classname to the declared class. A second JavaScript function illustrates setting the
opacity of a video element directly, instead of changing the classname.
<style>
.seeThroughVideo { opacity: 0.3 }
</style>

<script type="text/javascript">
function makeSeeThrough() {
document.getElementById("theVideo").className = "seeThroughVideo";
}
function setOpacityDirectly (val) {
document.getElementsByTagName("video")[0].style.opacity = val;
}
</script>

Using WebKit Properties


In addition to the standard CSS properties, you can apply WebKit properties to video in Safari or other
WebKit-based browsers. WebKit properties are prefixed with -webkit-. Many CSS properties begin as WebKit
properties, are proposed as CSS standards, and go through review before becoming standardized. When and
if a WebKit property becomes a standard property, -webkit- is dropped from the name. The -webkitprefixed version is maintained for backward compatibility, however.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

58

Adding CSS Styles


Adding CSS Styles to Video

You can safely add CSS properties that have the -webkit- prefix to your webpages. WebKit-based browsers,
such as Safari and Chrome, recognize these prefixed properties. Other browsers just ignore them. Use CSS
properties with the -webkit- prefix to enhance general websites, but verify that your site still looks good
using other browsers, unless your site is Safari-specific or designed solely for iOS devices.
Four noteworthy WebKit properties are filters, masks, reflections, and 3D rotation. These CSS properties are
available to other HTML elements as well, not just videos.

Adding a Filter
Safari 6 and later supports CSS filters, or special visual effects, that you can apply to many elements, including
videos (see Figure 5-3 (page 59)). These hardware-accelerated filters (such as brightness, contrast, saturation,
and blur) can be stacked on top of and animated against one another. Read CSS Property Functions in Safari
CSS Reference to find out more about CSS filters.
Figure 5-3

CSS filters on a video

The video above has a hue-rotation and saturation, as described in Listing 5-2 (page 60).

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

59

Adding CSS Styles


Adding CSS Styles to Video

Listing 5-2

Applying CSS filters to HTML elements

<!doctype html>
<html>
<head>
<title>Filters</title>
<style>
video {
float: left;
width: 50%;
}
.filtered {
-webkit-filter: hue-rotate(180deg)
saturate(200%);
}
</style>
</head>
<body>
<h1>Video with and without CSS filters</h1>
<p>The video on the left does not have CSS filters applied, while the video
on the right does.</p>
<p>These videos are playing from the same source file.</p>
<video src="shuttle.m4v" autoplay></video>
<video src="shuttle.m4v" autoplay class="filtered"></video>
</body>
</html>

Adding a Mask
You can make a video element appear non-rectangular or discontinuous by masking part of the video out
using -webkit-mask-box-image. Specify an image to use as a mask. The mask image should have the same
dimensions as the video, be opaque where you want the video to show, and be transparent where you want
the video to be hidden. Making areas of the mask semi-opaque makes the corresponding areas of the video
proportionally semi-transparent.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

60

Adding CSS Styles


Adding CSS Styles to Video

The following example uses CSS to position a video over the image of a porthole, then masks the video with
a circular image so the movie appears to be seen through the porthole.
Background image

Video

Mask

Masked video over image

<!doctype html>
<html>
<head>
<title>porthole</title>
</head>
<body>
<h1>Video with Filters</h1>
<p>
Video is saturated and blurred with CSS filters.
</p>
<img src="porthole.jpg" width="430" height="365">

<video src="myMovie.m4v" autoplay


style="position:relative; top:-325px;
-webkit-mask-box-image: url(portholemask.png);">
</video>
</body>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

61

Adding CSS Styles


Adding CSS Styles to Video

</html>

Note: If your mask conceals the built-in controls, they cannot be used to play the videobe sure
to provide a JavaScript controller or to set the autoplay attribute, bearing in mind that autoplay
is disabled on cellular-capable devices such as iPhone and iPad.

Adding a Reflection
Add a reflection of a video using the -webkit-box-reflect property. Specify whether the reflection should
appear on the left, right, above, or below the video, and specify any offset space between the video and the
reflection. The following snippet adds a reflection immediately below the video.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

62

Adding CSS Styles


Adding CSS Styles to Video

<video src="myMovie.m4v" autoplay style="-webkit-box-reflect: below 0px;">

If you set the controls attribute, the video controls will also appear mirrored in the reflection. Since the
mirrored controls are backwards and nonfunctional, this is not usually what you want. Video reflections are
best used with a JavaScript controller.
You can mask out part of the reflection by including the url of a mask image. The following example adds a
masked reflection below the video.
<!doctype html>
<html>
<head>
<title>Reflection with Mask</title>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

63

Adding CSS Styles


Adding CSS Styles to Video

<script type="text/javascript">

function playPause() {
var myVideo = document.getElementById('theVideo');
if (myVideo.paused)
myVideo.play();
else myVideo.pause();
}
</script>
</head>
<body align="center" style = "background-color: 404040">
<h1 style="color:#ffeeee">
Reflection with Mask
</h1>
<input type="button" value="Play/Pause" onclick="playPause()">
<BR><BR>
<video

src = "myMovie.m4v" id = "theVideo"

style = "-webkit-box-reflect: below 0px url(mask.png);">


</video>
</body>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

64

Adding CSS Styles


Adding CSS Styles to Video

</html>

Figure 5-4

Reflection with mask image

Important: The mask image is reflected, so flip it 180 on the axis of reflection from the way you want it
to appear.

Figure 5-5

Mask image

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

65

Adding CSS Styles


Adding CSS Styles to Video

You can specify a gradient instead of an image to mask the reflection. The following snippet creates a gradient
that fades to transparency.
<video style="-webkit-box-reflect: below 0px
-webkit-gradient(linear, left top, left bottom, from(transparent), to(black));">

Because the gradient is reflected, it is specified from transparent to blackits reflection goes from black to
transparent. Because the gradient is a mask, only its opacity matters. It could also be specified from transparent
to white.
The following snippet adds a color-stop to the gradient, causing it to reach transparency at four-tenths of its
length.
<video style="-webkit-box-reflect: below 0px
-webkit-gradient(linear, left top, left bottom, from(transparent), to(black),

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

66

Adding CSS Styles


Adding CSS Styles to Video

color-stop(0.4, transparent));">
Figure 5-6

Reflection with gradient mask and color stop

Rotating Video in 3D
You can use WebKit CSS properties to rotate video around the x or y axis. Rotating the video 180 allows the
user to see it playing from behind. Rotating the video 90 causes it to play edge-on, making it invisible and
revealing whatever is behind it. Rotation can be set statically using CSS or dynamically using JavaScript. The
following snippet sets the video rotation at 45 about the y axis.
<video style="-webkit-transform: rotateY(45deg);" src="myVideo.m4v" controls>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

67

Adding CSS Styles


Adding CSS Styles to Video

Note: When a video element is rotated between 90 and 270, the controls are either reversed or
edge-on, and are not operable.

Dynamic rotation is best used in conjunction with the webkit-transition property. Setting
webkit-transition causes the video element to rotate smoothly over a specified duration, without having
to set JavaScript timers or stepper functions. You set the transition property, specify the duration, and any
time you change the specified property, the change is animated smoothly over the specified duration. The
property to animate for rotation is -webkit-transform. When the animation completes, a
webkitTransitionEnd event is fired.
The following snippet sets the transition property to -webkit-transform and sets the animation duration
to 4 seconds.
<video src="myVideo.m4v" controls
style="-webkit-transition-property: -webkit-transform;
-webkit-transition-duration: 4s">

You can add perspective to the rotation, so that parts of the video element closer to the viewer along the z
axis appear larger, and parts further away appear smaller. To add perspective, set the -webkit-perspective
property of one of the video elements parents, such as a parent div or the document body.
Listing 5-3 dynamically flips a playing video 180 around its y axis, intermittently revealing the text behind the
video. The video has perspective when it rotates, due to the -webkit-perspective property of the body
element.
Listing 5-3

3D rotation with perspective

<!doctype html>
<html>
<head>
<title>Video Flipper</title>
<style>
video {
-webkit-transition-property: -webkit-transform;
-webkit-transition-duration: 4s;
}
body { -webkit-perspective: 500; }

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

68

Adding CSS Styles


Adding CSS Styles to Video

</style>
<script type="text/javascript">
var flipped = 0;
function flipper() {
if (flipped)
myVideo.style.webkitTransform = "rotateY(0deg)";
else
myVideo.style.webkitTransform = "rotateY(180deg)";
flipped = !flipped ;
}
</script>
</head>
<body>
<h1>Video Flipper</h1>
<p>Text hidden behind the video.</p>
<div style="position:relative; top:-40px;">
<video src="myMovie.m4v" id="myVideo" autoplay controls>
</video>
<input type="button" value="Flip Video" onclick="flipper()">
</div>
</body>

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

69

Adding CSS Styles


Adding CSS Styles to Video

</html>

Figure 5-7

Video in mid-rotation

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

70

Document Revision History

This table describes the changes to Safari HTML5 Audio and Video Guide .

Date

Notes

2012-07-23

Added information about the Web Audio API, syncing media with media
controllers, and CSS filters.

2011-07-05

Updated with description of fullscreen mode for HTML elements.

2010-12-16

Updated to describe inline audio on iPhone and iPod touch.

2010-11-15

Updated for Safari 5.02 and iOS 4.2.

2010-03-18

Corrected typos in sample code and text. Minor changes throughout.

2010-03-09

New document showing how to use the HTML5 <audio> and <video>
elements using HTML, JavaScript methods, DOM events, and CSS styles.

2012-07-23 | 2012 Apple Inc. All Rights Reserved.

71

Apple Inc.
2012 Apple Inc.
All rights reserved.
No part of this publication may be reproduced,
stored in a retrieval system, or transmitted, in any
form or by any means, mechanical, electronic,
photocopying, recording, or otherwise, without
prior written permission of Apple Inc., with the
following exceptions: Any person is hereby
authorized to store documentation on a single
computer for personal use only and to print
copies of documentation for personal use
provided that the documentation contains
Apples copyright notice.
No licenses, express or implied, are granted with
respect to any of the technology described in this
document. Apple retains all intellectual property
rights associated with the technology described
in this document. This document is intended to
assist application developers to develop
applications only for Apple-labeled computers.
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
408-996-1010
Apple, the Apple logo, iPad, iPhone, iPod, iPod
touch, Mac, Mac OS, OS X, QuickTime, and Safari
are trademarks of Apple Inc., registered in the
U.S. and other countries.
Java is a registered trademark of Oracle and/or
its affiliates.
Ping is a registered trademark of Karsten
Manufacturing and is used in the U.S. under
license.
iOS is a trademark or registered trademark of
Cisco in the U.S. and other countries and is used
under license.
Even though Apple has reviewed this document,
APPLE MAKES NO WARRANTY OR REPRESENTATION,
EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS
DOCUMENT, ITS QUALITY, ACCURACY,
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR
PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED
AS IS, AND YOU, THE READER, ARE ASSUMING THE
ENTIRE RISK AS TO ITS QUALITY AND ACCURACY.
IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES RESULTING FROM ANY DEFECT OR
INACCURACY IN THIS DOCUMENT, even if advised of
the possibility of such damages.
THE WARRANTY AND REMEDIES SET FORTH ABOVE
ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL
OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer,
agent, or employee is authorized to make any
modification, extension, or addition to this warranty.
Some states do not allow the exclusion or limitation
of implied warranties or liability for incidental or
consequential damages, so the above limitation or
exclusion may not apply to you. This warranty gives
you specific legal rights, and you may also have other
rights which vary from state to state.

Vous aimerez peut-être aussi