videos

Build a Dynamic Video Player with ActionScript 3: Part 1 of 3

This entry is part 1 of 3 in the series Build a Dynamic Video Player with ActionScript 3.0

Almost every Flash developer has had to make a video player at some point. There are quite a few different ways of doing this; some people use the built in NetStream Class and some use the FLVPlayback component in Flash. Either way will work, but we are going to use the NetStream Class because of how much lighter it is and what you can do with it.

This is a large tutorial that will be broken down to three parts. Each part will build off the previous one until we have our final result. Our player will be able to use an XML file to populate three galleries with an unlimited amount of categories, and an unlimited amount of videos in each category.

Let’s take a quick look at what we will be building in each part of this series:

Part 1

  • File setup, organize files and folders.
  • Understanding how the start file is set up.
  • Position items on the stage for startup stage resize.
  • Global rollover and rollout functions.
  • Set up our Net Stream class.
  • Get the video playing.
  • Add preloader functionality.
  • Set up controls for video playback. These include a play button, pause button, stop button, video timeline scrubber, and volume scrubber.

Part 2

  • Setup our video thumbnails, category thumbnails, and featured video thumbnails.
  • Write the XML file.
  • Load the XML file in Flash.
  • Create category items in the right sidebar.
  • Preload category item thumbnails.
  • Gallery button functionality for right sidebar.
  • Create video items in the right sidebar.
  • Preload video item thumbnails.
  • Build a dynamic vertical scrollbar that shows when necessary and hides when it is not needed.
  • Play selected videos.

Part 3

  • Display the current time and total time below the player.
  • Home button functionality.
  • Set our video’s width and height.
  • Center our video in the player window.
  • Check the XML file for any featured videos.
  • Add featured video items to Featured sub bar.
  • Preload featured video item thumbnails.
  • Add a dynamic horizontal scrollbar for the featured sub bar.

I did mention this in the classes, but I’d like to thank some people for their help with this tutorial.

Step 1: Understanding the Source Files

The fist thing to do is to download the source files I provided. This is very important as I am not going to go over what things are named and how I set up the file. I will however give brief overviews of specific things I did (like how I made my buttons and other things that are important). Basically, I put all the objects on the stage, organized the library, created movieclips for everything, properly named all the movieclips on the stage and created button rollovers for all necessary buttons. Along with creating and exporting the necessary movieclips.

The next thing to note is how I set up my folders for this project. You should create a folder on your desktop named whatever you want (eg.my_AS3_Video_Player). Open this folder, drop the the “flv” folder you downloaded, along with the “playlist.xml” and “theater.fla” files. The “theater.fla” file is your start file. The “playlist.xml” file is the xml file that is pre written. Inside the “flv” folder you will see all the videos we will be using, along with a “thumbs” folder which contains 3 other folders. These three folders each have a thumbnail image of all the videos at different sizes.

NOTE: If you do not want to use the videos I provided you can use your own, but make sure they have an audio track in them or else you will not be able to tell if the audio scrubber is working correctly.

Your start file should already be linked to the output folder when you open up the “theater.fla” file. If you know how this works then ignore the next sentence. If you do not know how this works click on file > publish setting. You should be on the formats tab. Here you enter “../output/theater.swf” for your .swf and if you want to publish the .html you enter “../output/theater.html”. You also need to go to the html tab and select percent for the dimensions. Otherwise your file will not center on the stage correctly.

The third thing you need to do is download the Caurina Tweener Class. Once this is downloaded you need to open the zip file and copy the caurina folder in your “src” folder so we can use it for our animations.

Page Setup

Step 2: Taking Note of Your Stage and Items

Now that you are set up with everything in place it’s time to look through the file. The first thing to take note of here is your stage size 850×580, this is not really that important as it will be set depending on your window size. It is however the minimum size your window will go before cropping part of the player. Second is the 4 layers on the stage. The top layer is where we will be writing our code. The second layer is where we will have video controls, and the video. The third layer is where we will have the playlist with different galleries, categories, and videos. The fourth layer is where we will place the featured videos that are set with a simple true or false in the xml.

The other thing I would like to point out is the items we will be adding to this file based on our xml. We will be populating them at runtime from our library. There are 3 items that are named featuredItem_mc, videoItem_mc, and categoryItem_mc. They are found in the folders in the library and are already set to be exported when you publish.

Other than that, the buttons along with rollovers and dynamic text are already set up for you. Feel free to customize if you want, but we will go over those steps later.

Library Items

Step 3: Let’s Start Writing Some Code!

Let’s import the necessary classes we will use for our tweens. We will also set our stage to align to the top left and set it to not scale. In the main timeline click on the AS3 layer and type the following:

import caurina.transitions.*; // import the tweener class for our transitions
import caurina.transitions.properties.FilterShortcuts; //  import the tweener filter shortcuts class
stage.scaleMode = StageScaleMode.NO_SCALE; // tell the stage not to scale our items
stage.align = StageAlign.TOP_LEFT; // set the stage to center in the top left of the .swf file
FilterShortcuts.init();  // initialize the filter shortcuts for our tweener class

Step 4: Name Objects on Stage

Now let’s add some naming variables so we don’t have to type such long instance names.

var videoBox:MovieClip = player_mc;  // this will target the player mc on the main stage
var sidebarBox:MovieClip = rightSidebar_mc; // target the right sidebar mc on the main stage
var featuredBox:MovieClip = featuredBox_mc; // target the featured box mc on the main stage
var featuredBoxBg:MovieClip = featuredBox_mc.featuredBoxBg_mc;  // target the featured box's background in the featured box

Step 5: Center Content on Start up

Below what we have written so far, type:

