I ran into a problem today that had me scratching my head for a bit. Suppose you have a large flash project that loads a number of external SWFs. Suppose furthermore that several of those SWFs, as part of their default behavior, instantiate display objects from within their own libraries. Let’s get more specific.

Take this example. Map.swf has a symbol in its library (a Bitmap) exported as “MarkIcon.” If in the constructor I add the following code…


public function Map() {

addChild(new Bitmap(new MarkIcon(50, 50)));

}

…my SWF has no problem correctly displaying its image. Pardon the awful graphics. This is for demonstration purposes only.

What happens when I later try to load this simple SWF into another SWF?

We get a compilation error of course. This sounds like a big problem, doesn’t it? What could we possibly do to fix this? We instantiate via the child SWFs applicationDomain property. Huh?


public function Map() {

var miDef:Class = this.loaderInfo.applicationDomain.getDefinition("MarkIcon") as Class;

addChild(new Bitmap(new miDef(50, 50) ));

}

Now it works everywhere. This same technique can also be used to instantiate the class from within the parent SWF. How’s that for fancy?

Categories: Actionscript 3ArticleTipsTutorial
Published: 08.10.10 :: No Comments »


I’d like to take a moment to draw your attention to a very useful class that’s been around for some time, but that I’ve never really bothered to use: flash.system.Capabilities. It gives you all kinds of useful information about the environment your SWF currently resides in. I’ve got an example below.

The SWF above (with any luck) should tell you whether or not you’re running a debug version of flashplayer, who the manufacturer of your flash plugin is, what operating system you’re running, what player type you’re using (should be plugin on this page), and what version of the flash player you’re running.

If you download the files for this demo here and run the SWF on your local machine, you should see a different value in the player type field.

The player type is the most useful piece of information to me. In theory you could use it to load different data or behave differently in general depending on whether you’re viewing your SWF in the Flash IDE or on a webpage, without having to add your own obnoxious boolean “debug” flags.

Categories: APIActionscript 3ArticleDocumentationDownloadsFlashTips
Tags:
Published: 08.05.10 :: No Comments »


Today, as happens once in a blue moon, I was presented with a stack of flash banner ads along with a request that they be squeezed under a 50k file size limit. If you’ve ever worked on banner ads you’re probably familiar with these sorts of limitations, as well as those placed on duration and the use of rich media. You may also be aware of how frustrating and difficult a task it can be to squeeze banners, with all the aesthetic demands placed on them, under these arbitrary size thresholds.

After several years of dealing with these issues, I’ve come up with an array of tips and guidelines for reaching the file sizes that ad networks demand. Some techniques are more effective than others. Many of them may compromise the aesthetic integrity of the files you’re working with so it’s best to use a mixture of these strategies to suit your needs.

I’ve prepared a sample banner in a standard size (300×250) to use as an example. You can download the initial source files by clicking here.

We have what seems to be a very simple banner animation. Several pieces of text fade or slide into view, and bubbles are dynamically placed on the stage and flown from right to left. A number of different fonts are used (all variations of HelveticaNeue) and the image in the background is crisp and clear. It may not seem like it’s very complicated, but this SWF is actually 1.6mb. How can that be the case, and how can we fix it? Let’s look at a couple things we can change.

1. Embedded Fonts

The most significant factor contributing to the file size of this SWF right now is the large number of embedded characters. If we browse through the assets being used in the SWF, we can come up with a list of the following fonts being used:

  1. Helvetica Neue LT Std 95 Black
  2. Helvetica Neue LT Std 67 Medium Condensed Oblique
  3. Helvetica Neue LT Std 77 Bold Condensed
  4. Helvetica Neue LT Std 87 Heavy Condensed
  5. Helvetica Neue LT Std 97 Black Condensed
  6. Helvetica Neue LT Std 107 Extra Black Condensed
  7. Helvetica Neue LT Std 73 Bold Extended

This may seem like a large number of fonts, but it’s not uncommon to receive compositions that use at least this many. This in itself, though, is not necessarily a problem. Where things get messy is when we look at how the fonts are embedded.

