Though more and more of us are developing with AS3, certain technologies remain in AS2. This forces us to find fast, simple ways to use these technologies within our projects. One such technology is YouTube.
The current YouTube player is still in AS2 and until it’s updated to AS3, we have to create a wrapper to allow us to load videos into our projects. Remember, stealing the FLV feed is against YouTube’s terms and conditions, so let’s do it the right way using the chromed or chromeless player.
It may not look like much, but what you’ve got there is the YouTube Player (chromed and chromless) loaded into an AS3 application.
Before we start…
This is a tutorial for intermediate to advanced Actionscripters (but don’t be intimidated if you’re neither, there’s no time like the present to start learning) as we’re going to be using both AS2 and AS3. It’s worth having a quick read of the points below:
- It’s worth checking out the documentation of the YouTube Player API. It’s available on Google Code and it has a good explanation of how to use the Player API and also has examples of AS2 and AS3 implementation.
- This tutorial is going to show how to build a set of components you can use with your AS3 projects in the future. This is much more handy than just showing you how you can bring the player into an application and then leaving you to it.
Step 1 – The Plan
The way we’re going to get this to work is by creating a SWF built with AS2 that will load in the Player. We will then create a set of AS3 classes that will allow us to use the code as simple components we can add into our applications. One downside of having to use a wrapper is that as well as importing the classes we’re going to make in AS3, we will also need to bring in the SWF wrapper so that we can load it through our classes.
Step 2 – Starting the Wrapper
The first thing we need to do is create our AS2 wrapper. I’m going to show you how to build the wrapper using a class, this means that you can either compile it using the Flash IDE or MTASC. So open up your favourite Actionscript 2 editor and let’s begin writing the AS2 class. We’re going to start by creating a YouTube Player class that we’ll then use in our wrapper, so create a new file called YouTubePlayer.as and start by adding a simple class:
class YouTubePlayer
{
public function YouTubePlayer()
{
}
}
The plan here is to have a class that allows us to simply load in a YouTube player then easily access and change certain properties such as auto play, HD/HQ and so on. Additionally, we’ll be using our class to stop and destroy the player when we’re ready to load in another one. First thing we do is create some public vars that will allow us to configure the player:
class YouTubePlayer
{
public var autoPlay:Boolean = true;
public var chromeless:Boolean = false;
public var pars:String = 'autoplay=0&loop=0&rel=0&showsearch=0&hd=1';
public var playerWidth:Number = 425;
public var playerHeight:Number = 344;
public function YouTubePlayer()
{
}
}
Step 3 – Handling Sandbox and Security Errors
Since we’re going to be loading in a SWF from YouTube, we need to make sure that our SWF allows the YouTube Player SWF to access certain properties within our wrapper. In order to do this, we use a function called System.security.allowDomain() within our constructor:
class YouTubePlayer
{
public var autoPlay:Boolean = true;
public var chromeless:Boolean = false;
public var pars:String = 'autoplay=0&loop=0&rel=0&showsearch=0&hd=1';
public var playerWidth:Number = 425;
public var playerHeight:Number = 344;
public function YouTubePlayer()
{
System.security.allowDomain('www.youtube.com');
System.security.allowDomain('youtube.com');
System.security.allowDomain('s.ytimg.com');
System.security.allowDomain('i.ytimg.com');
}
}
Step 4 – Preparing to Load the Player
In AS2 we can only create display objects by adding them to the stage. We’ll also change our constructor and add a new private var that will allow us to pass in a movie clip as the parent into which we’ll load the player:
class YouTubePlayer
{
public var autoPlay:Boolean = true;
public var chromeless:Boolean = false;
public var pars:String = 'autoplay=0&loop=0&rel=0&showsearch=0&hd=1';
public var playerWidth:Number = 425;
public var playerHeight:Number = 344;
private var parent:MovieClip;
public function YouTubePlayer(parent:MovieClip)
{
System.security.allowDomain('www.youtube.com');
System.security.allowDomain('youtube.com');
System.security.allowDomain('s.ytimg.com');
System.security.allowDomain('i.ytimg.com');
this.parent = parent;
}
}
Now we need to create a new private var for a movie clip loader and create a new instance of the MovieClipLoader() class; we’ll be using this to load the YouTube Player. We also add a new private var called player as this will be our reference to the YouTube Player, a private var called videoId, a private var called removePlayer, a public var called addEventListener, a private var called dispatchEvent and another private var called intervals which will initialised as a new array:
class YouTubePlayer
{
public var autoPlay:Boolean = true;
public var chromeless:Boolean = false;
public var pars:String = 'autoplay=0&loop=0&rel=0&showsearch=0&hd=1';
public var playerWidth:Number = 425;
public var playerHeight:Number = 344;
public var addEventListener:Function;
private var intervals:Array = [ ];
private var parent:MovieClip;
private var loader:MovieClipLoader;
private var player:MovieClip;
private var videoId:String;
private var removePlayer:Boolean;
private var dispatchEvent:Function;
public function YouTubePlayer(parent:MovieClip)
{
System.security.allowDomain('www.youtube.com');
System.security.allowDomain('youtube.com');
System.security.allowDomain('s.ytimg.com');
System.security.allowDomain('i.ytimg.com');
this.parent = parent;
loader = new MovieClipLoader();
}
}
So now we’re ready to start building our function that we’ll use to load a YouTube video. We’ll pass in a string that will contain the YouTube video’s Id.
Step 5 – Creating the Initialising Function
Let’s create a new function called init(). This function will accept one parameter: the YouTube video’s Id:
public function init(videoId:String):Void
{
this.videoId = videoId;
if ( player )
{
removePlayer = true;
if ( player.getPlayerState() != 1 )
{
// destroyPlayer();
}
else
{
player.stopVideo();
}
}
else
{
loadVideo();
}
}
So the first thing we do in this function is save the video id in our class variable. Since this class will be handling the creation and destroying of the player we need to check if the player already exists before creating. If it does exist, we check if it’s playing (ie the player will have a state of 1); if it is, we tell it to stop; otherwise we destroy the player. We set our class var removePlayer to true as this will be used later on in our class.
Step 6 – Loading the Player
We’ll start by loading in the player, then go into destroying it. Let’s create a function called loadVideo():
private function loadVideo():Void
{
var url:String = ( chromeless ? 'http://www.youtube.com/apiplayer' : 'http://www.youtube.com/v/' + videoId + '&' + pars );
player = parent.createEmptyMovieClip( 'Player' + ( new Date().getTime() ), parent.getNextHighestDepth() );
parent._visible = false;
loader.addListener({ onLoadInit: loadInit() });
loader.unloadClip( player );
loader.loadClip( url, player );
}
The first thing we do is determine whether we’re loading in the chromed or chromless player, we use the public class var chromeless to determine this. We then create a new movie clip within our parent that we’ll use to put the player into. AS2 sometimes has issues with creating movie clips when they’ve just been removed (this movie clip will be removed before another player can be loaded), so I use a little trick that adds a timestamp to the name of the movie clip so Flash doesn’t complain. I then hide the parent as we prepare to load the player.
We now need to initialise the loader, we add a listener to it, remove any reference that the loader has to our player (if we had already created it) and then we get the loader to load the YouTube player into our player movie clip.
We’ll now create our loadInit() function that will be fired once the SWF has been loaded and is ready:
private function loadInit():Void
{
intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
}
One beauty of AS3 is that most classes and components have the ability to dispatch events, allow you to add event listeners to that class. However, in AS2 this wasn’t as popular. The same stands with the YouTube Player, so therefore we need to run a function at intervals so we can check when the YouTube Player is ready.
You’ll notice that I’ve used a function called Delegate.create(). You’ll need to import this from mx.utils.Delegate and it’s quite important. The Delegate class allows you to load a function that’s within a certain scope. You see in AS2 when you fire a function (such as through a timeout, interval or onRelease) it is fired from the scope of the caller. If a movie clip has an onRelease function and within that function it calls another function, AS2 won’t look for that function within the class, rather within the movie clip. You therefore need to use a Delegate to tell AS2 where to look for this function. Fun.
We now create the function checkPlayerLoaded() which will check to see if the YouTube Player is ready:
private function checkPlayerLoaded():Void
{
if ( player.isPlayerLoaded() )
{
if ( chromeless )
{
player.loadVideoById( videoId );
}
player.addEventListener( 'onStateChange', Delegate.create( this, onPlayerStateChanged ) );
player.addEventListener( 'onError', Delegate.create( this, onPlayerError ) );
resizePlayer( playerWidth, playerHeight );
parent._visible = true;
for ( var i:Number = 0; i < intervals.length; i++ )
{
clearInterval( intervals[ i ] );
}
onPlayerReady();
}
}
The first thing we do is check that the player is loaded. We use the YouTube Player’s isPlayerLoaded() to check if the player is ready. If it’s not, the interval will just run this function again until the player is ready. Once it is, we check to see if we’ve loaded the chromeless player and if we have, we use the function loadVideoById() to load the video as the chromeless player has a few more functions.
We then assign some event listeners to the player as we want to know if there are any errors and if the player’s state has changed. We then resize the player to our desired height and width, then show the parent, then remove all the intervals and finally run a function that declares our player is ready.
So working down, we’ll first create the state change listener function onPlayerStateChanged():
private function onPlayerStateChanged(state:Number):Void
{
switch ( state )
{
case 0:
// ended
if ( removePlayer )
{
// destroyPlayer();
}
break;
case 1:
// playing
break;
case 2:
// paused
break;
case 3:
// buffering
break;
case 4:
// fudge knows
break;
case 5:
// video queued
break;
}
}
Now the next state of our class depends on whether you like to code. Since this function listens to the state of the player, some may just want to listen to ones that matter to them and create functions relating to the state. Others, like me, will dispatch events, making this a very useful component. We’ll need to make some changes to the class now and import the EventDispatcher class by importing it from ‘mx.events.EventDispatcher’. We then also need to add ‘EventDispatcher.initialize( this )’ to the constructor, so the class should look like this:
import mx.events.EventDispatcher;
import mx.utils.Delegate;
class YouTubePlayer
{
public var autoPlay:Boolean = true;
public var chromeless:Boolean = false;
public var pars:String = 'autoplay=0&loop=0&rel=0&showsearch=0&hd=1';
public var playerWidth:Number = 425;
public var playerHeight:Number = 344;
public var addEventListener:Function;
private var intervals:Array = [ ];
private var parent:MovieClip;
private var loader:MovieClipLoader;
private var player:MovieClip;
private var videoId:String;
private var removePlayer:Boolean;
private var dispatchEvent:Function;
public function YouTubePlayer(parent:MovieClip)
{
EventDispatcher.initialize( this );
System.security.allowDomain( '*' );
System.security.allowDomain( 'www.youtube.com' );
System.security.allowDomain( 'youtube.com' );
System.security.allowDomain( 's.ytimg.com' );
System.security.allowDomain( 'i.ytimg.com' );
this.parent = parent;
loader = new MovieClipLoader();
}
public function init(videoId:String):Void
{
this.videoId = videoId;
if ( player )
{
removePlayer = true;
if ( player.getPlayerState() != 1 )
{
// destroyPlayer();
}
else
{
player.stopVideo();
}
}
else
{
loadVideo();
}
}
private function loadVideo():Void
{
var url:String = ( chromeless ? 'http://www.youtube.com/apiplayer' : 'http://www.youtube.com/v/' + videoId + '&' + pars );
player = parent.createEmptyMovieClip( 'Player' + ( new Date().getTime() ), parent.getNextHighestDepth() );
parent._visible = false;
loader.addListener({ onLoadInit: loadInit() });
loader.unloadClip( player );
loader.loadClip( url, player );
}
private function loadInit():Void
{
intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
}
private function checkPlayerLoaded():Void
{
if ( player.isPlayerLoaded() )
{
if ( chromeless )
{
player.loadVideoById( videoId );
}
player.addEventListener( 'onStateChange', Delegate.create( this, onPlayerStateChanged ) );
player.addEventListener( 'onError', Delegate.create( this, onPlayerError ) );
resizePlayer( playerWidth, playerHeight );
parent._visible = true;
for ( var i:Number = 0; i < intervals.length; i++ )
{
clearInterval( intervals[ i ] );
}
onPlayerReady();
}
}
private function onPlayerStateChanged(state:Number):Void
{
switch ( state )
{
case 0:
// ended
if ( removePlayer )
{
// destroyPlayer();
}
break;
case 1:
// playing
break;
case 2:
// paused
break;
case 3:
// buffering
break;
case 5:
// video queued
break;
}
}
}
Now we’re ready to create some events.
Step 7 – Dealing With Events (in AS2)
Since we’re trying to make this code as ‘nice’ as possible, it makes sense to store our events as static strings within a class rather than writing them by hand. Create a new file called YouTubePlayerEvents.as and use the following code for it:
class YouTubePlayerEvent
{
public static var STATE_CHANGED:String = 'onStateChange';
public static var ERROR:String = 'onError';
public static var PLAYER_PLAYING:String = 'playerPlaying';
public static var PLAYER_ENDED:String = 'playerEnded';
public static var PLAYER_PAUSED:String = 'playerPaused';
public static var PLAYER_QUEUED:String = 'playerQueued';
public static var PLAYER_BUFFERING:String = 'playerBuffering';
public static var PLAYER_NOT_STARTED:String = 'playerNotStarted';
public var type:String;
public function YouTubePlayerEvent(type:String)
{
this.type = type;
}
}
Now that we have all the player’s events in a class, the first thing we should do is update our checkPlayerLoaded() function code:
player.addEventListener( YouTubePlayerEvent.STATE_CHANGED, Delegate.create( this, onPlayerStateChanged ) ); player.addEventListener( YouTubePlayerEvent.ERROR, Delegate.create( this, onPlayerError ) );
Now we need to dispatch events every time the player’s state has changed or if there’s an error, so we update onPlayerStateChanged():
private function onPlayerStateChanged(state:Number):Void
{
switch ( state )
{
case 0:
// ended
if ( removePlayer )
{
// destroyPlayer();
}
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_ENDED ) );
break;
case 1:
// playing
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PLAYING ) );
break;
case 2:
// paused
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PAUSED ) );
break;
case 3:
// buffering
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_BUFFERING ) );
break;
case 5:
// video queued
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_QUEUED ) );
break;
}
}
Before we finish, we need to add the onPlayerError() function and get that to dispatch an event:
private function onPlayerError():Void
{
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.ERROR ) );
}
Step 8 – Resizing the Player
Now we’ll create the function that handles the resizing of our player. This is handy because from time to you, you’ll need to resize your player, so create a resizePlayer() and put the following inside:
public function resizePlayer(width:Number, height:Number):Void
{
if ( player.isPlayerLoaded() )
{
player.setSize( width, height );
}
}
We create this function and make sure it’s available publicly. This is because, once again, you may create a project that requires the player’s size to be changed while it’s playing or without loading another video. Again, we use YouTube Player’s API function that allows us to resize the player by simply calling setSize().
Step 9 – Now the Player’s Ready
Now we get on to our final creation function which is onPlayerReady(). This function will simply check to see if we want our player to autoplay and if it does, start playing. You’ll notice that you can pass a variable ‘autoplay’ when you load the player, however, this only applies to the chromed player. I therefore found it easier just setting it to ’0′ and using a public boolean to set whether the player plays automatically or not:
private function onPlayerReady():Void
{
if ( autoPlay )
{
player.playVideo();
}
}
Ok, so now we’ve got to a point where we can test the player. As you can see, I’ve left the function destroyPlayer() commented out so it could be tested without Flash complaining. So here’s our class so far:
import mx.events.EventDispatcher;
import mx.utils.Delegate;
import YouTubePlayerEvent;
class YouTubePlayer
{
public var autoPlay:Boolean = true;
public var chromeless:Boolean = false;
public var pars:String = 'autoplay=0&loop=0&rel=0&showsearch=0&hd=1';
public var playerWidth:Number = 425;
public var playerHeight:Number = 344;
public var addEventListener:Function;
private var intervals:Array = [ ];
private var parent:MovieClip;
private var loader:MovieClipLoader;
private var player:MovieClip;
private var videoId:String;
private var removePlayer:Boolean;
private var dispatchEvent:Function;
public function YouTubePlayer(parent:MovieClip)
{
EventDispatcher.initialize( this );
System.security.allowDomain( '*' );
System.security.allowDomain( 'www.youtube.com' );
System.security.allowDomain( 'youtube.com' );
System.security.allowDomain( 's.ytimg.com' );
System.security.allowDomain( 'i.ytimg.com' );
this.parent = parent;
loader = new MovieClipLoader();
}
public function init(videoId:String):Void
{
this.videoId = videoId;
if ( player )
{
removePlayer = true;
if ( player.getPlayerState() != 1 )
{
//destroyPlayer();
}
else
{
player.stopVideo();
}
}
else
{
loadVideo();
}
}
private function loadVideo():Void
{
var url:String = ( chromeless ? 'http://www.youtube.com/apiplayer' : 'http://www.youtube.com/v/' + videoId + '&' + pars );
player = parent.createEmptyMovieClip( 'Player' + ( new Date().getTime() ), parent.getNextHighestDepth() );
parent._visible = false;
loader.addListener({ onLoadInit: loadInit() });
loader.unloadClip( player );
loader.loadClip( url, player );
}
private function loadInit():Void
{
intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
}
private function checkPlayerLoaded():Void
{
if ( player.isPlayerLoaded() )
{
if ( chromeless )
{
player.loadVideoById( videoId );
}
player.addEventListener( YouTubePlayerEvent.STATE_CHANGED, Delegate.create( this, onPlayerStateChanged ) );
player.addEventListener( YouTubePlayerEvent.ERROR, Delegate.create( this, onPlayerError ) );
resizePlayer( playerWidth, playerHeight );
parent._visible = true;
for ( var i:Number = 0; i < intervals.length; i++ )
{
clearInterval( intervals[ i ] );
}
onPlayerReady();
}
}
private function onPlayerStateChanged(state:Number):Void
{
switch ( state )
{
case 0:
// ended
if ( removePlayer )
{
//destroyPlayer();
}
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_ENDED ) );
break;
case 1:
// playing
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PLAYING ) );
break;
case 2:
// paused
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PAUSED ) );
break;
case 3:
// buffering
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_BUFFERING ) );
break;
case 5:
// video queued
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_QUEUED ) );
break;
}
}
private function onPlayerError():Void
{
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.ERROR ) );
}
public function resizePlayer(width:Number, height:Number):Void
{
if ( player.isPlayerLoaded() )
{
player.setSize( width, height );
}
}
private function onPlayerReady():Void
{
if ( autoPlay )
{
player.playVideo();
}
}
}
Now using MTASC or the IDE, quickly create a class/keyframe and add this to it:
var player = new YouTubePlayer( this ); player.autoPlay = false; player.playerWidth = Stage.width; player.playerHeight = Stage.height; player.init( 'R7yfISlGLNU' );
You should see something like this:
So there you should see a nice YouTube Player with Lonely Island’s "I’m on a boat" (worth a watch). You’ll notice that as soon as you start playing it, it’ll automatically turn on HD, nice eh?
Now that we’ve created our player, we now need the ability to change the video, so we need to be able to destroy the player.
Step 10 – Destroying the Player
A lot of YouTube AS3 player wrappers rely on AS3 to remove the player and add it again. However AS3 has really bad garbage collection, this means errors occur, like the sound doesn’t stop playing or you can’t load in a new player because the previous one hasn’t been removed yet. I do this all in AS2 as it’s much easier, cleaner and quicker.
So we simply need our AS2 wrapper to destroy the current player so that we can then load in a new one, so let’s create the destroyPlayer() function:
private function destroyPlayer():Void
{
intervals.push( setInterval( Delegate.create( this, checkPlayerDestroyed ), 500 ) );
removePlayer = false;
}
Now this looks sort of the same as the loadInit() function but we’re not going to start destroying the player until the interval is run, so create a new function called checkPlayerDestroyed():
private function checkPlayerDestroyed():Void
{
if ( !player )
{
for ( var i:Number = 0; i < intervals.length; i++ )
{
clearInterval( intervals[ i ] );
}
init( videoId, true );
}
else
{
for ( var players:String in parent )
{
parent[ players ].destroy();
removeMovieClip( parent[ players ] );
unloadMovie( parent[ players ] );
}
player = null;
}
}
What we do here is check if the player exists, if it does, we then go through our parent and destroy every instance of it (using YouTube Player's destroy() function). Once again, because AS2 is a bit slow at this sort of thing, we declare the player as null. Once the interval is run again and the player has been removed, we remove the intervals and we then run the init() function passing the video ID.
So now we can modify our test file we used in the first milestone and set it up with a button so that when that button is pressed another video will be loaded:
var holder = this.createEmptyMovieClip( 'holder', this.getNextHighestDepth() );
var button = this.createEmptyMovieClip( 'button', this.getNextHighestDepth() );
var player = new YouTubePlayer( holder );
with ( button )
{
beginFill( 0xFF0000 );
moveTo( 0, 0 );
lineTo( 100, 0 );
lineTo( 100, 100 );
lineTo( 0, 100 );
lineTo( 0, 0 );
endFill();
_x = 500;
}
button.onRelease = function():Void
{
player.init( 'sGTAnXqn9Jc' );
}
player.autoPlay = false;
player.playerWidth = 500;
player.playerHeight = Stage.height;
player.init( 'R7yfISlGLNU' );
So we have:
Step 11 - Stopping the Video
Last but by no means least, we need to be able to stop the player from playing, so we add a function called stop() to the bottom of our class, like so:
import mx.events.EventDispatcher;
import mx.utils.Delegate;
import YouTubePlayerEvent;
class YouTubePlayer
{
public var autoPlay:Boolean = true;
public var chromeless:Boolean = false;
public var pars:String = 'autoplay=0&loop=0&rel=0&showsearch=0&hd=1';
public var playerWidth:Number = 425;
public var playerHeight:Number = 344;
public var addEventListener:Function;
private var intervals:Array = [ ];
private var parent:MovieClip;
private var loader:MovieClipLoader;
private var player:MovieClip;
private var videoId:String;
private var removePlayer:Boolean;
private var dispatchEvent:Function;
public function YouTubePlayer(parent:MovieClip)
{
EventDispatcher.initialize( this );
System.security.allowDomain( '*' );
System.security.allowDomain( 'www.youtube.com' );
System.security.allowDomain( 'youtube.com' );
System.security.allowDomain( 's.ytimg.com' );
System.security.allowDomain( 'i.ytimg.com' );
this.parent = parent;
loader = new MovieClipLoader();
}
public function init(videoId:String):Void
{
this.videoId = videoId;
if ( player )
{
removePlayer = true;
if ( player.getPlayerState() != 1 )
{
destroyPlayer();
}
else
{
player.stopVideo();
}
}
else
{
loadVideo();
}
}
private function loadVideo():Void
{
var url:String = ( chromeless ? 'http://www.youtube.com/apiplayer' : 'http://www.youtube.com/v/' + videoId + '&' + pars );
player = parent.createEmptyMovieClip( 'Player' + ( new Date().getTime() ), parent.getNextHighestDepth() );
parent._visible = false;
loader.addListener({ onLoadInit: loadInit() });
loader.unloadClip( player );
loader.loadClip( url, player );
}
private function loadInit():Void
{
intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
}
private function checkPlayerLoaded():Void
{
if ( player.isPlayerLoaded() )
{
if ( chromeless )
{
player.loadVideoById( videoId );
}
player.addEventListener( YouTubePlayerEvent.STATE_CHANGED, Delegate.create( this, onPlayerStateChanged ) );
player.addEventListener( YouTubePlayerEvent.ERROR, Delegate.create( this, onPlayerError ) );
resizePlayer( playerWidth, playerHeight );
parent._visible = true;
for ( var i:Number = 0; i < intervals.length; i++ )
{
clearInterval( intervals[ i ] );
}
onPlayerReady();
}
}
private function onPlayerStateChanged(state:Number):Void
{
switch ( state )
{
case 0:
// ended
if ( removePlayer )
{
destroyPlayer();
}
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_ENDED ) );
break;
case 1:
// playing
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PLAYING ) );
break;
case 2:
// paused
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PAUSED ) );
break;
case 3:
// buffering
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_BUFFERING ) );
break;
case 5:
// video queued
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_QUEUED ) );
break;
}
}
private function onPlayerError():Void
{
dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.ERROR ) );
}
public function resizePlayer(width:Number, height:Number):Void
{
if ( player.isPlayerLoaded() )
{
player.setSize( width, height );
}
}
private function onPlayerReady():Void
{
if ( autoPlay )
{
player.playVideo();
}
}
private function destroyPlayer():Void
{
intervals.push( setInterval( Delegate.create( this, checkPlayerDestroyed ), 500 ) );
removePlayer = false;
}
private function checkPlayerDestroyed():Void
{
if ( !player )
{
for ( var i:Number = 0; i < intervals.length; i++ )
{
clearInterval( intervals[ i ] );
}
init( videoId );
}
else
{
for ( var players:String in parent )
{
parent[ players ].destroy();
removeMovieClip( parent[ players ] );
unloadMovie( parent[ players ] );
}
player = null;
}
}
public function stop():Void
{
removePlayer = false;
player.stopVideo();
}
}
So there we have our YouTube Player class! Whenever you need to use the YouTube Player in AS2, you can use this! Simples.
Step 12 - Creating the Wrapper
Now that our class is ready, we just need to create the wrapper we're going to load through AS3 so we can use the player. The communication between the wrapper (built in AS2) and the AS3 code will be done through using Flash Player's 'LocalConnection'. Now instead of writing my own local connection class, I use gSkinner.com's excellent class SWFBridge. So get yourself a copy, and get ready to create one final AS2 class.
Let's create a new class file called YouTubePlayerWrapper.as and set up the class:
class YouTubePlayerWrapper
{
public function YouTubePlayerWrapper(parent:MovieClip)
{
}
}
So we'll begin by setting up our class's variables and constructor:
import com.gskinner.utils.SWFBridgeAS2;
import mx.utils.Delegate;
import YouTubePlayer;
import YouTubePlayerEvent;
class YouTubePlayerWrapper
{
static var BRIDGE_NAME:String = 'YouTubePlayerWrapperBridge';
private var parent:MovieClip;
private var player:YouTubePlayer;
private var bridge:SWFBridgeAS2;
public function YouTubePlayerWrapper(parent:MovieClip)
{
Stage.scaleMode = 'noScale';
Stage.align = 'TL';
System.security.allowDomain( '*' );
System.security.allowDomain( 'www.youtube.com' );
System.security.allowDomain( 'youtube.com' );
System.security.allowDomain( 's.ytimg.com' );
System.security.allowDomain( 'i.ytimg.com' );
this.parent = parent;
init();
}
}
The first var we create is a static reference to the local connection bridge name. We then create private vars that reference the parent, the player and the bridge we're going to create. Since this wrapper will be used to create any size player, we need to set the stage's scale mode and align so that resize is simple and won't stretch the player. Again, we need to add the system security settings so that Flash Player doesn't complain. Finally we add the class's parent reference and then run the init() function.
Now we'll create our init() function:
private function init():Void
{
var playerHolder:MovieClip = parent.createEmptyMovieClip( 'playerHolder', parent.getNextHighestDepth() );
bridge = new SWFBridgeAS2( BRIDGE_NAME, this );
bridge.addEventListener( 'connect', this );
player = new YouTubePlayer( playerHolder );
player.addEventListener( YouTubePlayerEvent.PLAYER_ENDED, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_PLAYING, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_PAUSED, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_BUFFERING, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_QUEUED, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_NOT_STARTED, Delegate.create( this, sendEvent ) );
}
Here's just a quick run down of the function: we create a little holder for our player, we then initialise the bridge with the first variable being the bridge's name and the second the scope of the functions the bridge can launch, that's this class. We then initialise the player and apply event listeners to it. This is where the events dispatched by the player are handy as we're then able to bubble these events up to our AS3 code.
Now we create the sendEvent() function that will pass the events up to our AS3 code:
private function sendEvent(e:YouTubePlayerEvent):Void
{
bridge.send( 'sendEvent', e.type );
}
Now we need to add the functions we will need to call from the AS3 code, so we add a playVideo(), resizePlayer() and stopVideo():
public function playVideo(videoId:String, playerWidth:Number, playerHeight:Number, autoPlay:Boolean, pars:String, chromeless:Boolean):Void
{
player.autoPlay = ( autoPlay !== false ? true : false );
player.chromeless = ( chromeless ? chromeless : false );
player.pars = ( pars ? pars : player.pars );
player.playerWidth = ( playerWidth ? playerWidth : player.playerWidth );
player.playerHeight = ( playerHeight ? playerHeight : player.playerHeight );
player.init( videoId );
}
public function resizePlayer(width:Number, height:Number):Void
{
player.resizePlayer( width, height );
}
public function stopVideo():Void
{
player.stop();
}
As you can see, we're allowing our wrapper to pass all the public vars from AS3 to our wrapper and to also resize the player when it's needed.
It appears that our wrapper is ready, so just like we did with our milestone tests, we need to compile this wrapper into a SWF. Let's do just that and call it 'YouTubePlayerWrapper.swf'. The wrapper class should be like this:
import com.gskinner.utils.SWFBridgeAS2;
import mx.utils.Delegate;
import YouTubePlayer;
import YouTubePlayerEvent;
class YouTubePlayerWrapper
{
static var BRIDGE_NAME:String = 'YouTubePlayerWrapperBridge';
private var parent:MovieClip;
private var player:YouTubePlayer;
private var bridge:SWFBridgeAS2;
public function YouTubePlayerWrapper(parent:MovieClip)
{
Stage.scaleMode = 'noScale';
Stage.align = 'TL';
System.security.allowDomain( '*' );
System.security.allowDomain( 'www.youtube.com' );
System.security.allowDomain( 'youtube.com' );
System.security.allowDomain( 's.ytimg.com' );
System.security.allowDomain( 'i.ytimg.com' );
this.parent = parent;
init();
}
private function init():Void
{
var playerHolder:MovieClip = parent.createEmptyMovieClip( 'playerHolder', parent.getNextHighestDepth() );
bridge = new SWFBridgeAS2( BRIDGE_NAME, this );
bridge.addEventListener( 'connect', this );
player = new YouTubePlayer( playerHolder );
player.addEventListener( YouTubePlayerEvent.PLAYER_ENDED, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_PLAYING, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_PAUSED, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_BUFFERING, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_QUEUED, Delegate.create( this, sendEvent ) );
player.addEventListener( YouTubePlayerEvent.PLAYER_NOT_STARTED, Delegate.create( this, sendEvent ) );
}
private function sendEvent(e:YouTubePlayerEvent):Void
{
bridge.send( 'sendEvent', e.type );
}
public function playVideo(videoId:String, playerWidth:Number, playerHeight:Number, autoPlay:Boolean, pars:String, chromeless:Boolean):Void
{
player.autoPlay = ( autoPlay !== false ? true : false );
player.chromeless = ( chromeless ? chromeless : false );
player.pars = ( pars ? pars : player.pars );
player.playerWidth = ( playerWidth ? playerWidth : player.playerWidth );
player.playerHeight = ( playerHeight ? playerHeight : player.playerHeight );
player.init( videoId );
}
public function resizePlayer(width:Number, height:Number):Void
{
player.resizePlayer( width, height );
}
public function stopVideo():Void
{
player.stop();
}
}
Step 13 - Using the Wrapper
We're on the home straight now! So, to simply test this bad boy out, we just need to create a little class in AS3 to use this wrapper. I'd create a new project in your favourite AS3 editor and get a copy of your 'YouTubePlayerWrapper.swf' into your AS3 project folder. So then we simply create a class that loads the SWF, creates a connection and then sends vars for the playVideo() function. Don't forget to import gSkinner.com SWFBridge into the AS3 code:
package
{
import com.gskinner.utils.SWFBridgeAS3;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLRequest;
[SWF( width='600', height='400', frameRate='30', backgroundColor='#000000' )]
public class App extends Sprite
{
public static const BRIDGE_NAME:String = 'YouTubePlayerWrapperBridge';
private var player:Loader;
private var bridge:SWFBridgeAS3;
private var videoId:String;
private var loaded:Boolean;
public function App()
{
init( 'f8nNOQOh7dc' );
}
public function init(videoId:String):void
{
this.videoId = videoId;
if ( !loaded )
{
var request:URLRequest = new URLRequest( 'assets/swf/YouTubePlayerWrapper.swf' );
player = new Loader();
addChild( player );
player.contentLoaderInfo.addEventListener( Event.INIT, handlePlayerLoadedComplete );
player.load( request );
}
else
{
handlePlayerLoadedComplete();
}
}
public function play(videoId:String):void
{
bridge.send( 'playVideo', videoId, stage.stageWidth, stage.stageHeight, false, null, false );
}
public function stop():void
{
bridge.send( 'stopVideo' );
}
public function handlePlayerLoadedComplete(e:Event=null):void
{
if ( bridge )
{
handleBridgeConnect();
}
else
{
bridge = new SWFBridgeAS3( BRIDGE_NAME, this );
bridge.addEventListener( Event.CONNECT, handleBridgeConnect );
}
}
public function sendEvent(e:String):void
{
trace( e );
}
private function handleBridgeConnect(e:Event=null):void
{
loaded = true;
play( videoId );
}
}
}
This is code that you should understand, but just a quick run through: the main function that loads the player is called init(), I've put this in the constructor so that it actually loads a video rather than waiting for it to be fired. The init() function places the video ID within the class's variable, it then checks to see if the player has already been loaded. If it has, it then continues to send a command via the connection, otherwise it just loads it using Flash's standard Loader. Once the player has loaded and initialised, we then create the connection and once that's ready, pass the initial video ID to the player. There we have our YouTube Player available as an AS3 component!
Conclusion
So there we have our AS3 YouTube Player Component, but the fun shouldn't stop there. Remember that the AS2 wrapper passes all events up to the local connection, I've left the sendEvent() to just trace the event as you can now customise it to do your own doing. I would, for example, get it to dispatch events and that would help a lot when it comes to coding properly within AS3. Enjoy.