setMyStage(); // listener for page startup
function setMyStage():void
{
	videoBox.x = stage.stageWidth / 2 - (featuredBoxBg.width / 2);  // position videoBox's x location
	videoBox.y = (stage.stageHeight / 2 - videoBox.height / 2) - featuredBoxBg.height / 2; // position videoBox's y location
	sidebarBox.x = (stage.stageWidth / 2 + 92);  // position sidebarBox's x location
	sidebarBox.y = videoBox.y;  // position sidebarBox's y location based on the videoBox's y location
	featuredBox.x = videoBox.x;  // position featuredBox's x location based on videoBox's x location
	featuredBox.y = videoBox.y + videoBox.height + 4; // position featuredBox's y location based on videoBox's y location
}

Now if you test your movie your content will be centered in the middle of your .swf file. But not if you resize your .swf. So let’s take care of that.

Step 6: Add Stage Resize Listener and Function

Next we need to take care of what happens when you change your .swf width and height or your browser size. To do this type the following code below the setMyStage function:

NOTE: I usually put all my listeners together near the top of the code and all my functions together in the bottom. Some people do this in reverse. There is no perfomance benefit, but it does help to keep your file more organized. From here on whenever I add a listener I will be putting it below the last listener at the top and when I add a function I will be placing it below the last function on the bottom of the page. Oh, and you should also always place your variables at the top one after another.

stage.addEventListener(Event.RESIZE, myResizeEvent);  // add a listener to the stage to run a function when the stage width or height changes
function myResizeEvent(event:Event):void  //  run the function to handle stage width and height resize
{
	videoBox.x = stage.stageWidth / 2 - (featuredBoxBg.width / 2);
	videoBox.y = (stage.stageHeight / 2 - videoBox.height / 2) - featuredBoxBg.height / 2;
	sidebarBox.x = (stage.stageWidth / 2 + 92);
	sidebarBox.y = videoBox.y;
	featuredBox.x = videoBox.x;
	featuredBox.y = videoBox.y + videoBox.height + 4;
}

Now if you test your .swf file it will center on startup and if you change the width or height it will stay centered as well.

Step 7: Variables for Video Items on the Stage

Again let’s add some vars so our instance names are not so long.

var playBtn:MovieClip = player_mc.playBtn_mc;  //  targets the play button in the player
var pauseBtn:MovieClip = player_mc.pauseBtn_mc;  //  targets the pause button in the player
var stopBtn:MovieClip = player_mc.stopBtn_mc;  //  targets the stop button in the player
var videoBlackBox:MovieClip = player_mc.videoBlackBox_mc;  //  targets the black background box in the player
var videoPreloader:MovieClip = player_mc.videoPreloader_mc;  //  targets the video preloader in the player
var videoTitleTxt:TextField = player_mc.VideoTitle_txt;  //  targets the dynamic text that will display the video title
var videoTimeTxt:TextField = player_mc.videoTime_txt;  //  targets the dynamic text layer that will display time played and total time
var videoThumb:MovieClip = player_mc.videoTrack_mc.videoThumb_mc;  //  targets the video scrubber thumb
var videoTrackProgress:MovieClip = player_mc.videoTrack_mc.videoTrackProgress_mc;  //  targets the video progress bar
var videoTrackDownload:MovieClip = player_mc.videoTrack_mc.videoTrackDownload_mc;  //  targets the video download percentage bar
var volumeThumb:MovieClip = player_mc.volumeSlider_mc.volumeThumb_mc;  // targets the volume scrubber thumb
var volumeTrack:MovieClip = player_mc.volumeSlider_mc.volumeTrackFull_mc;  //  targets the volume scrubber track percentage bar

Step 8: Button Rollover and Rollouts

Here we will be using the same function for all of our rollovers and rollouts. The reason for this is that it reduces code, plus all the buttons we’ll be using will be doing the same thing, so why not just make one function that is reusable?

playBtn.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
playBtn.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
pauseBtn.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
pauseBtn.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
stopBtn.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
stopBtn.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
videoThumb.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
videoThumb.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
volumeThumb.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
volumeThumb.addEventListener(MouseEvent.MOUSE_OUT, btnOut);

Step 9: Global Functions for Buttons

Let’s add the two functions that allow us to add rollover and rollouts to any button which is set up as described in the next step.

function btnOver(event:MouseEvent):void
{
	event.currentTarget.gotoAndPlay("over");  //  Targets the current movieclip when the mouse rolls over it and tells it to go to the over label keyframe and play
}
function btnOut(event:MouseEvent):void  //  Targets the current Movieclip when the mouse rolls over it and tells it to go to the out label keyframe and play
{
	event.currentTarget.gotoAndPlay("out");
}

Now if you test your movie the buttons will change when you roll over and go back to their original state when you roll out.

Step 10: Rollover and Rollout Functionality

Let’s take a second to see how I create my buttons and how all the buttons and movieclips in this tutorial are set up. You don’t need to perform this step, but if you want to follow along go to the playBtn_mc movieclip in the player_mc movieclip and open it.

The first thing to do is design your button. Next, convert it to a movieclip and give it an instance name. If it’s a play button I would name it something like “playBtn_mc”. Give it the correct instance name. Lock these layers so you don’t accidentally place symbols on them. Once you do that open up the movieclip and create two layers on top of everything. Name one layer “AS3″ and the second layer “Labels”.

On the first frame of the AS3 layer open your ActionScript panel and type “stop();”. Do the same on the 10th frame. On the second frame of the Labels layer create a keyframe and highlight it. Now go to your properties panel and in the Name field type “over”. Now go to the 11th frame on the Labels layer and create another keyframe. Select each element separately and convert to a MovieClip. Once completed, select all and separate to layers. You can use the right-click (context) menu, or setup a keyboard shortcut. Since I’m constantly separating elements to layers I find it helpful to create a “Ctrl + D” shortcut [Command + D] on a Mac. (Note: the name of the layer will be based on the name you gave each symbol.)

