![]() |
|
|
#1 (permalink) |
|
Administrator
Join Date: Oct 2006
Posts: 25
![]() |
First Flash:
The Twice-Cooked Method Flash has always shipped with some method of generating an HTML page to contain Flash movies. Initially, it was a tool called AfterShock. Since the release of Flash 4, authors can export HTML pages with embedded movies from within the Flash authoring environment. This markup produced by Flash is the de facto standard that you’ll find in 99% of sites that use Flash movies. <object classid="clsid 27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com /pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="400" height="300" id="movie" align=""> <param name="movie" value="movie.swf"> <embed src="movie.swf" quality="high" width="400" height="300" name="movie" align="" type="application/x-shockwave-flash" plug inspage="http://www.macromedia.com/go/getflashplayer"> </object> As you can see, it’s a bit of a monster. There are two main tags used to embed the movie, requiring every value to be declared twice. Internet Explorer and its followers primarily use one tag; browsers that consider themselves friends of Netscape use the other. We’ll call this the Twice Cooked method. <object> is part of the XHTML specification, but is badly implemented here. It is used by IE style browsers to start an instance of the Flash Player and load in the specified movie. The <param> element is its bedfellow, offering any number of parameters to be passed to the player once it is started. <embed> is not part of the XHTML specification and will prevent your page from validating. It is used by Netscape and similar browsers for displaying Flash movies. Parameters are passed within the element as name/value attribute pairs. The <embed> Element The <embed> element was created by Netscape as their method of embedding plug ins and players in web pages. It’s not part of the XHTML specification, and while some browsers other than Netscape support it, it’s not standards-compliant, so it’s out. Bye bye, <embed> ... it's been swell. The <object> Element Without <embed>, we’re left with the <object> element, so it would be prudent to fully understand its capabilities. The great news is that just about every browser in popular use supports <object> in one way or another. The <object> element has no required attributes, but many are available for use. Below are the more interesting ones, along with edited highlights from the W3C specification. classid (URI) This attribute may be used to specify the location of an object’s implementation via a URI. It may be used together with or as an alternative to the data attribute (see below), depending on the type of object involved. codebase (URI) This attribute specifies the base path used to resolve relative URIs specified by the classid, data, and archive attributes. When absent, its default value is the base URI of the current document. data (URI) This attribute may be used to specify the location of the object’s data, or more generally, a serialized form of an object which can be used to recreate it. type (content-type) This attribute specifies the content type for the data specified by data. codetype (content-type) This attribute specifies the content type of data expected when downloading the object specified by classid. There are other attributes that allow references to archived versions, cause text to display while loading (we can do this is Flash already), and so on, as well as width, height, id, class and other common attributes. The ones listed above, however, are particularly relevant when it comes to embedding Flash movies. Another useful thing I learned is that an <object> tag can contain child elements which can be used as an alternative if the browser doesn’t have the capability to display the object itself. In fact, this is how the undesirable nested <embed> works in Netscape browsers—but more on that later. The Process Armed with a more thorough understanding of the markup, I set about doing some testing in various browsers. My first step was to try the Macromedia markup with the <embed> stripped out, and cleaned up for XHTML: <object classid="clsid 27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com /pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="400" height="300"> <param name="movie" value="movie.swf" /> </object> Unfortunately, this simply doesn’t work outside IE-style browsers. After a little jiggerypokery and some Googling, I discovered that the GUID used in the classid attribute was specific to the browser’s ActiveX configuration. In fact, it was causing Netscape 7 and Mozilla to totally ignore the object. The classid attribute does, however, perform an important function: telling the browser which Player to use. So we can’t simply get rid of it without replacing its functionality with something else. Fortunately, the Flash Player is configured to respond to content with a MIME type of application/x-shockwave-flash. This is great, because the type attribute allows us to specify a content type. Therefore, out goes: classid="clsid 27CDB6E-AE6D-11cf-96B8-444553540000" ... and in comes:type="application/x-shockwave-flash" Codebase The above change doesn’t get movies playing in Netscape browsers on its own. The next curiosity on the list is the codebase attribute. This contains a path to a copy of the Flash plug in-on Macromedia’s servers. This is actually incorrect usage of the attribute, as any paths within it are supposed to be within the same domain—a security feature. In many browsers (primarily IE) this attribute performs another function. The path contains a string on the end that specifies which version of the plug-in the server should deliver. If the version declared is later than the version currently installed, the browser will prompt the user to allow it to update. The downside is that this attribute also stops the movie from playing in Netscape and Mozilla when used in this way, so it’s gotta go. We’ll discuss a work-around for this lost functionality later on. With the codebase attribute gone, our markup is beginning to look pleasantly sparse: <object type="application/x-shockwave-flash" width="400" height="300"> <param name="movie" value="movie.swf" /> </object> Try this code, and it still won’t load a movie in Netscape. Having gotten this far, I worried that there was literally no way to use valid markup to deliver Flash in Netscape browsers, and every response to this question online told me as much. So I did what I always do and started trying crazy things. Making Progress When I tried out the data attribute, I nearly had kittens, as movies suddenly started playing in Netscape and Mozilla. Flipping back to IE revealed that the movies played there too. <object type="application/x-shockwave-flash" data="movie.swf" width="400" height="300"> <param name="movie" value="movie.swf" /> </object> After testing with some largish movies, I noticed something amiss. While every other browser was getting it right, IE/Windows was not streaming—it was waiting for the entire movie to download before playing it. This is fine for small movies, but for anything serious, the lack of streaming is unacceptable. I concluded that valid markup for Flash movies was possible, but only once Microsoft had fixed this problem with IE/Windows. The Satay Method A few days later I was discussing this issue with Jeffrey Zeldman, explaining how I’d come close to a solution but hadn’t quite found it. He was interested that I’d managed to come close, having experienced the problem himself on recent projects. This got me thinking, and while driving home that evening the solution hit me. The only problem with the code I had is that IE/Windows doesn’t stream the movie. It waits for the whole movie to download and then plays it. This is fine for very small movies, as the wait isn’t that noticeable. So, how about creating a very small container movie, which in the first frame loads in the real movie we want to play? I tested it, and it works. It’s a bit of a hack, but a valid and justifiable hack in my opinion. The greatest thing is that you don’t have to create a separate container movie for each “real” movie—one smart container can work with any Flash movie having the same proportions. No matter if your movie is made from beef, chicken, or pork, you still need to skewer it and dip it in the sauce to make it work. We call this the Satay Method. The container movie I created a new Flash movie and put the following ActionScript on Frame 1 right in the root of the movie: _root.loadMovie(_root.path,0); This instructs the Flash Player to load a movie, whose name is in the variable path on the root, into Level 0 of the current movie. All we need to do is make sure that the name of the movie we want to load is held in the variable called path. Flash makes this part easy. The Flash Player loads any name/value pairs that are passed to a Flash movie on a query string into the root of the movie. This is useful for many different applications, but in our case it means that we just need to call the movie like this: c.swf?path=movie.swf The container movie is c.swf. I’m passing it a variable called path with a value of movie.swf. This means that our ActionScript, when evaluated, would equate to this: _root.loadMovie("movie.swf",0); You can modify the behavior of the container movie to do whatever you like—as long as it’s kept small. You can use GET and POST to pass variables through the container if you need to, for example. This method, however, will only work well if the container movie is just a few kilobytes in size. The markup This leaves us with just the markup to finalize. We’ve dropped a lot of attributes, added some sparkling new ones, and tidied it all up: <object type="application/x-shockwave-flash" data="c.swf?path=movie.swf" width="400" height="300"> <param name="movie" value="c.swf?path=movie.swf" /> </object> So there it is—meaner, leaner, and altogether better for the environment. But what about that functionality we lost when axing the codebase attribute? Compensating The main problem with getting rid of the codebase attribute was that in IE and similar browsers it caused the user to be prompted to update their Flash plug-in if it was out of date. This is really useful, as it’s likely the only way that most ordinary web users get their players updated. The workaround is simple: just include one sacrificial movie at the front of your site with the codebase attribute left in. This needs to be a movie with no purpose within the site—just a 1k empty blob of nothingness that causes the user to be prompted if they have an old version of the plug in. Not the cleanest approach, but a practical one. It shouldn’t lose you any friends. Alternative Content Remember that behavior of the <object> tag I was talking about earlier, where the browser will try to parse a child element if it can’t work with the object itself? It’s very cool. If you were to look at the source code of the home page at Macromedia.com, you’d see that they serve up an alternative image if the user can’t view Flash movies. They are detecting the Flash Player with JavaScript, and then using JavaScript to dynamically write out HTML based on the detection. Ugly, ugly, ugly. Here’s how I’d do it: <object type="application/x-shockwave-flash data="c.swf?path=movie.swf" width="400" height="300"> <param name="movie" value="c.swf?path=movie.swf" /> <img src="noflash.gif" width="200" height="100" alt="" /> Second video: It has always gotten my goat that Internet Explorer’s non-standard use of the object tag has forced standards-loving browsers to use the non-standard embed tag in order to embed movies on a web page. Even on Apple’s site, the embed tag—a Netscape extension, for Pete’s sake!—is so entrenched that it’s hard to even find information about using the object element for QuickTime, except in a non-standard way. The use of embed has gone on too long. Wishing for it to become part of the official specs is like wishing your partner would start putting the cap on the toothpaste. It’s not going to happen. It’s time to move on. If you want to validate your website, you have to get rid of embed. In this article, I’ll show you how. Online Movies: Google Video and YouTube ALA readers will remember Drew McLellan’s seminal article on Flash Satay. In that article, Drew described a method for inserting Flash animations on a page without using the embed element. Flash Satay has two parts. First, Drew figured out that you can use a single object element to call Flash as long as you specify its type adequately. Second, to properly stream Flash movies, you have to embed a sort of reference movie. I’ve been experimenting with Drew’s code on Google Video and YouTube content. I was shocked to find that Google Video suggests you use only the embed tag to embed their video on Web pages. Alas, not shocked that they would suggest such a thing—just shocked that it actually works on Internet Explorer, which stopped supporting the non-standard, but universally-supported embed tag years ago in favor of its proprietary implementation of the standard object tag that renders that tag completely invisible to standards-loving browsers. It turns out that IE supports embed as long as the visitor has the appropriate player already installed. If not, they get an error and a generic broken-plugin icon, but no help. YouTube, for its part, does the often seen but hardly standard twice cooked approach, offering both the object and embed tags. Since both Google Video and YouTube serve movies through the Flash player—regardless of your movie’s format when you uploaded it—you can use Drew’s single object method to embed such movies on your page. Indeed, you don’t have to use the Satay part of his code; movies on Google Video and YouTube stream even without the reference movie he suggests. (Line wraps marked » —Ed.) <object type="application/x-shockwave-flash" data="http://video.google.com/googleplayer.swf? » 8755581808731033658" width="400" height="326" id="VideoPlayback"> <param name="movie" value="http://video.google.com/googleplayer.swf? » docId=8755581808731033658" /> <param name="allowScriptAcess" value="sameDomain" /> <param name="quality" value="best" /> <param name="bgcolor" value="#FFFFFF" /> <param name="scale" value="noScale" /> <param name="salign" value="TL" /> <param name="FlashVars" value="playerMode=embedded" /> </object> My real peeve, however, as I mentioned above, isn’t with Flash movies—which I have little experience with—but with QuickTime and Windows Media Player movies. I’ve been trying to embed these in a standard way for years, but without much luck. Quite recently, I came upon the MIME type that will let you use a single object for Windows Media Player files (.wmv). I still can’t quite believe it. Eureka! One object for Windows Media Player I am a firm believer in paying attention to mistakes. It’s only when I notice that I’ve done something wrong, and figure out why, that I am able to figure out new ways of doing things right. As I was reviewing the technique, I noticed that although it did work well for QuickTime movies (as described below), it didn’t work for Windows Media Player movies…on Opera…for Windows. I suppressed the urge to ignore it, and as I dug for an answer to that problem, I came across the MIME type that will let you use a single object to embed Windows Media Player files: video/x-ms-wmv. To embed a Windows Media Player file, you should be able to use this code (Line wraps marked » —Ed.): <object type="video/x-ms-wmv" data="http://www.sarahsnotecards.com/catalunyalive/ » fishstore.wmv" width="320" height="260"> <param name="autostart" value="true" /> <param name="controller" value="true" /> </object> But it turns out that IE6 and IE7 and Safari (strange bedfellows if ever there were), all need a little extra push, in the form of an extra param element: <object type="video/x-ms-wmv" data="http://www.sarahsnotecards.com/catalunyalive/ » fishstore.wmv" width="320" height="260"> <param name="src" value="http://www.sarahsnotecards.com/catalunyalive/ » fishstore.wmv" /> <param name="autostart" value="true" /> <param name="controller" value="true" /> </object> And it works. Personally, I consider this pretty experimental, or at the very least sacrilegious… embedding a Windows Media Player movie without a classid! (What’s next? Valid documents with no DOCTYPE?) I tested this simple example in IE5.5, IE6, IE7, Opera Win/Mac, Firefox Win/Mac, and Safari and it worked just fine. That said, I don’t do a lot of scripting or Microsoft stuff, so your mileage may vary. (Note: Of course, there are many more param elements that you may wish to use.) Embedding QuickTime movies without embed Unfortunately, I’m still pretty sure there’s no type that would convince IE to open a QuickTime movie without an ActiveX control. The obvious choices, type="video/quicktime" or even type="application/x-quicktime", only work on standards-loving browsers. So I went a different route. Some basic premises This technique is based on a couple of premises:
Embedding QuickTime for Internet Explorer I’m going to use QuickTime for my example, but you can use the same technique with Windows Media Player movies with the classid attribute, as I’ll show you a bit farther along. To insert a basic QuickTime movie in Internet Explorer, we’ll use something like this (Line wraps marked » —Ed.): <object classid="clsid:02BF25D5-8C17-4B23-BC80 » -D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="320" height="256"> <param name="src" value="http://www.sarahsnotecards.com/catalunyalive/ » diables.mov" /> <param name="controller" value="true" /> <param name="autoplay" value="false" /> </object> Don’t forget the height or the width or that horrendous classid which calls the QuickTime ActiveX control. Note that the param element that specifies the URI of the movie has a name attribute of “src,” not “url” or “movie.” You can preview the effect here. In IE, you’ll see a movie, in other browsers you won’t see a thing. Embedding QuickTime movies for everyone else Although standards-loving browsers can’t deal with that object since the classid attribute is that awful number instead of a URL, they will keep looking to see if there’s any nested objects they can deal with. So, just before the closing </object> tag, we’ll use a standard implementation of the object element (Line wraps marked » —Ed.): <object classid="clsid:02BF25D5-8C17-4B23-BC80- » D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="320" height="256"> <param name="src" value="http://www.sarahsnotecards.com/catalunyalive/ » diables.mov" /> <param name="controller" value="true" /> <param name="autoplay" value="false" /> <object type="video/quicktime" data="http://www.sarahsnotecards.com/catalunyalive/ » diables.mov" width="320" height="256"> <param name="autoplay" value="false" /> <param name="controller" value="true" /> </object> </object> The width and height are required, as is the type. If you view this combination in a standards-loving browser, it looks great, if a bit loud. IE 6 (and earlier), as we mentioned before, can’t quite decide what to do with the second object and basically botches it with a ghostly apparition. What IE can’t see, it can’t mess up Although IE’s conditional comments were designed to be used for the rather questionable purpose of serving it special code that is hidden from other browsers, we’ll use them here to hide code from IE but not from other browsers. (It’s a bit of a slap in the face—though not really that surprising—that Microsoft has the nerve to refer to these other browsers as “downlevel”.) Comments written with Microsoft’s “original syntax” don’t validate (surprise) but thankfully, Lachlan Hunt figured out a way to adjust them so that they do. So we need to hide the second object from IE with its own commenting system. Insert <!--[if !IE]>--> in front of the second <object> tag and <!--<![endif]--> right after the first closing </object> tag. (Line wraps marked » —Ed.) <object classid="clsid:02BF25D5-8C17-4B23-BC80- » D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="320" height="260"> <param name="src" value="http://www.sarahsnotecards.com/catalunyalive/ » diables.mov" /> <param name="controller" value="true" /> <param name="autoplay" value="false" /> <!--[if !IE]>--> <object type="video/quicktime" data="http://www.sarahsnotecards.com/catalunyalive/ » diables.mov" width="320" height="260"> <param name="autoplay" value="false" /> <param name="controller" value="true" /> </object> <!--<![endif]--> </object> Now it’s beautiful! What’s more you can use the whole collection of parameters with the object element as described on Apple’s Developers site. Next time, I’ll test with a slightly less raucous movie. The details for Windows Media Player If you’d rather embed Windows Media Player files with the classid and not in the one-object method I demonstrate near the beginning of this article, the code is only slightly different. For the classid in the initial object tag, use classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6". To specify the URL of your Windows Media Player movie, use a param element with a name attribute equal to “url” for most browsers and then repeat the value using a name attribute equal to “src” for Safari. Then in the second, standards-compliant implementation of the object, use the same code as in the one-object method. Here’s an example (Line wraps marked » —Ed.): <object classid="CLSID:6BF52A52-394A-11d3-B153- » 00C04F79FAA6" id="player" width="320" height="260"> <param name="url" value="http://www.sarahsnotecards.com/catalunyalive » /fishstore.wmv" /> <param name="src" value="http://www.sarahsnotecards.com/catalunyalive » /fishstore.wmv" /> <param name="showcontrols" value="true" /> <param name="autostart" value="true" /> <!--[if !IE]>--> <object type="video/x-ms-wmv" data="http://www.sarahsnotecards.com/catalunyalive » /fishstore.wmv" width="320" height="260"> <param name="src" value="http://www.sarahsnotecards.com/ » catalunyalive/fishstore.wmv" /> <param name="autostart" value="true" /> <param name="controller" value="true" /> </object> <!--<![endif]--> </object> A small wrinkle, or, what’s left to do As of January 2006, Apple started promoting the use of JavaScript to call movies for web pages so that users wouldn’t have to click on ActiveX controls in order to activate them. It’s a long, convoluted story that began with a lawsuit against Microsoft and ended up making life difficult for the rest of us. At any rate, the methods described above work almost perfectly without any JavaScript at all, with one caveat: QuickTime movies won’t autoplay in IE. I’m not sure I’d even want the example video to autoplay! Nevertheless, I find it highly suspicious that Windows Media Player files load in the background and autoplay without any interaction while QuickTime movies show just the initial frame while the audio plays, but no moving pictures are shown. At any rate, I want to see how the activating ActiveX controls issue plays out before I implement what I consider a rather laborious JavaScript solution to my whole site. I use very little JavaScript and like to keep it that way. Whether you go the JavaScript route or not is actually irrelevant to the article at hand. Either way, you can still eschew the embed tag for the standard object element. I would have liked to figure out a way to hide the inner objects only from IE 6 and earlier, since IE 7 (at least in beta 2) seems to be handling nested object elements properly, but I was unsuccessful. While there is a conditional comment that would allow such a thing (<!--[if gte IE 7]>-->), the extra characters (-->) that Lachlan offered to make the thing validate are visible with IE7 (as they should be logically). Any ideas? On the shoulders of giants Other people have also worked on this problem. This article agreed that two nested object elements should work but relied on what I consider rather complicated CSS to hide the second object. Ian Hickson used the IE comments to hide a second object from IE that had Flash content. And the aforementioned Lachlan Hunt figured out how to write valid Internet Explorer conditional comments that hide content from IE while revealing it to other browsers </object> If the browser doesn’t know how to play objects with a MIME type of application/x-shockwave-flash, it will simply go for the next child element and give that a try. I’m guessing that a simple image element should be okay for most people. Failing that, you can simply use text. Work in progress I’ve written this article with the knowledge that it’s simply one man’s findings and thus a work in progress. Consider it like a scientific theory: what I state today is only proven until it’s disproved. Third Audio: Audio In this example, an .mp3 file is being played: <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="200" height="16"> <param name="src" value="audio.mp3" /> <param name="autoplay" value="true" /> <param name="pluginspage" value="http://www.apple.com/quicktime/download/" /> <param name="controller" value="true" /> <!--[if !IE]> <--> <object data="audio.mp3" width="200" height="16" type="video/quicktime"> <param name="pluginurl" value="http://www.apple.com/quicktime/download/" /> <param name="controller" value="true" /> </object> <!--> <![endif]--> </object> |
|
|
|