In the case of our original file, we’re embedding every character in every font we’re using. If you look at the screenshot above, that’s almost 100,00 characters per font, or nearly 700,000 characters total. Most of the characters we’re embedding are entirely unnecessary. How can we resolve this issue? There are three ways.

  1. Embed a smaller subset of the font. I generally use the following.
  2. Embed only the characters being used within each text field. This is a fine option for fields that won’t be changing. You can accomplish this by first clicking “Don’t Embed” to clear any groups you’ve already included, and then clicking “Auto Fill.”
  3. Make your text fields static. Generally this works well, although sometimes static text renders in unpredictable ways. This is also roughly equivalent to option 2.

After going through the source file and correcting every dynamic text field (using option 2), our 1.6mb SWF is down to a sweet and slim 36kb.

2. Image Compression

Another way we can influence file size is by toying with the JPEG compression settings for our SWF. By default, Flash embeds bitmaps at 80% of their original quality. Most of the developers I know rarely if ever tweak this setting, and in most cases it’s not necessary to, but if you’re willing to toy around the the figures you can squeeze a few more kb out of your SWF quite easily.

You can modify image compression in two ways.

  1. Modify the global compression settings for your SWF. You can find this control in the publish settings panel under the “Flash” tab.
  2. Modify the compression settings for individual images. When it comes to fine tuning your application, this is a better way to go. You can access this menu by selecting a bitmap in the library panel, right clicking, and selecting “Properties.”

This method is far from flawless, and the results are often hard to predict. In the case of the SWF we’re working with above, I’ve created a demo showing what the platypus photo in the background looks like at various compression levels. Click and drag the slider to adjust the quality of the image (displayed in the field next to the slider).

You probably can’t even see a difference before getting down below 70. From there to 40 the changes are subtle, and they become more noticeable with each step from 30 down. Obviously you have to know where to draw the line when you’re sacrificing image quality for filesize, though in the example above I would be willing to go perhaps as low as 20 if the need were great enough.

In our original SWF, setting the JPEG quality to 20 brought our filesize down from 36kb (after modifying our fonts) to a tiny 24kb.

3. External Libraries

Depending on what you’re trying to accomplish in your banner, you may require external libraries for animation or data connectivity. It’s easy to forget that including these libraries can add to the overall file size of your published SWF.

In our sample SWF we’re using the TweenLite library to animate bubbles across the screen and to remove them when they’ve cleared the left edge. TweenLite is a wonderful library, and it’s already quite small, but you may not be aware that there is a smaller version of TweenLite available called TweenNano. TweenNano is packaged with TweenLite, and unless you intend to do something highly complex it has all the same basic functionality.

The code in our original file for animating bubbles looks like this.

//
TweenLite.to(bubble, Math.random()*10, { _x: -150, ease: Expo.easeOut, onComplete: killBubb, onCompleteParams: [bubble] });
//

To switch over to TweenNano, all we have to do is change the name of the static class we’re referring to, like so:

//
TweenNano.to(bubble, Math.random()*10, { _x: -150, ease: Expo.easeOut, onComplete: killBubb, onCompleteParams: [bubble] });
//

Switching the code in our application from TweenLite to TweenNano brought our file size down from 24kb to a miniscule 20kb.

4. Flash Player Version

The final fix I would recommend for our sample file requires an awareness of the environment you’re publishing to and the needs and capabilities of your project. While it may seem at first that it’s best to publish to the latest version of FlashPlayer, if your application isn’t taking advantage of newer features it may be in your best interests to hang back with an earlier version.

Our original application, after all the cuts we’ve already made, was clocking in at 20kb published for Flash Player 8. If we publish to Flash Player 7, we reduce the filesize even further down to an insane 16kb!

What do we lose for the bargain? In this case, the ability to specify anti-aliasing methods for our text fields. Because this animation is simple, and nothing dramatic happens with text, we can part with those capabilities quite comfortably.

Of course, there are trade offs here as well. You may think that it’s better to publish to Flash Player 9 than 10 if your project doesn’t require features like native 3D support, but perhaps you could achieve some performance benefit by replacing your Arrays with Vectors?

Which version of Flash Player you choose to publish to will depend on your unique needs, but it’s worthwhile to remember that the latest is not necessarily the greatest.

Conclusion

After applying the above techniques to our original swf with a filesize of 1.6mb, we were able to reduce it to only 16kb. That’s a 99% reduction, and it’s sure to make clients and advertising networks happy. The new, shrunken files, can be found by following this link.

Keep these tips in mind and let me know if you have any other tricks for putting the squeeze on bloated SWFs.