Button Code And Labels

Don’t worry about giving them instance names, since we will just be tweening them. If you don’t convert each element you want to animate to a symbol, then Flash will create tweens in your library that become messy. Go to the 10th frame of the layer you want to tween and create a keyframe, then go to the 20th frame of the same layer and create another keyframe.

Now highlight all the layers frames and right-click. Select “create classic tween”. Don’t deselect just yet, go to the properties panel. Select the tween tab and enter 100. Now select the 10th frame of the layer and go to the properties panel and select the style tab. Here you can select what you want the current element to do. That’s it. You can also change how long the animation takes on rollover and rollout by moving where the stop actions are and the over/out label keyframes are.

Finished Button

This is how all the buttons are set up in this tutorial, so anytime you see a rollover or rollout this is how I did it. With the code from steps 7 & 8 and the button from this step you can create a button with rollover and rollout functionality in any project.

Step 11: Make Movieclips Behave Like Buttons

Let’s add buttonMode and mouseChildren to our buttons. Add this below your variables at the top of your code.

playBtn.mouseChildren = false;  //  makes the elements inside the targeted movie clip unselectable
playBtn.buttonMode = true;  // gives the hand cursor when you hover over the movieclip
pauseBtn.mouseChildren = false;
pauseBtn.buttonMode = true;
stopBtn.mouseChildren = false;
stopBtn.buttonMode = true;
videoThumb.mouseChildren = false;
videoThumb.buttonMode = true;
volumeThumb.mouseChildren = false;
volumeThumb.buttonMode = true;

Now all your buttons in the player_mc movie clip should have rollover and rollout functionality when you test your movie.

Step 12: Start Up

Here we will hide the video preloader, set the video title dynamic text field to be blank, along with zeroing out the video time dynamic text layer. Type the following code below the code in step 10:

videoPreloader.visible = false;
videoTitleTxt.text = "";
videoTimeTxt.text = "0:00 / 0:00";

Step 13: Setting Up Our NetStream Object

Here we will set up a variable that collects the current video from the xml and sets it to a string. We’ll also set the video height and width with a Number that will eventually change when we open a new movie. Add the following variables to the list of variables at the top of your code:

var currentVideo:String;  //  this string will be used to play the current video selected
var videoWidth:Number = 500;  // this will set the width of the video object and can be changed later on
var videoHeight:Number = 400;  //  this will set the height of the video object and can be changed later on
var duration:Number; //  we will use this later to get the duration of the video being played

Step 14: Create a Video Object

Now that we have all the functionality set up for the player, it’s finally time to get a video to start playing. We first need to create a video item, set its position and add it to the stage in the correct layer. Below everything in your ActionScript layer type the following:

var video:Video = new Video(videoWidth, videoHeight);  //  create a new Video item and set its width and height
video.x = 0;  //  position the video's x position
video.y = 0;  //  position the video's y position
videoBlackBox.addChild(video);  //  add the video item to the videoBlackBox movieclip in the player_mc movieclip

Step 15: NetConnection and NetStream Connection

Now we need to create a new NetConnection and link it to the new NetStream connection along with some listeners for the NetStream. Add this to your code:

var video:Video = new Video(videoWidth, videoHeight);  //  create a new Video item and set its width and height
video.x = 0;  //  position the video's x position
video.y = 0;  //  position the video's y position
videoBlackBox.addChild(video);  //  add the video item to the videoBlackBox movieclip in the player_mc movieclip

var nc:NetConnection = new NetConnection();  //  variable for a new NetConnection
nc.connect(null);  //  set the nc variable to null
var ns:NetStream = new NetStream(nc);  // create a variable for a new NetStream connection & connect it to the nc variable
ns.addEventListener(NetStatusEvent.NET_STATUS, myStatusHandler);  //  add a listener to the NetStream to listen for any changes that happen with the NetStream
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);  //  add a listener to the NetStream for any errors that may happen

video.attachNetStream(ns);  // attach the NetStream variable to the video object
var newMeta:Object = new Object();  // create a new object to handle the metaData
newMeta.onMetaData = onMetaData;  //  when we recieve MetaData, attach it to the newMeta object
ns.client = newMeta;  // attach the NetStream.client to the newMeta variable
ns.bufferTime = 5;  // set the buffer time to 5 seconds

Step 16: NetStream Functions and Buffer Video

Now let’s add the functions to handle what happens when there is a specific video event or an error with the connection. We will also handle the buffer for the video. Add the code below:

function asyncErrorHandler(Event:AsyncErrorEvent):void
{
	//trace(event.text);  // this will handle any errors with video playback
}
function myStatusHandler(event:NetStatusEvent):void
{
	//trace(event.info.code);  // this will handle any events that are fired when the video is playing back
	switch(event.info.code)  //  switch statement to handle the various events with the NetConnection
	{
		case "NetStream.Buffer.Full":  //  when our buffer is full fire the code below
			ns.bufferTime = 10;  // set buffer time to 10 seconds
			Tweener.addTween(videoPreloader, {alpha:0, time:.3});  // tween videoPreloaders alpha to 0
		break;
		case "NetStream.Buffer.Empty":  //  when our buffer is empty fire the code below
			ns.bufferTime = 10;  // set buffer time to 10 seconds
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});  // tween videoPreloaders alpha to 1
		break;
		case "NetStream.Play.Start":  //  when our video starts playing we fire the code below
			ns.bufferTime = 10;  // set the buffer time to 10 seconds
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});  //  tween videoPreloaders alpha to 1
		break;
		case "NetStream.Seek.Notify":  // when you seek with the scrubber it sends a notify signal of the time
			ns.bufferTime = 10;  // set the buffer time to 10 seconds
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});  //  tween videoPreloaders alpha to 1
		break;
		case "NetStream.Seek.InvalidTime":  // when you release the scrubber ahead of the video that has been loaded, you get this error.  it will jump you back to the last frame that has been loaded
			ns.bufferTime = 10;  // set the buffer time to 10 seconds
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});  //  tween videoPreloaders alpha to 1
		break;
		case "NetStream.Play.Stop":  // when you reach the end of the video
			Tweener.addTween(videoPreloader, {alpha:0, time:.3});  //  tween videoPreloaders alpha to 0
			ns.pause();  // pause the video
			ns.seek(1);  // seek the video to the first frame
		break;
	}
}
function onMetaData(newMeta:Object):void
{
	//trace("Metadata: duration=" + newMeta.duration + " width=" + newMeta.width + " height=" + newMeta.height + " framerate=" + newMeta.framerate);  // traces what it says
	duration = newMeta.duration;  // set the duration variable to the newMeta's duration
}