Uhn.. Nice transformation!
You can download youtube videos with Bywifi (Video Streaming Downloader). Bywifi is a free program for downloading, transcoding and accelerating video streaming.
Wrong url for source files … ;)
Aah, the dreaded missing link… Thanks for the heads up!
Excellent tutorial!!
Didn’t realize you could do this. Thanks! Also, excellent choice of thumbnail video.
You could make a tutorial, how to make our own players!
That yeahh, that wold be great!! :)
Don’t worry, I’m currently writing a flash video player for the web site 1click2fame.com and I’ll be posting the write up and a tutorial on my blog: http://www.ahmednuaman.com
As promised, here’s a blog (with code) about how to create an FLV player: http://ahmednuaman.com/blog/2009/06/22/creating-a-video-player-in-actionscript-3/
FYI to see examples of where this is used, check out:
http://youtube.com/laurencemills
http://youtube.com/3dcarouseldemo
http://youtube.com/perspectivecarousel
http://www.google.com/ig/adde?moduleurl=cs-stage5.tangozebra.com/80364/ahmed/Player.xml&source=imag
wow great tutorial and super funny video :p
http://www.lostinactionscript.com/blog/index.php/2007/10/13/flash-you-tube-api/
Great tutorial. You choice of example video is funny, but pretty distasteful. May be a bit embarrassing for those of us at work, or with moral fiber lol!
My bad! Didn’t mean to offend you! It was just to illustrate that you could easily trigger auto HD/HQ and it’s a bit of a funny vid! Hope no offence was caused!
Hey,
I tried your tutorial…with the exception that I need it to be completely removed when i move to a different area…
So i have a video gallery with the list of video gallery. now it works fine untill i move from the video gallery to say the photo gallery so on a button i have
youTubePlayer.destroyPlayer(); gotoAndPlay(‘photos’); as an button event which is really advancement in the timeline…
and no dice… i run this in the middle of a video playing and the video is still playing(well i still hear the audio)…what u recommend i do?
concerning the above comment…i believe i was not as explanitory… i made a function destroyPlayer in App.as
I am testing locally.
oh by the way…can i get the CS3 files?
is it also worth mentioning that the App.as is tied to a movieclip on the timeline?
ok so i moved it as a authored instance and made it dynamic… what i also did was put in a function removeVideo on the time that will
stop the player…destroy the player…remove the moveclip instance… no dice man… time i went back to re-instanciate it it crashed….
Sorry mate I don’t think your script works man….
firstly you cant play more than one instance of it in a browser…
secondly the stopVideo doesn’t work
third Im not sure but removing it doesn’t end there. Nore would the destroyVideo… something seems to be keeping it alive so to speak…
nice try though mate :-)
Hi Kendall, sorry to hear that! Here are a few points:
1. Since it’s using local connection, you can only have one instance per browser window, it’s just how Flash Player is.
2. The destroying of the video player happens in AS2 as it’s much easier, what issues are you having? Compiling in the Flash IDE is bad as the IDE debug player can’t handle it, that’s why it’s better to debug in the browser and use Logger() or to just use Flex Builder or FDT
What are you trying to do?
I’ve got another tut coming out soon on creating a gadget with the YouTube player, so watch this space.
Well I’m doing a flash website for which and area of the website has to deal with flash video. I am using youtube as a host and using the api to show video within the flash website. The problem that I seem to be having is only when I need to leave the video area… whether it be in the middle of a video playing or any other situation. When I come back to the video gallery and trying to play a video. For reasons I cannot load the video. I can load another video on first load of the video gallery and load video consecutively. But lets say I need to leave the video area and go to another area of the website…what do I do?
destroy the player?
stop the player?
unload the player?
in the Apps.as I created a “removeVideo” function for which on executed tried “bridge.send(‘destroyPlayer’);” no dice
tried to stop the video…no dive
what i did was a init(null). This seemed to work but in trying to load another video. it didn’t work
when i have to go to another area of the website I’m either advancing the playhead or loading another clip…thus removing the video gallery…thus removing the player. I guess the local connection is not being closed properly.
I have the source files but can’t open the source files as I have CS3
Why don’t you simply stop the player rather than destroying it?
Because even if i stopped the player…if i moved on to another frame and come back to it later…I STILL am unable to load a movie or even continue on for that matter
I think what is happening is that even when i destory it….there is still some reminiance of the local connection…and its like i can’t load a new one…. i dunno i cant open you fla cause im using CS3
Oh so you’re using the Flash IDE? Scripting on frames right? Hmmm, ok, well, why don’t you create everything on the first frame of the movie, rather than destroying the player, just stop it and hide it. The player has the ability to load more movies, just like the tutorial shows, so there’s no need to destroy it and reload it. If you want, you can post your code somewhere and I can have a look.
PS, move out of the IDE and start coding without the stage!
welll to begin this video area is just a part of the whole application. It is a whole separate swf to be loaded into the main movie. For testing purposes I’m just concentrating on this aspect and just developed it as a swf entity itself. I’m actually no using the IDE but debugging using the browser and setting a text field with debugging information. I need to destroy the player cause in the overall application I am loading and unloading different swfs…
I have been trying another wrapper but to no avail either…
http://www.ovidiudiac.ro/blog/2009/03/youtube-as3-wrapper-documentation/
my code is in the comments…both wrappers have the same principle…what I like about yours is that I have acccess to the local connection. But I’m not sure what is causing it to “stall” so to speak.
to see what I am doing take a look here
http://www.brotherresistance.com/gallery_movie.html
click on the video link and click on any of the videos present…
click on the other videos just to see that it is loading different movies
it works yes?
now click on the photos link… This will use the destroy and reload. now try loading clip…
what are your thoughts on this?
It makes my eyes bleed!
Nevertheless, when I click on a thumbnail and then click on another thumbnail in the background, the player loads fine which suggests that whichever wrapper you’re using is fine, it’s just your code that’s acting weird.
Now I’m concerned that you may be trying to reload the player rather than stopping and hiding it. It’s best to construct the player on frame 1 rather than waiting til the SWF reaches a frame, constructing, then going back to that frame.
ITs not about hiding or stopping the player….at the end of the day its part of a loaded swf…which will be unloaded when i go to another section of the website. Ill have to unload that entire swf and load another swf into that area…so I need to be sure that the video can be removed and reloaded in that event situation
But there’s no need to unload it and then reload it. AS3 has a different garbage collection strategy and it works out better to just hide it, check this out: http://www.gskinner.com/blog/archives/2006/06/as3_resource_ma.html
I simply suggest stopping it, then making it invisible, nothing wrong with that eh?
Hi
I would like to thank you for the tutorial.
I have played around with your app.as file and I noticed that there are various random errors that are occurring such as trying to access other local files, errors opening other URL’s. I was wondering if this is normal, or is there a way that I can fix these errors?
Also is there a way to disable the stars and other youtube assets?
Here’s an explanation of why and how to fix it: http://ahmednuaman.com/blog/2009/06/23/security-sandbox-violation-getting-you-down/
Ok, a lot of people have asked me about switching videos, here’s a quick write up on how to do it: http://ahmednuaman.com/blog/2009/06/29/the-youtube-player-api/
Thanks for the great tutorial.
hi,
does anybody know how to create a flash app like this? http://www.perkstoveland.com/demos/youtube.swf
I’ve google lots of youtube wrapper, but non is able to play multiple videos at the same time in one flash except this “claimed” one, which the author said is able to use diff ‘id’ to play multiple youtubes at the same time and has no limitations. I’ve tested and it’s true, just don’t know how it made it. I made one too with diff ids, but after testing only one video is allowed to play at a time. anyone has idea or wrapper like this?
it doesn’t play multiple videos for me…
I’m a newbie. Can you please provide the code to include in the AS3 SF file to use this class. That would help a lot. Thanks.
keep getting the following error: Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.
Thanks
Just do var player:App = new App(); There’s more info here: http://ahmednuaman.com/blog/2009/06/29/the-youtube-player-api/
Hi,
I’ve gotten to step 10 and I preview it in flas cs3 and the video comes up with no hd option and I get these errors as I press play and other functions
*** Security Sandbox Violation ***
SecurityDomain ‘http://s.ytimg.com/yt/swf/cps-vfl107668.swf‘ tried to access incompatible context ‘http://www.youtube.com/v/R7yfISlGLNU&autoplay=0&loop=0&rel=0&showsearch=0&hd=1‘
*** Security Sandbox Violation ***
SecurityDomain ‘http://s.ytimg.com/yt/swf/cps-vfl107668.swf‘ tried to access incompatible context ‘http://video-stats.video.google.com/s?ns=yt&docid=R7yfISlGLNU&el=embedded&ps=default&vid=iBAMG0owHbdtmLnm6W1GyBZsRnE7BOS7C&fexp=903201&eurl=file%3A%2F%2F%2FBACK%2520UP%2FFlash%2520Web%2520design%2Fyoutube%2520player%2Fytplayer%2Eswf&cr=US&hbd=4290104&hbt=56.125&rt=0.815999999999999&plid=AARut0guhNCdlzpj&fmt=5&md=1&sd=B4A7D0C02&w=545&h=375&bt=0.492000000000001&bd=246160&bc=252274&len=188.131&st=0.183&et=0.183&fv=MAC%209%2C0%2C45%2C0‘
*** Security Sandbox Violation ***
Connection to file:///BACK%20UP/Flash%20Web%20design/youtube%20player/ halted – not permitted from http://i3.ytimg.com/vi/R7yfISlGLNU/hqdefault.jpg
– Remote SWFs may not access local files.
*** Security Sandbox Violation ***
Connection to file:///BACK%20UP/Flash%20Web%20design/youtube%20player/ halted – not permitted from http://i3.ytimg.com/vi/R7yfISlGLNU/hqdefault.jpg
– Remote SWFs may not access local files.
I could use some help, thanks.
Check this post out: http://ahmednuaman.com/blog/2009/06/23/security-sandbox-violation-getting-you-down/
good morning sir this i am new comer i want reference .what way i search then i understand. demo i want bec can do that orginal file refer to create work and get new idea so
Hi, thanks for this tutorial, I’ve used it to make this http://www.kongregate.com/games/locos/youkongregate
I believe YouTubePlayerWrapper.as has to be compiled into a swf. How is this done? I am using MTASC but I am getting numerous errors which I am trying to resolve, one by one. For example the compiler does not seem to recognize the global function removeMovieClip. I am ready to give up using MTASC.
Is there a better way to create the swf file?
After some tweaking to the Actionscript 2.0 files,YouTubePlayerWrapper.as and YouTubePlayer, I finally got the MTASC compiler to generate a swf file, but the wrapper still does not work. Apparently, the bridge (SWFBridgeAS3) is not creating a valid connection. Any help would be appreciated.
For anyone interested, here are the steps I followed to generate the swf file with the MTASC compiler.
MTASC mainly complained about code in the class YouTubePlayer, which is instantiated in the YourTubePlayerWrapper class.
The compiler objected to the global functions removeMovieClip and unloadMovie. I replaced these with the instance method calls,
(parent[ players ]).removeMovieClip(); and ( parent[players ]).removeMovieClip();
The compiler did not like mx.utils.Delegate, so the various calls to the Delegate.create function created a problem (in both the YouTubePlayer and YouTubePlayerWrapper classes).
Apparently, most of the mx components, including mx.,utils.Delegate, are not directly supported by MTASC. After removing all references to the mx.utils.Delegate and any calls to its create method, I add the following class and replaced calls to Delegate.create with calls to EventDelegate.create:
class EventDelegate {
private function EventDelegate () {};
public static function create (scope, method:Function):Function {
var params:Array = arguments.splice (2, arguments.length-2);
var proxyFunc:Function = function ():Void {
method.apply(scope, arguments.concat (params));
}
return proxyFunc;
}
}
(see: “http://lists.motion-twin.com/pipermail/mtasc/2005-April/001602.html”)
Lastly, MTASC complained about the following syntax in the loadVideo function:
loader.addListener({ onLoadInit: loadInit() });
I replaced this with:
loader.addListener(this);
and changed the name of YouTubePlayer’s loadInit method to onLoadInit.
After these changes I was able to use MTASC to generate YouTubePlayerWrapper.swf.
Thanks Ahmed, this was a very helpful tutorial. The one snag I ran into was figuring out how to access getter functions on the AS2 player through the bridge. Can you demonstrate how, for instance, you would access the getDuration method? Thanks!
Hello .. My name is Rodrigo. I have a very big doubt on that player on youtube in flash … I tried to adapt it to AS3 but I could not … Could you get me up and running in AS3?
Thanks Ahmed, this is a great tutorial.
However now I’m having trouble having it work on firefox. Is there any security issue that I’m overlooking?
It works fine in safari.
this is good post
great, this what i’m looking for. nice tutorial :)
Hi, thanks for the great tutorial….but now that the YouTube Player API has been updtaed to AS3,are you going to have a tutorial on using it? It would be great. I can’t make it work correctly based on the official documentation.Thanks
Tnx a lot – was looking for that – and it’s great.
Only one problem, couldn’t understand how to make it work with HQ, can you please give an example for that – I would be very grateful. High Quality is the new format : )
Thanks, Shefy
Even with the Security.allowdomain I still get sandbox errors.. any ideas?
Hi,
Loved this tutorial.
Can you please give an example, how to open you tube movie on HQ?
thanks, Shefy
hello how can i change the layout can you upload the fla form App.swf please
Finally found some current all AS3 code from this tutorial’s authors website. No need for AS2 at all. Couldn’t find anything that made as much sense out there until I found these current updates: YouTubePlayerAS3.as and YouTubePlayerEvent.as at http://http://github.com/ahmednuaman/AS3
Seriously! I’ve been seeking google for hours in this and i also lastly think it is listed here!