Categories: Actionscript 2AdvertisingArticleDownloadsTipsTutorial
Published: 05.21.10 :: 1 Comment »


Most of the problems I tackle as a Flash Developer are logical/programmatic challenges, however on occasion a project presents me with aesthetic demands that require alternative approaches. That is to say (and I may not admit to this later), not all problems are best solved with code.

The circular preloader is a classic example. Now let’s be clear that I’m not talking about a segmented ring, a la Youtube.

In fact, these are relatively easy to create. The preloader in YouTube’s player could be recreated in 8 frames. I’m talking about a ring that fills in the same manner as a standard progress bar. These animations have been around for as long as people have been preloading content in Flash, so it shouldn’t be difficult. Right?

The problem is that Flash doesn’t offer any good tools for animating circular fills. The Oval Primitive tool seems like it would solve this problem at first glance, but try applying a shape tween to one and you’ll see why it’s not appropriate. The only reliable way to accomplish the effect is to animate a mask, by hand, using the brush tool, around the outside of your ring.

There are two big problems with this method:

  1. It’s very time consuming.
  2. It’s difficult to make sure that the bar grows at a consistent rate.

Unfortunately, this is mostly as good as it gets. I’ve worked at devising code-based solutions to this problem in the past (and I will again in the future) with limited success.

Because I expect that you, like me, will turn to the timeline next time you’re asked to produce one of these preloaders, I’ve gone ahead and created some assets that should (hopefully) give your efforts a kick start. Consider the demo below:

The animated ring in the center is a 360 frame animated mask (1 frame per degree!) constructed using the Oval Primitive tool. I know that I previously said that you can’t effectively tween an Oval Primitive in the way we need, and that remains true. This animation is done frame-by-frame. Yes, I really sat here and created a single keyframe for every degree in a 360 degree fill.

These are all vector graphics, so you can scale/rotate to your heart’s content without worrying about losing quality. My recommendation on how to use the animation goes something like this:


// Assuming your preloader is named "preloader"

function updatePreloader(progress:Number):void {

preloader.gotoAndStop(Math.round(progress*360));

}

You can get a feel for how this all works by checking out the source files. Let me know if these are any help to you, and if so I’ll try to provide more assets in the future to solve other common problems.

Categories: AnimationArticleDownloadsTips
Published: 05.18.10 :: 1 Comment »


A Runtime Error

Perhaps you’re familiar with this image. How embarassing to launch an app only to find that it’s throwing up large, intrusive error windows!

What’s to be done? Well, you have two options:
  1. Write perfect code.
  2. Use Runtime Error Handling

Some day I’ll elaborate on the secrets of the first option(1, 2), but for the time being I’d like to talk about Runtime Error Correction and Handling.

Let me begin by explaining what a runtime error is. As compared to a Compile Error, which is caught on compilation, or a Logical Error, which is due to fuzzy logic on the part of the programmer, a Runtime Error is an error that occurrs in your code while it is executing.

Flash has several types of Runtime errors that are thrown at different times depending on the type of error that occurrs. As somebody who works with Flash every day, I can say with some confidence that the most important and common ones for you to worry about are TypeErrors, ReferenceErrors, and RangeErrors. You may also find yourself occasionally encountering SecurityErrors and SyntaxErrors, but for now we’ll just worry about the first three.

How do these errors occur? Let’s break it down one by one.

TypeErrors

Type errors generally occur when you improperly coerce the value of one variable to the type of some incompatible “other” variable. What does this mean? Here’s an example:

var mov = getChildByName("myMovieClip");
mov.gotoAndPlay(2);

The code above will throw an error because you’re implicitly (rather than explicitly) trying to coerce a DisplayObject into behaving like a MovieClip. What the hell am I talking about? Well, if you check the documentation for the “getChildByName” method on the MovieClip class, you’ll see that it returns a DisplayObject. What this means is that whenever you call this method without explicitly casting its return object, Flash is going to assume you’re just talking about a vanilla, plain-jane DisplayObject.

Here are two solutions:

var mov = getChildByName("myMovieClip") as MovieClip;

…or…

var mov = MovieClip(getChildByName("myMovieClip"));

Both lines of code do the same thing. For the sake of readability, I prefer the first method.

ReferenceErrors

Reference Errors occur when you try to access or set a property that doesn’t exist on a non-dynamic class. For people who are new to object oriented programming in AS3, this will happen for a while until you really appreciate the difference between a dynamic and a non-dynamic class. Let’s look at an example.