Step 17: Play the Video!

Finally, add this line of code to play the video:

ns.play("flv/bsu-football-open.flv");  //  tell the netstream what video to play and play it

Now if you test your video it should play. It will be scaled weird because we have not used the xml file to set the width and height. Don’t worry about this yet, we will handle that problem later. None of the buttons will work and the scrubber bar will not be working. That’s because we haven’t linked them yet, so let’s do that now.

Step 18: Add Listeners for Buttons

Now let’s add some listeners for our buttons so we can get some functionality working.

playBtn.addEventListener(MouseEvent.CLICK, playBtnClick);  //  add a click listener to the playBtn
pauseBtn.addEventListener(MouseEvent.CLICK, pauseBtnClick);  // add a click listener to the pauseBtn
stopBtn.addEventListener(MouseEvent.CLICK, stopBtnClick);  // add a click listener to the stopBtn

Step 19: Add Playback Functions

function playBtnClick(event:MouseEvent):void
{
	ns.resume();  //  tell the NetStream to resume playback
}
function pauseBtnClick(event:MouseEvent):void
{
	ns.pause();  //  tell the NetStream to pause playback
}
function stopBtnClick(event:MouseEvent):void
{
	ns.pause();  //  tell the NetStream to pause playback
	ns.seek(0);  //  tell the NetStream to go to the first frame of the video
}

Now if you test your movie and click the pause button, your video should pause. If you click the stop button your video should jump to the first frame and pause. If the video is paused or stopped you can click the play button to resume the video. Now let’s get the timeline and volume scrubbers to work.

Step 20: Add Volume Scrubber Variables and Listeners

We need to add some variables to our code so we can get our volume scrubber working.

var videoSound:SoundTransform;  //  variable to control the global sound in your movie
var volumeBounds:Rectangle;  //  variable to set the volume scrubber bounds

volumeThumb.addEventListener(MouseEvent.MOUSE_DOWN, volumeScrubberDown);  add a MOUSE_DOWN listener to the volume scrubber thumb

Step 21: Add Volume Scrubber Code

Let’s add all the code to get the scrubber to work.

videoSound = new SoundTransform();  // creates a new SoundTransform object
videoSound.volume = 1;  //  sets the SoundTransform object to 1 which is 100%
ns.soundTransform = videoSound;  //  links the video to the SoundTranform object
function volumeScrubberDown(event:MouseEvent):void
{
	volumeBounds = new Rectangle(0,0,75,0);  //  sets the bounds for the scrubber
	volumeThumb.startDrag(false, volumeBounds);  //  when you click and drag the volumeThumb movieclip it runs this function
	stage.addEventListener(MouseEvent.MOUSE_UP, volumeThumbUp);  //  add listener to the stage for when your mouse releases the click
	stage.addEventListener(MouseEvent.MOUSE_MOVE, volumeThumbMove);  //  add listener to the stage for when your mouse moves
}
function volumeThumbUp(event:MouseEvent):void
{
	volumeThumb.stopDrag();  //  stops the volumeThumb from being dragged
	stage.removeEventListener(MouseEvent.MOUSE_UP, volumeThumbUp);  //  remove this listener from the stage
	stage.removeEventListener(MouseEvent.MOUSE_MOVE, volumeThumbMove);  // remove this listener from the stage
}
function volumeThumbMove(event:MouseEvent):void
{
	volumeTrack.width = volumeThumb.x;  //  sets the blue bar in the volumeScrubber to the width of where the scrubber is
	videoSound.volume = (volumeThumb.x) / 50;  //  sets the volume of the video to a percentage of the track depending on where your volumeThumb.x location is
	ns.soundTransform = videoSound;  //  actually transform the volume.
}

Test your movie now. You can scrub the volume thumb and hear the audio change!

Step 22: Scrubber Variables and Listeners

We need to add some more variables for the video timeline scrubber. Type the following in the vars section of your code:

var videoInterval = setInterval(videoStatus, 100);  // duration between intervals, in milliseconds
var amountLoaded:Number;  //  variable to tell us how much of the video has been loaded
var scrubInterval;  //  variable for the timeline scrubber

videoThumb.addEventListener(MouseEvent.MOUSE_DOWN, videoScrubberDown);

Step 23: Add Functions for the Video Scrubber

Let’s add the functions that will allow us to scrub the timeline and also move the scrubber bars to track amount played and amount loaded.

