310.684.3047

StageVideo AS3 API Sample Code for Flash Professional

Good afternoon readers,

I spent a nice chunk of the weekend finishing up the sample code files I'll be presenting along with my talk on "Delivering Best Video Experiences with Flash", which I will be giving at Adobe MAX on October 5th, and LA Flash on September 21st.

This talk covers a lot of ground, from video compression optimization to WMODE settings — but mostly centers around the StageVideo enhancements in the recent versions of the Adobe Flash Player.

For those who don't know, StageVideo is a new way of rendering video in the Flash Player, that takes even more advantage of Graphics Processing Units (or GPUs, which are generally faster at working with video than CPUs).

With regular hardware accelerated video, the GPU decodes the video, but the CPU then still renders the video in the Flash Player.

With StageVideo hardware acceleration, the GPU decodes the video, and also renders the video, directly to the screen, underneath the Flash Player (and all the rest of your Flash content).

I've included the following graphics on one of my slides to help illustrate this point (click on the image for the full size):

StageVideo Hardware Acceleration Comparison Chart

I'll explain more about how this all works in the talk.

When it comes to using StageVideo, fortunately, it's pretty easy.

First off, if you use OSMF (the Open Source Media Framework for coding media experiences in Flash from Adobe), or Strobe Media Playback (Adobe's open-source media player built on OSMF), StageVideo just works for you (OSMF v1.6 and later). Really, it's that simple.

If you are using OSMF, and want to disable StageVideo, all you need to write is:

OSMFSettings.enableStageVideo = false;

In AS3, there is a new API for StageVideo. The new StageVideo class essentially replaces the Video class in functionality (though you still need to use the Video class in your code, as fall-back in case your viewers do not support StageVideo). This means that all the rest of your video playback code (including the NetStream and NetConnection) work the same way. All you need to do is call attachNetStream() on the StageVideo object, instead of the Video object, like so:

myVideo.attachNetStream ( ns ) ;

to:

myStageVideo.attachNetStream ( ns ) ;

Now, the StageVideo class does work differently than the Video class. First, you do not create StageVideo instances — the Flash Player will create them for you if it can, and store references to them in a vector on the stage called stageVideos.

There are more differences than that, but if you just want to get started learning and using the AS3 StageVideo API, I'm posting one of the sample files from the talk. This is the 'simple' sample file, which demonstrates the basic code to get StageVideo playing, and little else. I've also prepared a more complex demo, including the RENDER_STATE event, the colorSpaces property, and pan and zoom functionality, which I'll be distributing to those who come to my talk (again, that will be at Adobe MAX on October 5th, and LA Flash on September 21st).

I've included the sample code, below, in this post. You can also download it as a zip file.

Again, this code is for the simple StageVideo demo. Just set this as your document class in Flash Professional CS5.5, and of course, update the _videoURL constant to point to your own video:

/* AS3
	Copyright 2011 R Blank
*/
package
{
 
	/**
	 *	This class illustrates a simple StageVideo implementation.
	 *
	 *	@langversion ActionScript 3.0
	 *	@playerversion Flash 10.2
	 *
	 *	@author R Blank
	 *	@since  09.09.2011
	 */
 
	//import the MovieClip, because this class is a MovieClip
	import flash.display.MovieClip ;
	//import the Rectangle, so that we can size and position the StageVideo instance
	import flash.geom.Rectangle ;
	//import StageVideoAvailabilityEvent so we can hear 
	//when StageVideo availability changes
	import flash.events.StageVideoAvailabilityEvent;
	//import StageVideo so we can use StageVideo
	import flash.media.StageVideo;
	//import StageVideoAvailability to get the values for the
	//StageVideoAvailabilityEvent.available property
	import flash.media.StageVideoAvailability;
	//import Video as a backup for when StageVideo is not available
	import flash.media.Video;
	//import the NetConnection and NetStream to play our video file
	import flash.net.NetConnection;
	import flash.net.NetStream;
	//import the TextField so we can log values visibly 
	import flash.text.TextField ;
 
	public class StageVideoPlayerExample extends MovieClip {
 
		//--------------------------------------
		// CLASS CONSTANTS
		//--------------------------------------
 
		//the location of our video file
		private const _videoURL : String = "../_media/bunny.mov" ;
 
		//--------------------------------------
		//  CONSTRUCTOR
		//--------------------------------------
		public function StageVideoPlayerExample ( ) {
			//call the _init function to startup
			_init () ;
		}
 
		//--------------------------------------
		//  PRIVATE VARIABLES
		//--------------------------------------
 
		//the Video object to play video when StageVideo is not available
		private var _video : Video ;
		//the StageVideo object to play fully accelerated video
		private var _stageVideo : StageVideo ;
		//the NetStream and NetConnection objects to play video
		private var _ns : NetStream ;
		private var _nc : NetConnection ;
		//the TextField object to log informationvisibly in the browser
		private var _tf : TextField ;
 
		//--------------------------------------
		//  PRIVATE & PROTECTED INSTANCE METHODS
		//--------------------------------------
 
		//called by the constructor to startup the player
		private function _init ( ) : void
		{
			//the NetConnection object over which video is delivered
			_nc = new NetConnection ( ) ;
			//connect _nc to null because we are playing video progressively
			_nc.connect ( null ) ;
			//create the NetStream to deliver video over the NetConnection
			_ns = new NetStream ( _nc ) ;
			//define the NetStream client as 'this'
			//where _ns will look for the onMetaData and onCuePoint methods
			_ns.client = this ;
			//tell the NetStream to play our video file
			_ns.play ( _videoURL ) ;
			//create the video object as back up, in case StageVideo is not available
			_video = new Video ( ) ;
			//listen for the StageVideoAvailabilityEvent
			//which is fired as soon as this listener is added
			//and when StageVideo becomes available or unavailable 
			//throughout SWF playback
			stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoAvailability);
			//create the TextField for logging
			_tf = new TextField ( );
			_tf.height = stage.stageHeight ;
			_tf.width = stage.stageWidth ;
			_tf.mouseWheelEnabled = true ; 
			_tf.multiline = true ; 
			_tf.wordWrap = true ; 
 
			//add the TextField to the display list
			addChild ( _tf ) ;
 
		}
 
		//called when we wish to start StageVideo playback
		private function _enableStageVideo() : void {
			//if we do not have a StageVideo object reference 
			//already stored in _stageVideo
			if ( _stageVideo == null ) 
			{
				//set _stageVideo to reference the first of our
				//available StageVideo objects (up to 8 available on desktops)
				_stageVideo = stage.stageVideos [ 0 ] ;
				//size and position our _stageVideo with a new Rectangle
				_stageVideo.viewPort = new Rectangle ( 0 , 0 , 320 , 240 ) ;
			}
			//if the _video object is in the display list
			if ( _video.parent )
				//remove _video from the display list
				removeChild ( _video ) ;
			//attach our NetStream instance to our StageVideo instance
			_stageVideo.attachNetStream ( _ns ) ;
		}
 
		//called when StageVideo becomes unavailable
		//and we need to use a Video object as back-up
		private function _disableStageVideo() : void {
			//attach our NetStream to our Video object
			_video.attachNetStream ( _ns ) ;
			//add the Video object to the display list
			//(so that it can be seen)
			addChild ( _video ) ;
			//add the _tf TextField back to the display list
			//so that it is on top of the _video object
			addChild ( _tf ) ;
		}
 
 
 
		//--------------------------------------
		//  StageVideo Event Handlers
		//--------------------------------------
 
		//our callback function for the
		//StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY event
		private function _onStageVideoAvailability ( evt : StageVideoAvailabilityEvent ) : void {
			//log the availability of StageVideo
			_tf.text = "Stage Video: " + evt.availability ;
			//if StageVideo is available
			if ( evt.availability )
				//call _enableStageVideo
				_enableStageVideo ( ) ;
			else 
				//otherwise call _disableStageVideo
				_disableStageVideo ( ) ;
		}
 
 
		//--------------------------------------
		//  NetStream Event Handlers
		//--------------------------------------
 
		//the NetStream will look for these two methods
		//on whatever object is identified as the NetStream's client
		//if they do not exist, you will receive a run time error
		//when the NetStream encounters metadata or cuepoints in the video
		public function onMetaData( info:Object ) : void { }
		public function onCuePoint( info:Object ) : void { }
 
	}
 
}