package {
     public class Foo() {
          public function Foo() {
               trace(this.bar);
          }
     }
}

The example above will throw a Reference Error because the class Foo doesn’t have a property named “bar.” I have two solutions.


package {
public class Foo() {
     public var bar:*;
          public function Foo() {
               trace(this.bar);
          }
     }
}

In the above example, we just made sure that the public class Foo does have a property named “bar.”

package {
     public dynamic class Foo() {
          public function Foo() {
               trace(this.bar);
          }
     }
}

In this second example, we made the public class Foo into a dynamic class. What this means is that we can refer to any property we want on Foo, and if it doesn’t exist Flash will create it for us automatically. This may sound like a very tempting proposition, but the first approach is most definitely preferred on this one, which is a point I will explain at a later date. For the time being, just take my word for it: Avoid making your classes dynamic if you can.

RangeErrors

A Range Error occurs when you attempt to refer to an index that doesn’t exist in an Array. For example:

var shitty_bands:Array = [ "Slipknot", "Linkin Park", "Insane Clown Posse"];
trace(shitty_bands[3]);

The code above will generate a range error because the shitty_bands array doesn’t have any entries at an index of 3. You’ve literally referred to an entry that is out of the range of the array, making this a pretty easy error to remember. To solve, you could…

var shitty_bands:Array = [ "Slipknot", "Linkin Park", "Insane Clown  Posse"];
trace(shitty_bands[shitty_bands.length-1]);

…use properties of the array to make sure that you don’t refer to entries outside of its range, which also saves you the trouble of actually needing to know the number of entries in the array at any given point (assuming you were just trying to grab the last item in the array), or you could…

var shitty_bands:Array = [ "Slipknot", "Linkin Park", "Insane Clown  Posse", "The Black Eyed Peas"];
trace(shitty_bands[3]);

…just add another shitty band to the array.

Admittedly, these are stop-gap solutions that all depend on what you’re actually trying to accomplish with your program. There is one final solution.

Explicit Error Handling

What do I mean by Explicit Error Handling? I mean that you anticipate when portions of your code may throw errors, and set up appropriate control structures to deal with them when they happen. There are two ways to do this, and the method you choose may vary depending on the type of error you anticipate and the amount of code you’re trying to control for. Let’s consider the first method.

Error Event Listeners

Many errors can be taken care of with simple event handlers. Security Errors and IOErrors, for example, have their own event classes that you can listen for.


package {

     import flash.net.*;

     import flash.events.*;

     public class Foo() {

          public function Foo() {

               var loader:URLLoader = new URLLoader();

               loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityErrorHandle, false, 0, true);

               loader.addEventListener(IOErrorEvent.IO_ERROR, _ioErrorHandle, false, 0, true);

               loader.load(new URLRequest("data.xml"));

          }

     }

     private function _securityErrorHandle(e:SecurityErrorEvent):void {

          trace("SecurityError :: ",e.errorID);

     }

     private function _ioErrorHandle(e:IOErrorEvent):void {

          trace("IOError ::",e.errorID);

     }

}

Depending on how large or complex your application is this may be a good solution for you. I know that in some respects I find this easiest to understand as it runs on the existing Event metaphor that I’m accustomed to using for everything else in AS3.

The second method employs a construct which with, if you have done any programming in the past, you are probably familiar.

