SVG at the movies - take two!
Wednesday, November 21, 2007 6:13:03 PM
This article will show you how to present video on the web using open standards and SVG (Scalable Vector Graphics.)
Introduction
As you may have already guessed one of the major new features introduced in the SVG Tiny 1.2 specification is the
video
element. It should be noted that while this is a major feature and a great leap forward, SVG Tiny 1.2 itself doesn't mandate any particular audio or video codecs. This topic is explored in the call for video on the web article on dev.opera.com. Of particular interest in that article are the svg video demos at the bottom.Prerequisites
First, for maximum enjoyment you need a way of viewing the examples in this article. I suggest the experimental Opera 9.5 video build, which can be downloaded here. At the moment there is only a Windows build, but *nix and OSX builds are in the works. Because of the beauty of open standards you can choose any SVG-supporting browser you like to view the content, such as Firefox, although at the time of writing declarative animations are not supported in Firefox, so the demos below may not work as intended.
The experimental builds of Opera and Firefox both implement Ogg Theora and Ogg Vorbis as the baseline audio/video format, which means that it's implemented natively in the browsers and that it will work the same across all platforms and different browsers.
Lights, camera, ACTION!
Examples first, explanations later. Note that this example requires support for declarative animation in SVG, and some other SVG 1.1 features, like styling with CSS and patterns.
View live example.
Click the white rectangle - a short animation will play, and then a video will start playing.
Animation in SVG
One of the coolest things about SVG is the previously-mentioned declarative animation. With this you can create advanced animated SVG content without having to write a single line of JavaScript. Instead, you specify simple properties - for example properties to animate between two values during a particular amount of time. You can even add interactivity since events are supported in the declarative animation model. Here is an excerpt showing both how to listen for a click, and how to animate things using declarative animation:
<g transform="matrix(0 -10 10 0 50 50)" style="fill: white"> <g transform="translate(0 -2)"> <path transform="matrix(1 0 0 1 -5 -5)" d="M10,10H4L0,6V0h10V10z"> <animate id="ref" attributeName="d" to="M10,10H0L0,10V0h10V10z" begin="click" dur="1s" fill="freeze" /> </path> <animateTransform attributeName="transform" type="translate" begin="ref.begin" dur="1s" fill="freeze" values="0 -2; 0 0" /> </g> ...
The above code does the animated morphing of the white rect shape in the above example. By animating the
d
attribute from one value to the next you don't have to worry about interpolating the values yourself, however, due to the design of path animation the paths must be compatible, which means they must have the same number of path commands and the path command types must be of the same type after normalization has taken place. This is illustrated by this testcase; to morph between any two shapes the best bet is to make all segments into Bezier curves. Kevin Lindsey made some tools for doing just that, and I recommend reading his introduction to Bezier curves article and looking at the path morphing script API. Now let's look at some more code:... <animateTransform attributeName="transform" type="translate" begin="ref.end" dur="0.5s" fill="freeze" values="50 50;160 120" /> <animateTransform attributeName="transform" type="rotate" begin="ref.end" dur="0.5s" fill="freeze" additive="sum" values="-90;0" /> <animateTransform attributeName="transform" type="scale" begin="ref.end" dur="0.5s" fill="freeze" additive="sum" values="10 10;32 24" /> <set attributeName="display" to="none" begin="ref.end+0.5s" fill="freeze" /> </g>
Here we see what gives us the rotating and scaling rectangle. By using the
additive
attribute it's easy to use multiple transformations and animate them separately. First in the stack of animated transforms is a translation (a move) between the coordinates (50,50) and (160,120). We'll let the browser interpolate values between those two coordinates over the course of half a second. At the same time a rotation animation takes place, between -90 and 0 degrees. This animateTransform
specifies additive="sum"
, which means that it will not replace the previous transform, but be appended to it by doing a post-multiplication. Then we add a scaling transform - perhaps you only expected to see two values instead of four in the values
attribute? That is of course possible, but sometimes you want to apply different scale factors to the x- and y-axis, and that is the case here. Finally the shape is hidden by animating the display
property.How to do cheap video clipping
You might have been impressed with the non-rectangular clipping of the video (the smooth smooth curved shape that looks something like a tv-set.) The neat thing is that this is not really clipping - it's just drawing on top of the video, which can provide the faded edges due to SVG supporting opacity. The overlay has been optimized to use only fill (since stroking operations are usually more expensive in vector graphic engines), as we can see in the source below.
<g transform="translate(-15, -10)" style="display: none; fill: #fa9bce"> <path style="fill-opacity: 0.4" d="M0,0v260h350V0H0z ..." /> <path d="M0.5,0.5v260h350V0.5H0.5z M330.073,235.451 ..."/> <path style="fill:none;" d="M0.5,0.5v260h350V0.5H0.5z ..."/> </g>
There are drawbacks to this "poor man's" clipping. Say if you want an advanced background around the video frame - eg animated gradients - or something that is not a simple solid color? You can get around this by simply using the clipping features of SVG 1.1 to do arbitrary shape clipping, then you can place your clipped video or graphics anywhere. For an example of using clipping and video together, see here.
Action? I mean interaction
Now it's time for something a bit more interactive - here's an example that allows real-time transformation of video with a bit of JavaScript. Click to play the video, and then drag the corners of the video to transform it.
View live example.
Tweaking the examples
To get these examples to work in Opera, I had to do a bit of debugging, but this really was a small effort, basically consisting of applying the debugging techniques presented in the debugging SVG with Opera article. First, since the experimental video build doesn't support MPEG-4 (the format of the original videoclip) there is a choice of re-encoding the video or simply using another video file, for example one of the growing selection of Theora videos available at wikimedia. Next, as is often the case with content authored mainly for the Adobe SVG plugin, some minor details needed to be changed in the scripts. What I did in order to keep the content mostly as-is was to include a wrapper script for the DOM methods getURL and parseXML. These two methods are sometimes used in old svg content, and are also included in the SVG Tiny 1.2 specification, though there are some differences in how it is specified there versus what was implemented in the Adobe SVG plugin.
The rather simple wrapper script uses XMLHttpRequest and DOMParser to provide the same functionality offered by the getURL and parseXML methods.
Many thanks to Antoine Quint and xml.com for letting me publish modified examples from the original SVG at the movies article.
Comments
Erik DahlströmMacDev_ed # Sunday, November 25, 2007 9:49:38 PM
Judging from how people share video on the web today I don't think transcoding content is such a big problem. It's easy enough to do, and the tools are already out there.
Antoine Quintgraouts # Thursday, November 29, 2007 5:18:32 PM
andrewshikaka # Thursday, November 29, 2007 6:21:13 PM
zoquete # Thursday, November 29, 2007 7:25:53 PM
Unbelievable,
I hear a czech singer - Ivan Mládek - in background. Very poplular in the 70's - 80's
UNBELIEVABLE!!!
Zoquete (Czech Republic)
_____
Sorry I was not logged in
FataL # Friday, November 30, 2007 12:13:33 AM
jonyellow # Saturday, December 29, 2007 2:01:49 PM
deborahwebb # Tuesday, February 12, 2008 12:13:41 PM
annmacgiff # Tuesday, February 12, 2008 1:15:21 PM
qwertzguy # Tuesday, February 26, 2008 12:28:24 PM
I've just updated to Opera 9.26 and the first example only does the white box anymation but no video and the second example doesn't do anything at all.
Is this because of Opera 9.26?
Thanks
Erik DahlströmMacDev_ed # Tuesday, February 26, 2008 4:10:49 PM
Yes, you need the experimental video build to see the video, like it says in the Prerequisites section.
Charles McCathieNevilechaals # Saturday, July 19, 2008 2:50:11 AM
Unregistered user # Sunday, November 1, 2009 1:39:42 PM
Unregistered user # Wednesday, December 2, 2009 9:57:18 PM
Charles McCathieNevilechaals # Sunday, December 6, 2009 6:32:53 PM
Unregistered user # Tuesday, March 23, 2010 1:17:31 AM
Nguyễn Thunguyenthupk # Tuesday, May 11, 2010 1:44:37 AM