function videoStatus():void
{
	amountLoaded = ns.bytesLoaded / ns.bytesTotal;  //  set our amountLoaded variable to a number that is the bytesLoaded divided by the bytesTotal of the video
	videoTrackDownload.width = amountLoaded * 340;  // sets the width of the videoTrackDownload bar to the amountLoaded var and multiply it by the track width.
	videoThumb.x = ns.time / duration * 340;  //  move the videoThumb x position to the location on the track that is linked to the current video timeline
	videoTrackProgress.width = videoThumb.x;  // changes the width of the videoTrackProgress bar to the x location of the videoThumb
}
function videoScrubberDown(event:MouseEvent):void
{
	var bounds:Rectangle = new Rectangle(0,0,340,0);  //  sets the bounds for the video scrubber based on the width of the scrubber
	clearInterval(videoInterval);  //  clear our videoInterval so we can scrub 
	scrubInterval = setInterval(scrubTimeline, 10);  //  sets the scrubTimeline listener to update the video
	videoThumb.startDrag(false, bounds);  //  starts to drag the videoThumb within the bounds we set
	stage.addEventListener(MouseEvent.MOUSE_UP, stopScrubbingVideo);  //  add listener to the stage to listen for when we release the mouse
}
function scrubTimeline():void
{
	ns.seek(Math.floor((videoThumb.x / 340) * duration));  //  seeks the video to the frame related to the videoThumb's x location on the scrubber track
}
function stopScrubbingVideo(Event:MouseEvent):void
{
	stage.removeEventListener(MouseEvent.MOUSE_UP, stopScrubbingVideo);  // removes this listener when we release the mouse
	clearInterval(scrubInterval);  //  clears the scrubInterval listener so the video will resume playback
	videoInterval = setInterval(videoStatus, 100);  //  set the videoStatus interval to move the videoThumb with the video playback percentage
	videoThumb.stopDrag();  //  tells the videoThumb to stop draggin with our mouse
}

Your final code for this lesson should look like this:

//////  IMPORT CLASSES AND SET STAGE PROPERTIES  //////
import caurina.transitions.*;
import caurina.transitions.properties.FilterShortcuts;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
FilterShortcuts.init();

////// MAIN STAGE MOVIE CLIPS //////
var videoBox:MovieClip = player_mc;
var sidebarBox:MovieClip = rightSidebar_mc;
var featuredBox:MovieClip = featuredBox_mc;
var featuredBoxBg:MovieClip = featuredBox_mc.featuredBoxBg_mc;

////// VIDEO MOVIE CLIPS //////
var playBtn:MovieClip = player_mc.playBtn_mc;
var pauseBtn:MovieClip = player_mc.pauseBtn_mc;
var stopBtn:MovieClip = player_mc.stopBtn_mc;
var videoBlackBox:MovieClip = player_mc.videoBlackBox_mc;
var videoPreloader:MovieClip = player_mc.videoPreloader_mc;
var videoTitleTxt:TextField = player_mc.VideoTitle_txt;
var videoTimeTxt:TextField = player_mc.videoTime_txt;
var videoThumb:MovieClip = player_mc.videoTrack_mc.videoThumb_mc;
var videoTrackProgress:MovieClip = player_mc.videoTrack_mc.videoTrackProgress_mc;
var videoTrackDownload:MovieClip = player_mc.videoTrack_mc.videoTrackDownload_mc;
var volumeThumb:MovieClip = player_mc.volumeSlider_mc.volumeThumb_mc;
var volumeTrack:MovieClip = player_mc.volumeSlider_mc.volumeTrackFull_mc;

////// VIDEO VARS //////
var currentVideo:String;
var videoWidth:Number = 500;
var videoHeight:Number = 400;
var videoInterval = setInterval(videoStatus, 100);
var amountLoaded:Number;
var duration:Number;
var scrubInterval;
var videoSound:SoundTransform;
var volumeBounds:Rectangle;

////// FILE STARTUP //////
videoPreloader.visible = false;
videoTitleTxt.text = "";
videoTimeTxt.text = "0:00 / 0:00";
playBtn.mouseChildren = false;
playBtn.buttonMode = true;
pauseBtn.mouseChildren = false;
pauseBtn.buttonMode = true;
stopBtn.mouseChildren = false;
stopBtn.buttonMode = true;
videoThumb.mouseChildren = false;
videoThumb.buttonMode = true;
volumeThumb.mouseChildren = false;
volumeThumb.buttonMode = true;

////// SET STAGE //////
setMyStage();
stage.addEventListener(Event.RESIZE, myResizeEvent);

////// VIDEO EVENT LISTENERS //////
playBtn.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
playBtn.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
playBtn.addEventListener(MouseEvent.CLICK, playBtnClick);
pauseBtn.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
pauseBtn.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
pauseBtn.addEventListener(MouseEvent.CLICK, pauseBtnClick);
stopBtn.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
stopBtn.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
stopBtn.addEventListener(MouseEvent.CLICK, stopBtnClick);
videoThumb.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
videoThumb.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
videoThumb.addEventListener(MouseEvent.MOUSE_DOWN, videoScrubberDown);
volumeThumb.addEventListener(MouseEvent.MOUSE_OVER, btnOver);
volumeThumb.addEventListener(MouseEvent.MOUSE_OUT, btnOut);
volumeThumb.addEventListener(MouseEvent.MOUSE_DOWN, volumeScrubberDown);

////// VIDEO CODE //////
var video:Video = new Video(videoWidth, videoHeight);
video.x = 0;
video.y = 0;
videoBlackBox.addChild(video);
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, myStatusHandler);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
video.attachNetStream(ns);
var newMeta:Object = new Object();
newMeta.onMetaData = onMetaData;
ns.client = newMeta;
ns.bufferTime = 5;