package {
     public class Foo() {
          public function Foo() {
               try {
                    trace(this.bar);
               } catch (e:ReferenceError {
                    trace("Reference Error!");
               } finally {
                    // do something else
               }
          }
     }
}

The Try…Catch…Finally construct exists in pretty much every programming language known to man. It’s also pretty simple to understand. The application “attempts” to do whatever is within the “try” statement. If an error occurs, it’s handled in the “catch” statement, and whatever was going to take place in the “try” statement just doesn’t happen. After these steps, the application does whatever is indicated in the “finally” statement. It doesn’t get much easier than that. This is also nice because it forces you to deal with errors at the site of their creation, and to be more thoughtful about where and why errors happen.

Categories: Actionscript 3ArticleBest PracticesFlashFlexTipsTutorial
Published: 03.31.10 :: No Comments »


Gesture Recognition

I’ve spent the last day or two reacquainting myself with what’s been done to achieve reliable gesture recognition in AS3. I have reviews of two different packages I tried, one of which is relatively new and one of which has been around for some time.

One note about all of the gesture recognition classes I’ve looked at is that they are direction-dependent. That is to say that if you’re attempting to capture the gesture corresponding to a vertical line, a stroke from top to bottom is not the same thing as a stroke from bottom to top. Furthermore, neither of those will necessarily be captured in a stroke from top to bottom to top. This all has to do with the algorithms being employed to detect gestures and attempts to make them run as efficiently as possible.

The first package I looked at was offered up by a Mr. Felix at bertiesbraum.de. Felix’s gesture recognizer consists of AS3 implementations of the “$1 Gesture Recognizer” and “ShortStraw Corner Finder” algorithms, which he has the decency to cite and link to (unlike me).

His post does a much better job of explaining basic usage of the classes than I care to at the moment, but what I will say is that I was unable to get the classes to function without false positives. This is likely because, as Felix notes, “The gestures are also rotation, position and scale invariant,” which is to say that a single stroke probably ends up being a single stroke, regardless of which direction it points. With more complex figures I was able, in the sample application Felix provides, to demonstrate direction dependence. In my case I’m trying to detect single strokes in distinct directions, and so it may be that these algorithms are over-engineered for my purposes.

The second package I looked into was posted in a short article at ByteArray.org by Didier Brun. I caught this post when it first came out (almost three years ago) and was very impressed with the concept but didn’t have any real use for it at the time. I toyed with it today and have been pleased with the results.

Initially Mr. Brun’s classes posed the same problem that most gesture recognition algorithms do: it was unable to recognize identical patterns if they proceeded in different directions. Additionally, all of the packages I’ve seen presume that the user will begin their gesture by pressing the mouse button down, and end the gesture by releasing it. I’m trying to detect whether or  not a user is shaking an object they’ve picked up in an up-and-down fashion, so it’s important to me to recognize sub-gestures within a larger “gesture.” If I depend solely on button presses and releases, the gesture that ends up being analyzed consists of tens of motions at the least.

I came up with a solution using Mr. Brun’s classes that allowed me to achieve my ends. Brun’s gesture recognition class offers a custom event that fires when capture begins and ends, when a match is made or not made, and while capture is taking place. The last of those was most important to me. I added a public property to his existing GestureEvent class. The modified class looks like this:

package com.foxaweb.ui.gesture {

	import flash.events.Event;

	public class GestureEvent extends Event {

		// ------------------------------------------------
		//
		// ---o static
		//
		// ------------------------------------------------

		public static const START_CAPTURE:String="startCapture";
		public static const STOP_CAPTURE:String="stopCapture";
		public static const CAPTURING:String="capturing";
		public static const GESTURE_MATCH:String="gestureMatch";
		public static const NO_MATCH:String="noMatch";

		// ------------------------------------------------
		//
		// ---o properties
		//
		// ------------------------------------------------

		public var datas:*;
		public var fiability:uint;
		public var moves:String;

		// ------------------------------------------------
		//
		// ---o constructor
		//
		// ------------------------------------------------

		public function GestureEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false){
			super (type,bubbles,cancelable);
		}

		// ------------------------------------------------
		//
		// ---o methods
		//
		// ------------------------------------------------

		public override function clone():Event{
			return new GestureEvent(type, bubbles, cancelable) as Event;
		}

	}
}

I also made a change to the MouseGesture class to make sure that “moves” were being attached to GestureEvents dispatched during the “CAPTURING” phase. The modified function looks like this:

protected function captureHandler(e:TimerEvent):void{

	// calcul dif
	var msx:int=mouseZone.mouseX;
	var msy:int=mouseZone.mouseY;

	var difx:int=msx-lastPoint.x;
	var dify:int=msy-lastPoint.y;
	var sqDist:Number=difx*difx+dify*dify;
	var sqPrec:Number=DEFAULT_PRECISION*DEFAULT_PRECISION;

	if (sqDist>sqPrec){
		points.push(new Point(msx,msy));
		addMove(difx,dify);
		lastPoint.x=msx;
		lastPoint.y=msy;

		if (msx<rect.minx)rect.minx=msx;
		if (msx>rect.maxx)rect.maxx=msx;
		if (msy<rect.miny)rect.miny=msy;
		if (msy>rect.maxy)rect.maxy=msy;
	}
	// event
	var evt:GestureEvent = new GestureEvent(GestureEvent.CAPTURING);
	evt.moves = moves.join("");
	dispatchEvent(evt);

	//dispatchEvent (new GestureEvent(GestureEvent.CAPTURING));

}