Share and enjoy!

-r

Category: Code & Samples, Events

Tagged: , , , ,

16 Responses

  1. Would love to see this working but I get an error

    Error #2095: flash.net.NetStream was unable to invoke callback onXMPData.

    something I guess to do with lack of meta data in my particular video clip. Shouldn't this be handled by the two last functions in your sample?

    Thanks for sharing this.

  2. rblank says:

    Howdy Martin:

    Sounds to me like not like your video is missing metadata, but instead includes XMP data (which is sort of unusual, in my experience with compressed video for the web).

    The two functions included in my above code would NOT handle XMP data — they handle standard metadata (width, height, framerate, duration, etc) and cue points.

    So, perhaps unsurprisingly, what you need to add is an onXMPData method, just like onCuePoint, located on the NetStream's client.

    public function onXMPData ( info : Object ) : void {}

    For reference, the full set of methods that the NetStream might look for on the client are:
    - onCuePoint()
    - onImageData()
    - onMetaData()
    - onPlayStatus() (FMS only — at least as far as I know)
    - onTextData()
    - onXMPData()

    Good luck!

    -r

  3. Thanks for replying on that. You were absolutely right I was missing the onMetaData method. That certainly resolved that first error. Now it compiles fine but oddly with the sample video I am using I just get audio no video. I am using a clips from http://support.apple.com/kb/HT1425. So far I tried three of the clips – the m4v, mov and mp4 but they all behave the same. Am I missing something dumb here (won't be the first time).

    Thanks Martin

    ps Enjoy MAX – I attended MAX Europe a couple of times before they stopped running it over here. It was a fantastic event

  4. rblank says:

    Hello Martin,

    It may seem silly, but the format of your video (.m4v, .mov, etc) does not tell you the codec. Flash supports H.264, so you need to see if your video is really H.264. If you are on Mac, you can tell by loading it into Quicktime and checking the Info panel; if you are on PC, you can install GSpot (http://www.headbands.com/gspot/) which will tell you what codec is in your video.

    Also, please confirm what version of Flash Pro and the Flash Player you are using.

    Cheers,

    -r

  5. Resolved it! Was to do with me not published my SWF from Flash Professional to Hardware acceleration 'direct' mode and also needed to amend my HTML wrapper to 'direct' mode too. Thanks for your swift response.

  6. rblank says:

    Ah yes, I spend a few slides covering that in my talk.
    Glad you figured it out.
    You can see a few words posted about that here, too: http://labs.almerblank.com/2011/03/the-wmode-embed-parameter-de-mystified/

    Honestly, WMODE is sort of annoying in this workflow (especially when the two wmodes you need — "direct" or "gpu" — are not even available as options in the Flash Pro publish settings!)

    Cheers,

    -r

  7. RJ Garcia says:

    Hey, I get a "Cannot access a property or method of a null object reference." When I try to implement your code. The error occurs on line 92: stage.addEventListern…..
    Anyways, the only changes I've made to the code are the _videoUrl constant and the constructor. I made the videoUrl constant into a normal variable which gets populated in the constructor. I'm using this class for an iPhone application. In one of my views I create an instance of this class that you created. Anyways, when I instantiate the class, I get the error. It would be really great if I get some help on this problem. Thank-you very much for your help

    RJ

    • rblank says:

      It sounds like the code can not see the stage.

      In which case, my guess is that you have not implemented this code as the document class in your Flash Project. Can you confirm?

  8. nicotroia says:

    thank you very much!

  9. brian says:

    any tips for getting this to work in Flash Builder 4.5.1 as a AS3 mobile project exporting to ios?

    doesn't work on desktop emulation or ont he device. the StageVideoAvailabilityEvent never fires

    • rblank says:

      Howdy Brian:

      StageVideo is supposed to work for AIR for iOS (since AIR 3.0, I believe). I do not know what may be happening in your project. Can you query the Stage.stageVideos property?

      -r

  10. Greg says:

    I'm having a similar problem as Brian and Martin had. Running your code in a project targeted for iOS, I get audio, but no video. Translating this code to my own document class, I have an issue with the 'stage.stageVideos[0]' call, which gives me the error 'The index 0 is out of range 0'. Even with that error, I do still get audio, but no video. I'm not sure what the 'direct' mode is and how I set that, if that's the solution to any of this. Thanks.

    • rblank says:

      Hi Greg,

      Sorry about the difficulties you are encountering. I'm not doing any work with AIR for mobile devices any more, so it's difficult for me to say exactly what you're seeing. If stage.stageVideos[0] doesn't exist, to my understanding, that means StageVideo is not supported (which also sounds consistent with the playback symptoms you mention).

      What type of video file are you trying to play? Is it MP4?

      Also, to set GPU mode of 'direct', you will want to set to 'direct' in your application descriptor file. And, according to this post you also need to add “-swf-version=13" to the additional compiler arguments.

      Good luck,

      -r

  11. Anton says:

    I just can't make it work! I've created a new AS3 project, created a blank fla file, attached the main class from Zip file. Placed a h264 video and changed the video source in code. Targeted flash player 10.3 and published with windows mode – direct.

    As the result – when I open html file, I get StageVideo : available sign, but it does not play.

  12. Keng says:

    Thanks for the code!
    Some discoveries, I found that StageVideo video playback ( I attached a webcam to it), the image quality is smoother, but the video colors are washed out.
    Video, on the other hand, appears to be bit more pixelated, but with much better black and more vivid color.
    Just wondering do you or anyone else here experience the same?

    • rblank says:

      Those results are not surprising. Depending on the path your video follows to get rendered (the render path, discussed a bit here, http://labs.almerblank.com/2011/10/stagevideo-part-2-how-it-works/ ) — whether using the GPU or CPU — the image may look different. And the differences will often be different for the video content, vs. the other visual content overlaid on top of the video. And, what's worse — the differences also depend on the specific hardware you (or your viewers) has installed.

      Good luck!

Leave a Reply