function asyncErrorHandler(Event:AsyncErrorEvent):void
{
	//trace(event.text);
}
function myStatusHandler(event:NetStatusEvent):void
{
	//trace(event.info.code);
	switch(event.info.code)
	{
		case "NetStream.Buffer.Full":
			ns.bufferTime = 10;
			Tweener.addTween(videoPreloader, {alpha:0, time:.3});
		break;
		case "NetStream.Buffer.Empty":
			ns.bufferTime = 10;
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});
		break;
		case "NetStream.Play.Start":
			ns.bufferTime = 10;
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});
		break;
		case "NetStream.Seek.Notify":
			ns.bufferTime = 10;
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});
		break;
		case "NetStream.Seek.InvalidTime":
			ns.bufferTime = 10;
			Tweener.addTween(videoPreloader, {alpha:1, time:.3});
		break;
		case "NetStream.Play.Stop":
			Tweener.addTween(videoPreloader, {alpha:0, time:.3});
			ns.pause();
			ns.seek(1);
		break;
	}
}
function onMetaData(newMeta:Object):void
{
	//trace("Metadata: duration=" + newMeta.duration + " width=" + newMeta.width + " height=" + newMeta.height + " framerate=" + newMeta.framerate);
	duration = newMeta.duration;
}
ns.play("flv/bsu-football-open.flv");

////// VIDEO BTN FUNCTIONS  //////
function playBtnClick(event:MouseEvent):void
{
	ns.resume();
}
function pauseBtnClick(event:MouseEvent):void
{
	ns.pause();
}
function stopBtnClick(event:MouseEvent):void
{
	ns.pause();
	ns.seek(0);
}

////// VOLUME SCRUBBER //////
videoSound = new SoundTransform();
videoSound.volume = 1;
ns.soundTransform = videoSound;
function volumeScrubberDown(event:MouseEvent):void
{
	volumeBounds = new Rectangle(0,0,75,0);
	volumeThumb.startDrag(false, volumeBounds);
	stage.addEventListener(MouseEvent.MOUSE_UP, volumeThumbUp);
	stage.addEventListener(MouseEvent.MOUSE_MOVE, volumeThumbMove);
}
function volumeThumbUp(event:MouseEvent):void
{
	volumeThumb.stopDrag();
	stage.removeEventListener(MouseEvent.MOUSE_UP, volumeThumbUp);
	stage.removeEventListener(MouseEvent.MOUSE_MOVE, volumeThumbMove);
}
function volumeThumbMove(event:MouseEvent):void
{
	volumeTrack.width = volumeThumb.x;
	videoSound.volume = (volumeThumb.x) / 50;
	ns.soundTransform = videoSound;
}

////// TIMELINE SCRUBBER //////
function videoStatus():void
{
	amountLoaded = ns.bytesLoaded / ns.bytesTotal;
	videoTrackDownload.width = amountLoaded * 340;
	videoThumb.x = ns.time / duration * 340;
	videoTrackProgress.width = videoThumb.x;
}
function videoScrubberDown(event:MouseEvent):void
{
	var bounds:Rectangle = new Rectangle(0,0,340,0);
	clearInterval(videoInterval);
	scrubInterval = setInterval(scrubTimeline, 10);
	videoThumb.startDrag(false, bounds);
	stage.addEventListener(MouseEvent.MOUSE_UP, stopScrubbingVideo);
}
function scrubTimeline():void
{
	ns.seek(Math.floor((videoThumb.x / 340) * duration));
}
function stopScrubbingVideo(Event:MouseEvent):void
{
	stage.removeEventListener(MouseEvent.MOUSE_UP, stopScrubbingVideo);
	clearInterval(scrubInterval);
	videoInterval = setInterval(videoStatus, 100);
	videoThumb.stopDrag();
}

////// BTN OVER & OUT FUNCTIONS //////
function btnOver(event:MouseEvent):void
{
	event.currentTarget.gotoAndPlay("over");
}
function btnOut(event:MouseEvent):void
{
	event.currentTarget.gotoAndPlay("out");
}

////// POSITION CONTENT //////
function setMyStage():void
{
	videoBox.x = stage.stageWidth / 2 - (featuredBoxBg.width / 2);
	videoBox.y = (stage.stageHeight / 2 - videoBox.height / 2) - featuredBoxBg.height / 2;
	sidebarBox.x = (stage.stageWidth / 2 + 92);
	sidebarBox.y = videoBox.y;
	featuredBox.x = videoBox.x;
	featuredBox.y = videoBox.y + videoBox.height + 4;

}
function myResizeEvent(event:Event):void
{
	videoBox.x = stage.stageWidth / 2 - (featuredBoxBg.width / 2);
	videoBox.y = (stage.stageHeight / 2 - videoBox.height / 2) - featuredBoxBg.height / 2;
	sidebarBox.x = (stage.stageWidth / 2 + 92);
	sidebarBox.y = videoBox.y;
	featuredBox.x = videoBox.x;
	featuredBox.y = videoBox.y + videoBox.height + 4;
}

Test your movie; the video should play and you should be able to scrub the video now.

Conclusion

This first part was mostly spent setting up the ground work and getting some basic functionality going. In the next next chapter we’re going to prepare the thumbnails, set up the XML, change how our video loads the movies, get our three gallery buttons working, add items and thumbnails for categories and add our video items with their thumbnails.

There’s plenty to get your teeth into, I hope you’re enjoying it so far.


Other parts in this series:Build a Dynamic Video Player with ActionScript 3: Part 2 of 3»