The final step was to deal with the entire set of move data in my application. I configured my instance of the MouseGesture class to handle GestureEvent.CAPTURING events and created the following function to deal with them.

private function _captureHandler(e:GestureEvent):void {
	var reShake:RegExp = /(62|26)/g;
	var shakes:int = e.moves.match(reShake).length;
	field_shakes.text = "Number of Shakes: " + shakes;
	if (shakes >= 12) {
		stage.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));
		field_shakes.text = "Congratulations!";
	}
	trace(e.moves);
}

The important thing to note here is the regular expression being used. The strings “62″ and “26″ correspond to the output that would be expected from a vertical shake gesture in the MouseGesture class (respectively “up->down” and “down->up”). What the function does is scan the entire list of movements and look for instances in which the patterns I’m trying to match have occurred in sequence. For each occurrence of either pairing, we know that the user has successfully “shaken” the can. A single call fired to the “_captureHandler” function might have a “moves” list that looks like this…

0666662255222666666222566222266222266672226666122561

…in which each digit corresponds to one of 8 possible directions the user moved his mouse. If you count carefully, you’ll find 8 instances of either the sequence “62″ or the sequence “26.”

Ultimately Mr. Brun’s class ended up being more useful for the project that I’m working on, but I hope to see other implementations in the future that will allow for more complex gestures to be recognized.

Published: 03.11.10 :: No Comments »


If you’ve been reading things around here recently, you may recall that I posted an entry filled with glowing praise for RichFLV. I had been aware of the application for some time (it was one of the first AIR apps I saw receiving significant praise/attention), but had only started using it several weeks prior in my own development efforts.

In the time since then, my company began making heavy use of RichFLV for a large project I’ve been developing. The project required tons of external video and animation, and I had decided that the best way to synchronize the two was to use FLV embedded cuepoints as controllers for external SWF content (FLV, SWF, cuepoint -> frame label). Because of the volume of video we’ve been dealing with (around 2gb), the idea of being able to dynamically modify cuepoints without having to rebuild video seemed like an obvious win for us.

To say the least, there have been complications. I have three complaints with RichFLV at this point. One of them is a minor inconvenience and the other two are potential deal breakers.


Really? No Native Drag and Drop?



The first problem is quite simple and amounts to more of an inattention to detail than anything. RichFLV doesn’t support native drag and drop for playing video files. It may sound like I’m nitpicking, but when you’re dealing with several hundred video files buried in a complex folder structure, having to go to the “file -> open” dialogue to change files becomes a quick annoyance.


Cuepoint Confusion?



The second problem is that, once in a while, RichFLV completely screws up your cuepoints. On the one hand, it will often duplicate cuepoints at incorrect time codes (see cue12, appearing twice, the first of which has the same timecode as cue 11), and on the other hand it frequently refuses to designate cuepoints correctly as event or navigation points (see the final cue12). Generally we give our cuepoints distinct, meaningful names so that when they fire we can respond to them intelligently. It’s easy to see how the problems highlighted above prevent that.


Funky Metadata?



The final problem has to do with the metadata that RichFLV generates. There’s a little bit of backstory required for this one.

At the same time that this project was starting, I and my colleagues had taken an interest in the Open Source Media Framework and had planned to build a new video player around it to use with projects in the future. The inclusion, specifically, of Parallel and Serial media elements built into OSMF seemed like a great fit for the needs of this project. We decided to proceed with development of our video player and to deploy it in this project as it reached a usable state.

It didn’t take long before we were having major problems (with our Video Player!). We were consistently unable to get the OSMF to play videos with embedded cuepoints, even though we’d seen plenty of examples of it doing just that. The specific error we were receiving was as follows:

Error #2044: Unhandled AsyncErrorEvent:. text=Error #2095: org.osmf.net.dynamicstreaming.DynamicNetStream was unable to invoke callback onMetaData. error=TypeError: Error #1034: Type Coercion failed: cannot convert Object@3ca86769 to Array.

You’ll notice that the framework was unable to correctly invoke it’s “onMetaData” handler. Generally when you deploy video in Flash, you first wait for metadata to be made available so you can scan it for important information about the file, and for information about cuepoints. When attempting to playback FLV files in which cuepoints had been embedded with RichFLV, we received this error every single time. In fact, it didn’t even matter if we went back and stripped all of the cuepoints from the video. Once RichFLV touched the metadata, the video was effectively “broken.” We struggled with this error for days before eventually dropping the idea of moving forward with OSMF. Instead we had to fall back on another (self-created but very outdated) video player to complete the project.

Now, I have little (if any) experience with generating or encoding video, but I was so frustrated by all of this that I spent some time today digging  through the flv file format specification. The first thing I noticed was that RichFLV was providing incorrect values for the CodecID property of the FLV file format (specifically 4 for On2 VP6 rather than 5 for On2VP6 with alpha). Furthermore, I discovered that if I reencoded my FLVs using Adobe Media Encoder (which should understand the FLV format) rather than RichFLV, all of my problems disappeared. Go figure.

None of the above is necessarily meant to dissuade you from using RichFLV if you find it useful. As far as I can tell, the original developer hasn’t released a new version of it in well over a year, and this thing has been around since AIR was still called Apollo. Hopefully these bugs will get more public attention and the developer will be prompted to update the app or disseminate the source code so somebody else can pick up development on what otherwise has been a great and useful application.

Categories: ArticleBugsFLVTipsVideo
Tags:
Published: 03.01.10 :: 4 Comments »


So, I thought I’d bring attention to a strange inconsistency I run into on a very regular basis while developing applications in Adobe Flash.

Much of the work that I do in flash has to do with displaying and managing video. To date, I have probably created at least 50 different playlist enabled video players, by which I mean video players with a list of either links, thumbnails, or both that allow you to play other videos in the same container without leaving the page. For example, something like this…


A Generic Video Player


…with a playlist that allows you to select other videos, like this…


Video Player with Playlist


This is all well and good. Because I try to build in a way that’s generalized for client accessibility and ease-of-use (and because I don’t want to be solely responsible for updating these things myself), the standard way to go about creating something like this would be to have an external XML document that contains all of the information required to build the playlist. The application is responsible for loading that document and extracting that information from it, which it uses to build a clickable, interactive playlist. This is all quite simple. The XML could look something like this:

<playlist>
	<item>
		<uid>1</uid>
		<title>Video 1</title>
		<video>PATH TO VIDEO</video>
		<thumbnail>Image for video</thumbnail>
	</item>
	<item>
		<uid>2</uid>
		<title>Video 2</title>
		<video>PATH TO VIDEO</video>
		<thumbnail>Image for video</thumbnail>
	</item>
	<!-- and on, and on, and on -->
</playlist>

The folder structure for such an application could (and would) conceivably look like this:


FLA Folder



Within our document root, we have an FLA folder to hold our source files.

FLV Folder



We have an FLV folder for holding video assets.

SWF Folder



We have a SWF folder for holding all of our compiled application SWFs.

XML Folder



And finally we have an XML folder for holding any XML documents we’ll be loading in the application. The index file resides in the document root.

Here’s where things get screwy.

In my application, when I’m ready to load my external XML in order to build a playlist, my code will look like this:

var req:URLRequest = new URLRequest("xml/playlist.xml");
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, _playlistHandle, false, 0, true);
loader.load(req);

After I’ve loaded my playlist, suppose I want to play the first video. For the sake of brevity, we will suppose that I have an instance of a video player class that will allow me to simply pass the path to the FLV in to begin playing it, and that it’s already been instantiated and configured under the name “_player.”

function _playlistHandle(e:Event):void {
	var loader:URLLoader = e.target as URLLoader;
	var xml:XML = XML(loader.data);
	_player.play(xml.item.video[0].toString());
}

What do you suppose the path to my video is going to be, within my xml doc? If you look above, you’ll see I loaded the xml from the document root, and it would be natural for you to assume that the path to the first video is “flv/video.flv.” In this instance, you would be incorrect.

The correct path to the video file would be “../flv/video.flv.” Why is this? The relative path to an asset, in flash, varies according to what type of asset it is you’re accessing. In the case of XML you load your file from the location in which the SWF file is running, which in our example is the document root. When you’re loading video, however, you have to load your file from the physical location of the swf, not from where it’s running. In our example, that means our video file must be loaded as if the application is running from within our “swf” subfolder.