Tags: Videos
  • reno

    WOW THIS IS SOME AWESOME STUFF

    • Basanta

      it didn’t work. tell me how is worksssssssssss

  • http://www.limess.nl Groningen

    Now this is a very very good tutorial! tnx a lot.

    Greetings,

    From Groningen(Best City ofThe Netherlands)

    • ThE_OwNeR

      Breda = Best city of the Netherlands :]

      Awesome tutorial :D This is really Plus material ;)

    • http://snaptin.com Ian Yates
      Staff

      Dirksland = Best city of the Netherlands

      Sorry, just wanted to get involved..

    • Daniel Apt

      Sorry guys, Amsterdam wins :D!

  • http://www.neilrpearce.co.uk neil

    Looking forward to finishing this one. Just what i was after!

  • shaight

    zackattack–he’s a VIDEO FREAK!!!!

    I’m so impressed…this is the BEST!

    WOW!!!!

  • http://labs.dariux.com Dario Gutierrez

    Wooww excellent tutorial Zachary!

  • André

    The result is amazing, but this is the kind of thing that really should be done using document class and and external as files, would be much more simple the code and much less lines ;)

    Thanks for sharing

  • John

    The code has to go somewhere no better place than the timeline :)
    I’m so glad this is NOT using classes

    • jack

      you dont need to be a douche John. He will get there.

      Just cause you know how build classes and maybe…MAYBE…extend them let alone having any sort of concept of a design pattern doesnt mean that he wont be better than you at it once he learns.

      on that note…Zachary…you are off to a great start. You need to start learning OOP Actionscript though if you want to be on the top.

      • John

        I think you missed my point The place to start is the timeline.

        These tutorials should be about learning and my point is that the timeline is the best place to learn actionscript.
        So if people want to change the tutorial to use classes then go on the script is there for you.

      • André

        John, the best place to learn the good AS3, is not the timeline, at adobe´s website they tell that coding in timeline is a bad habbit, and if you know how to code in external .as files you know how easyer is to create the same result with much less code, and a little bit faster…

    • Rich

      What a ridiculous statement.

    • Kylio

      John, you are obviously a novice at best.

      Ive been working in the industry building websites and applications for over 5 years now.

      Its that kind of short-sighted stupidity and bad practice that continues to hinder flash developers and make us look like the incompetent slackers of the development world.

      Complex applications require design patterns and classes are the building blocks of a great and stable application.

      If you wanna code on the time-line the rest of your life and not progress any further as a developer that’s fine, just don’t expect to go anywhere inside the industry on a professional level because most REAL flash developers wanna work with guys that know actionscript from an OOP point of view.

      Further more don’t expect others to engage in such terrible coding habits. This is a place of learning, lets not teach people bad habits.

      • John

        Be interested in seeing one of your Complex applications or even one of you Websites.

        Post a link

  • http://www.jamieholliday.co.uk jamie

    Excellent Tut, very well commented. Looking forward to part 2. Thanks

  • Pingback: uberVU - social comments

  • qborreda

    Great tut so far, Zachary. Appreciated!

  • reno

    Am getting this error

    1137: Incorrect number of arguments. Expected no more than 2.

    FilterShortcuts.as, Line 52
    FilterShortcuts.as, Line 59
    FilterShortcuts.as, Line 74
    FilterShortcuts.as, Line 105
    FilterShortcuts.as, Line 110
    FilterShortcuts.as, Line 126
    FilterShortcuts.as, Line 139
    FilterShortcuts.as, Line 155

    any solutions.

    • http://www.dtxcreative.com Zachary Haight
      Author

      Sounds like your missing something with the Tweener class. Maybe you have a comma somewhere or are missing something in a Tween. Check your code with the finished code at the bottom of the tut. It’s hard to say what is wrong without looking at your code.

  • http://www.youtube.com/watch?v=VEVuy_mN-LE idreamofpixels

    I’ve been searching for a good video player tutorial for some time now. Great job, can’t wait for the next part!

  • Rich

    Wow, what a terrible start. Can’t wait to see what a mess you’ll be in by part 3

    • Deoxys

      ???

  • http://www.lovittmcmanus.com Chris McManus

    WOW! And for Free? 2x wow! Thank you very much for sharing I eagerly await the next installments.

    Thumbs Up
    Shared
    Dug
    Tweeted
    FB post

    Did I miss anything? Again thanks a ton, keep up the good work!

    • http://snaptin.com Ian Yates
      Staff

      delicious.com? Well, you did ask..

  • AndreWF

    Great to see how others code their stuff. And honestly, your style is better than mine … -.-

  • http://www.paramidoh.blogspot.com Javier

    Yes it is a bit messy, but it is still a great tutorial.

    And if you like to complain that much, why don’t you change this to OO and send it to Zachary so he can improve his skills. Or you just like to complain and do nothing.

    • Debbie

      i’m with you javier.!

      • http://www.jamieholliday.co.uk jamie

        Yep I agree too, if you have a way to improve the code, please share and it will benefit everyone. This is a place to learn new skills.
        I think constructive critique is good, having a dig for the sake of it serves no purpose.

    • Rich

      Why should readers be educating the authors on the subjects that they are writing about?

      The point isn’t that it’s ‘a little bit messy’, but that it teaches bad practices to people who are presumably just starting out in development so won’t know to question them.

      Relatively complex applications like a video player should be built with an OO approach and ideally with some form of design pattern(MVC and the state pattern in this case). If this is beyond the author’s current experience then they shouldn’t be submitting tutorials on the subject and ActiveTuts shouldn’t be accepting them.

  • http://whoisbradsedito.com Brad Sedito

    Excellent work, Zach – and great job on the aesthetics as well – i’d like to see more of your stuff.

    - Brad

  • http://www.dtxcreative.com Zachary Haight
    Author

    Thanks for the positive feedback everyone! I am working through the book essential actionscript 3.0 right now, trying to wrap my head around classes. I know I need to learn it but I have only been writing code for a year now and some of it is way over my head. It would be great if any of the readers here could rewrite this using classes so I could compare. We could maybe do a second set of tutorials to show how this could be done with the use of classes for some of the more advanced readers. Email me (zackattack27@gmail.com) or get a hold of me on twitter (zackattack27) if you are interested. I know the whole community here would be thankful :)

    • André

      I like to help people who REALLY want to know the good habbits of AS3, who really want to learn, i can help you with classes, you can join the discussion chat in msn or yahoo messenger, just add the contact group225300@groupsim.com (i am most time there), there are some other people who helps too

  • http://www.atozsolution.com website design New York City

    Thanks for posting this very informative article. I have learned a lot. Cheers to a wonderful 2010!

  • dub

    dont forget your fullscreen button :)

  • Thomas

    Thanks for you works, that’s very usefull.

  • Daniel Apt

    Very impressive end result, after my exams I’ll completely read it. But kudos on the end result ;)

  • yassi

    Fantastic tut, Thank you!
    Looking forward to part 2 and 3. But could you please write the tutorial with document class and external classes?
    Thanks in advance

  • Nicolaj

    That Was Wired

    i had just spend time lokking for a tutorial everywhere and when i gave up and
    decided to make somethine else Woalla Thans´ks :)

  • Bruno Crociquia

    Just adding my two cents for the OOP enthusiasts that commented here.

    All i can say is that there is more than one way to skin a cat. This is one.
    Might not be using model view controller, or any other packaged approach, but it gets the job done and its easy to follow.

    I actually find it easier for people to understand how to code in the timeline and then gradually work your way up to more complex levels of coding, and as you evolve as a programmer you come to get use the best practices because you understand why they are a best practices and not just because someone told you.

    Besides, learning patterns and knowing where to apply them is something very hard to pick up with written articles online, specially if you are just starting out. This is a step by step tutorial, i don’t expect for it to go in detail about the methods (its not an online course) i just expect to see what those methods were, the demo works fine in my computer, its not slow and not buggy, thats what the end user will see. Could it be faster and easier to update? of course. But as far as i see it, its a job well done.

    • André

      I think, the way the actionscript evolves, soon there will be no more timeline codding, in AS2 you still can code directly in object, wich you can´t now in AS3, the next step is to eliminate completely the timeline… so i think the best is to code the AS3 in external .as files, wich is the correct way… But it´s just what I think

  • Basanta

    great to the source code to video player i will go through it./……….. thankz

  • Basanta

    code didn’t work . 12 errors were found

  • Stevie J

    Hey tutsplus network…since you have probably one of the most useless video players on the web I think you should take some notes!!

  • Nicolaj

    If you guys only want a simple one you might ckeck this out

    http://www.adobe.com/devnet/flash/articles/video_playlist.html

  • Sanj

    This is awesome however it throws up an error on line 167
    videoSound = new SoundTransform(); // creates a new SoundTransform object

    I wonder why can anyone help or am I just Thick?

  • LoriMo

    This seems like a great tutorial. However, when I tested my movie, I received the following error:

    ReferenceError: Error #1065: Variable caurina.transitions.properties::FilterShortcuts is not defined. at theater_fla::MainTimeline/frame1()

    Please Help!

  • Pingback: Why degradation

  • mei

    Seems it can’t find the stream as the “trace(event.info.code)” in the myStatusHandler function shows me this: NetStream.Play.StreamNotFound .. I have all the folders in the correct place (not in the desktop, but even though, I didn’t move their positions) and cannot understand why it can’t find it. So, I’m stuck in the step 17: Play the video. Any ideas?

  • http://www.e11world.com e11world

    This may be the first time I liked looking at AS3 code. I’ve never created anything in AS3 yet but with this tutorial, I really plan to do so.
    Thanks!

  • Justin

    This is an excellent tutorial! My complements.

  • itguy79

    If you are having problems with step one. remove the last { and then your movie will play correctly. Ok I am on to step 2 now. This is a great tut!

  • pixelBender67

    I hear you Zach I have only been doing this for under ayear and would also like to get off the timeline
    I look forward to learning more through active tuts, you guys rock !

  • http://perredicarlo.com Perre

    Hey Zachary,

    Your tutorial rocks. Your explanations at the outset – about why you keep vars in one place and functions in another – will help me organize code throughout future projects. Thanks.

    Glad to see you’re starting the process of converting this to Classes. Best of luck and I look forward to the next tutorial.

    I noticed two fixes you may wish to update:
    1. The first four lines of STEP 15 duplicates STEP 14.
    2. STEP 12 says this: “Type the following code below the code in step 10.” However STEP 10 is your explainer for button architecture. I think you mean “below the code in step 9″.

  • Raf

    Thanks,

    i’ve been searching for day’s now how to make my scrubber work.

    grts

  • Matt

    I’m getting this error

    1087: Syntax error: extra characters found after end of program. 1087: 2. import caurina.transitions.*;

    Any ideas?

    When I downloaded the caurina files I didn’t see anything that said “caurina”. everything said Tweener. Is that the same thing?

  • Gerry

    Hi,

    Yes the code is messy; but the guy had the “confidence” to go for it and has shown a desire to learn more.

    @Rich – “Why should readers be educating the authors on the subjects that they are writing about?”

    Yo dude, why so touchy and why the hell not – If Zachs tut helps just a few, its been worth it. And if Andre helps him out with the .as files (OOP) what’s the wrong in this?

    Then it’s been an even greater learning AS3 learning experience for the beginners.

    @ Rich

    If I were to tell you that I’m a funny guy. Would you beleive me?

    If others were to tell you Gerrys a funny guy. Would you beleive them?

    It’s all good.

    Kind Regards,

    Gerry

    PS Andre and Zach should work together; and produce an OOP version to this tut. Split the CASH ;)

  • Kaiss Salha

    where is the “src” file?

  • ken

    hey does any one know how i can put a like on videos so that it can add selected videos to a playlist,

  • jagdish

    hi,
    how to add video into .xml file of adobe flash.

  • mark

    i have a quiestion. when i want to copy it in AS3 file it gives me all sorts of errors. my question is, how does the file.as looks like ? Do you copy the code in package{ } directly?

  • bateman

    great tutorial man, easy to understand im just stuck at the end of part 1 the player shows up but nothing plays and it flashes if anyone knows anything about that i would appreciate the help

  • JORGE ORTEGA

    Didn’t work:

    1151: A conflict exists with definition playBtn in namespace internal.

    Not working, gonna search another tutorial that works…