Why is this the case? I honestly have no idea. I can only imagine that in some obtuse way it’s meant to protect video content from being exploited by external domains or malicious third parties, though I can’t see exactly how.

Hopefully if you find yourself developing such an application, and you can’t figure out why the paths to your videos won’t resolve correctly, you’ll remember reading about the issue here. If anyone has a good explanation for why this is the case, I’d also be very curious to be informed.

Categories: ArticleBugsDocumentationFlashTips
Tags:
Published: 02.26.10 :: No Comments »


I’ve decided that in addition to posting code samples, applications, and packages for download I would also engage in trying to promote practices that I find helpful in making writing AS3 easier in the long run. What do I mean when I say these tips will make things easier? I mean that as you continue to work with code you’ve written, especially within larger projects, you should find it less difficult to track down bugs, interpret code you may not have looked at for some time, and share code with other developers.

The first tip has to do with namespaces and scope. If you’re at all familiar with object oriented programming and writing classes in AS3, you know that within a class you can declare variables to hold important data that are unique to each instance of the class. The built in namespaces available for these variables are public, private, and internal.

Today I’ll be discussing the public and private namespaces, and how you should use them when considering how an instance of your class will be used throughout your application.

For the purposes of making myself clear, suppose we’re tasked with creating a class intended to represent a person:

package {
     public class Person {
          public function Person() {}
     }
}

A “Person” may have a number of characteristics we’d like to keep track of. For example, we may want each “Person” to be aware of his name, age, and gender. We can declare these values as members of each instance of the class by placing variable declarations within the brackets corresponding to the class definition. The question I intend to answer today is whether we should declare these values as public or private.

If you intend to pass instances of your Person class around your application, and you intend to retrieve the values stored within, it may seem that the simplest thing to do is to declare your class variables as public.

package {
     public class Person {
          public var name:String;
          public var age:int;
          public var gender:String;

          public function Person() {}
     }
}

This may seem like a good idea, as in the future you may want to access a person’s name like so:

var guy:Person = new Person();
guy.name = "franz";
trace(guy.name) // output: franz

However, suppose you have a large number of people you need to represent. Furthermore, suppose these people have their values extracted and used in a large number of places throughout your code. Furthermore, suppose after you’ve done the leg work of getting most of your application ready, it occurs to you, for whatever reason, that a person’s name should be in all capital letters. Now, you could track down every declaration of a person and replace the name with capitalized text…

var guy:Person = new Person();
guy.name = "FRANZ"
trace(guy.name); // output FRANZ

…or you could find every instance in which you want to output a name and do the following…

trace(guy.name.toUpperCase()) // output: FRANZ

…or you could have saved yourself a lot of time and trouble by doing things right in the first place. Let’s amend our existing class definition by making our member variables private, and by adding getter and setter functions for each of those variables:

package {
     public class Person {
          private var _name:String;
          private var _age:int;
          private var _gender:String;

          public function Person() {}

          public function get name():String {
               return _name;
          }
          public function set name(val:String):void {
               _name = val;
          }

          public function get age():int {
               return _int;
          }
          public function set age(val:int):void {
               _age = val;
          }

          public function get gender():String {
               return _gender;
          }
          public function set gender(val:String):void {
               _gender = val;
          }
     }
}

Now, if you want to make sure that every name is displayed in all caps, you can modify the name getter function like so:

public function get name():String {
     return _name.toUpperCase();
}

…and voila! The next time you try to access a person’s name (any person, anywhere), you’ll get the desired output. Let’s enumerate the benefits of using this approach:

  1. You get application-level control over the values associated with your classes, without having to dig around for individual members.
  2. Because of the above, you’re less likely to miss members of your classes floating around in obscure functions, and so in the long run you’ll have fewer unpredictable bugs.
  3. You could theoretically call other functions every time a value is accessed for more complex interactions with your class.
  4. Using setters, you can filter values placed in your classes at an application-wide level.

One important point to remember is that the name of your getter and setter functions cannot be same as the name of the private variable you’re using them to access. I recommend prefixing the names of all of your private variables with some sigil (I’m fond of underscores) to deal with this, and later, when you’re making adjustments to your massive class, it’s easy to see at a glance while scanning through your code which variables are private and which are not.

That’s all for now. More tips will be coming down the pipelines in the future.

Categories: ArticleBest PracticesFlashFlexTipsTutorial
Published: 02.14.10 :: No Comments »