| |
Expanding the Flash Actionscript 3.0 Videoplayer |
|
Alright, here’s the second part of the video player tutorial. We will be adding the following new features:
- Playlist support
- Fullscreen support
- Save volume
- Clickable progress/volume bar
You can preview the final result of this tutorial here.
Requirements
Adobe Flash CS3
Source Files
We also wanted to create a box displaying a message when the video is still buffering. But there has been an issue with the NetStreamEvent. It doesn’t fire the NetStream.Buffer.Empty event when the player’s actually buffering. People from the community say that this problem is somehow related with the encoding software of the flash video files. Since we didn’t find a proper solution, we left this feature out. If someone has an idea how this problem can still be properly solved, feel free to leave us a comment.
Playlist support
Ok, let’s begin with the major new feature. Adding the playlist support is quite simple and nearly implemented the same way as in the slideshow tutorial. So we have our XML file which looks like this:
<playlist> <vid src="video/hancock.flv" desc="Hancock (2008) - Movie Trailer"/> <vid src="video/redbelt.flv" desc="Redbelt (2008) - Movie Trailer"/> <vid src="video/the_dark_knight.flv" desc="The Dark Knight (2008) - Movie Trailer"/> </playlist>
As you can see, each video has two attributes. One describes the source to the file and the other one is a short description or the title of the movie.
Now it’s time to go on with coding. We changed the line which defines the source of the flash video file to the following:
var strSource:String = root.loaderInfo.parameters.playlist == null ? "playlist.xml" : root.loaderInfo.parameters.playlist;
Like this, flash will look for the flash variable playlist which you can add in the html file. If it’s defined, then the value will be assigned to the variable strSource. Otherwise we just assign a default location. Like this, you can use one compiled SWF file for every playlist you want to publish.
In order to load this file, we need to add three more variables to our video player:
var urlLoader:URLLoader; var urlRequest:URLRequest; var xmlPlaylist:XML;
urlLoader will later be used to load and handle the loaded xml file. urlRequest is an object for the urlLoader to load the playlist file. And xmlPlaylist will then contain the loaded xml data from the urlLoader.
We’ve added these code lines add the bottom to the initVideoPlayer() function:
urlRequest = new URLRequest(strSource); urlLoader = new URLLoader(); urlLoader.addEventListener(Event.COMPLETE, playlistLoaded); urlLoader.load(urlRequest);
A new urlRequest will be created with the source location of the xml file. Then we create a new urlLoader, add an event listener when the loading is completed and finally load the file. What’s also important is that we hide the controls of the video player in the first line of the initVideoPlayer() function since we don’t want that the user can click anything if the playlist hasn’t been loaded yet.
As soon as the playlist is loaded we call the playlistLoaded() function which looks like this:
function playlistLoaded(e:Event):void {
xmlPlaylist = new XML(urlLoader.data);
playVid(0, false)
mcVideoControls.visible = true;
}
We assign the received data from the loader to the xml object, set the first video source but not play the video and show the video controls since we’ve loaded all the stuff.
Now we need a back and forward button. We add two event listeners for the buttons in the initVideoPlayer() function:
mcVideoControls.btnNext.addEventListener(MouseEvent.CLICK, playNext); mcVideoControls.btnPrevious.addEventListener(MouseEvent.CLICK, playPrevious);
Then we define a new variable that saves the current number:
var intActiveVid:int;
Now let’s take a closer look at the playVid() function
function playVid(intVid:int = 0, bolPlay = true):void {
if(bolPlay) {
tmrDisplay.stop();
nsStream.play(String(xmlPlaylist..vid[intVid].@src));
mcVideoControls.btnPause.visible = true;
mcVideoControls.btnPlay.visible = false;
} else {
strSource = xmlPlaylist..vid[intVid].@src;
}
vidDisplay.visible = true;
mcVideoControls.mcVideoDescription.lblDescription.x = 0;
mcVideoControls.mcVideoDescription.lblDescription.htmlText = (intVid + 1) + ". " + String(xmlPlaylist..vid[intVid].@desc) + "";
intActiveVid = intVid;
}
As you can see, it now needs to have a video number and a boolean value if the video should be played or just be set to the strSource variable. The function also sets the new description label of the requested video with the value from the xml object and positions it to zero on the x-axis. And finally the intVid value gets assigned to the variable intActiveVid.
The playNext() and playPrevious() function are now ease to implement. We just check if there there is still a video left we can skip or rewind and call the playVid function with the parameter intActiveVid + 1 or intActiveVid – 1 depending on the direction:
function playNext(e:MouseEvent = null):void {
if(intActiveVid + 1 < xmlPlaylist..vid.length())
playVid(intActiveVid + 1);
}
function playPrevious(e:MouseEvent = null):void {
if(intActiveVid - 1 >= 0)
playVid(intActiveVid - 1);
}
When a video reached it’s end, we stoped the player. But now we want to play the next video in the playlist if there’s still one left, if not, ok then we stop the player
So we change this in the netStatusHandler() function:
if(intActiveVid + 1 < xmlPlaylist..vid.length()) playNext(); else stopVideoPlayer();
Now there’s only the vertical scrolling of the video description label left for the playlist feature. It could be that you need an extra long title for your video. In that case, we’ve just created a very long one lined textfield that’s masked. On top of that is an invisible button that will be used to know, if the user moves the mouse over the label so we can scroll it if it’s to long. In order to know if we’re currently scrolling the label and to know in which direction the scrolling is going, we need to set two new variables:
var bolDescriptionHover:Boolean = false; var bolDescriptionHoverForward:Boolean = true;
Now we need to add an event listener on the invisible button:
mcVideoControls.mcVideoDescription.btnDescription.addEventListener(MouseEvent.MOUSE_OVER, startDescriptionScroll); mcVideoControls.mcVideoDescription.btnDescription.addEventListener(MouseEvent.MOUSE_OUT, stopDescriptionScroll);
The functions startDescriptionScroll() and stopDescriptionScroll() are simply setting the bolDescriptionHover variable to true or false depending on the mouse event. startDescriptionScroll() additionally checks, if it’s even necessary to scroll the text:
function startDescriptionScroll(e:MouseEvent):void {
if(mcVideoControls.mcVideoDescription.lblDescription.textWidth > 138)
bolDescriptionHover = true;
}
function stopDescriptionScroll(e:MouseEvent):void {
bolDescriptionHover = false;
}
To actually move the label we just add some new lines of code to the updateDisplay() function which is called by the timer object:
if(bolDescriptionHover) {
if(bolDescriptionHoverForward) {
mcVideoControls.mcVideoDescription.lblDescription.x -= 0.1;
if(mcVideoControls.mcVideoDescription.lblDescription.textWidth - 133 <= Math.abs(mcVideoControls.mcVideoDescription.lblDescription.x))
bolDescriptionHoverForward = false;
} else {
mcVideoControls.mcVideoDescription.lblDescription.x += 0.1;
if(mcVideoControls.mcVideoDescription.lblDescription.x >= 0)
bolDescriptionHoverForward = true;
}
} else {
mcVideoControls.mcVideoDescription.lblDescription.x = 0;
bolDescriptionHoverForward = true;
}
First, we check if we’re currently over the label. The we figure out, which way we move the text. Since the updateDisplay() function is called pretty often, we get a smooth motion by incrementing and decrementing the label’s x value just by 0.1. So, when moving forward, we actualy move the label to the left and check, if we’ve reached the end. If so, we invert the bolDescriptionForward value and begin to move the field to the right until it reached zero on the x-axis. If the user’s no hovering over the invisible button, we just reset the position of the label and the direction flag.
Fullscreen support
Since flash player version 9,0,28,0 you can use the fullscreen feature. In order to get this to work, you also need to set this in the HTML code. But since Flash does all the HTML stuff for you, you only need to change the mode to allowFullscreen in the publish settings of HTML

The implementing of the fullscreen support is rather simple in our case because we don’t have too much stuff on the stage we need to reposition/resize once we hit the fullscreen mode. So, first of all, we set the scale mode of the stage to no scale because we want to resize the object individualy and not everything. We also set the stage align mode to the top left corner:
stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT;
Then we add two event listeners for the fullscreen button. One to enter it and one for leaving the full screen mode. We also add an event listener when the fullscreen mode changes. The visibility of the btnFullscreenOff button will be set to false. We do all of this in the initVideoPlayer() function:
mcVideoControls.btnFullscreenOn.addEventListener(MouseEvent.CLICK, fullscreenOnClicked); mcVideoControls.btnFullscreenOff.addEventListener(MouseEvent.CLICK, fullscreenOffClicked); stage.addEventListener(FullScreenEvent.FULL_SCREEN, onFullscreen); mcVideoControls.btnFullscreenOff.visible = false;
To actualy enter and leave the fullscreen mode, all you need to do is to set the display state of the stage to the wanted mode. That’s what we’re doing when the user clicks the fullscreen buttons:
function fullscreenOnClicked(e:MouseEvent):void {
stage.displayState = StageDisplayState.FULL_SCREEN;
}
function fullscreenOffClicked(e:MouseEvent):void {
stage.displayState = StageDisplayState.NORMAL;
}
Now we only need to define the resizing action in the onFullScreen() function:
function onFullscreen(e:FullScreenEvent):void {
if (e.fullScreen) {
mcVideoControls.btnFullscreenOn.visible = false;
mcVideoControls.btnFullscreenOff.visible = true;
mcVideoControls.x = (Capabilities.screenResolutionX - 440) / 2;
mcVideoControls.y = (Capabilities.screenResolutionY - 33);
vidDisplay.height = (Capabilities.screenResolutionY - 33);
vidDisplay.width = vidDisplay.height * 4 / 3;
vidDisplay.x = (Capabilities.screenResolutionX - vidDisplay.width) / 2;
} else {
mcVideoControls.btnFullscreenOn.visible = true;
mcVideoControls.btnFullscreenOff.visible = false;
mcVideoControls.x = 0;
mcVideoControls.y = 330;
vidDisplay.y = 0;
vidDisplay.x = 0;
vidDisplay.width = 440;
vidDisplay.height = 330;
}
}
So, first we check if we’re entering the fullscreen mode. If so, we switch the fullscreen buttons, align the control bar in the bottom center of the screen and size up the video display and center it on to the screen. If we’re leaving the fullscreen mode, what you can also do by pressing the ESC key on your keyboard, we reset all the stuff to how it was before.
That’s was already everything for the fullscreen support
Save volume
This is quite an important feature and really ease to implement in flash. To save the last used volume you can use the flash cookies which will be stored on the computer of the user. They are like normal browser cookies, but can only accessed through flash. So, the first thing we need to do is creating a new shared object:
var shoVideoPlayerSettings:SharedObject = SharedObject.getLocal("playerSettings");
The function getLocal returns the shared object you’ve requested. In our case we want to have the playerSettings cookie/shared object. Since we want to set the volume on the start, we add the following line to the initVideoPlayer() function:
var tmpVolume:Number = DEFAULT_VOLUME;
if(shoVideoPlayerSettings.data.playerVolume != undefined) {
tmpVolume = shoVideoPlayerSettings.data.playerVolume;
intLastVolume = tmpVolume;
}
mcVideoControls.mcVolumeScrubber.x = (53 * tmpVolume) + 318;
mcVideoControls.mcVolumeFill.mcFillRed.width = mcVideoControls.mcVolumeScrubber.x - 371 + 53;
setVolume(tmpVolume);
First we assign the DEFAULT_VOLUME to a temporary variable. Then we check if the user has already a cookie with the player volume. If so, we override the value from the variable. Then we update the volume bar and set the volume with the setVolume() function. In order to store the new volume in the cookie, we add the following two new lines to the setVolume() function:
shoVideoPlayerSettings.data.playerVolume = intVolume; shoVideoPlayerSettings.flush();
The function flush() writes the new value immediately in the flash cookie.
Clickable progress/volume bar
This is just a beauty hack for the player. We want to be able to click on the progress or the volume bar to begin with the scrubbing. So, we just added two invisible buttons on the off the bars and added the function to it as when you click the scrub buttons directly:
mcVideoControls.mcVolumeScrubber.btnVolumeScrubber.addEventListener(MouseEvent.MOUSE_DOWN, volumeScrubberClicked); mcVideoControls.mcProgressScrubber.btnProgressScrubber.addEventListener(MouseEvent.MOUSE_DOWN, progressScrubberClicked);
And what’s also changed is, that we now lock the center in the startDrag() function. Like this the scrubber will move to where you clicked on the bars:
function volumeScrubberClicked(e:MouseEvent):void {
bolVolumeScrub = true;
mcVideoControls.mcVolumeScrubber.startDrag(true, new Rectangle(318, 19, 53, 0));
}
function progressScrubberClicked(e:MouseEvent):void {
bolProgressScrub = true;
mcVideoControls.mcProgressScrubber.startDrag(true, new Rectangle(0, 2, 432, 0));
}
We’ve already reached the end of the second part of the video player tutorial. We hope that you enjoyed reading it and we appreciate every kind of feedback.
Full code with comments
// ###############################
// ############# CONSTANTS
// ###############################
// time to buffer for the video in sec.
const BUFFER_TIME:Number = 8;
// start volume when initializing player
const DEFAULT_VOLUME:Number = 0.6;
// update delay in milliseconds.
const DISPLAY_TIMER_UPDATE_DELAY:int = 10;
// smoothing for video. may slow down old computers
const SMOOTHING:Boolean = true;
// ###############################
// ############# VARIABLES
// ###############################
// flag for knowing if user hovers over description label
var bolDescriptionHover:Boolean = false;
// flag for knowing in which direction the description label is currently moving
var bolDescriptionHoverForward:Boolean = true;
// flag for knowing if flv has been loaded
var bolLoaded:Boolean = false;
// flag for volume scrubbing
var bolVolumeScrub:Boolean = false;
// flag for progress scrubbing
var bolProgressScrub:Boolean = false;
// holds the number of the active video
var intActiveVid:int;
// holds the last used volume, but never 0
var intLastVolume:Number = DEFAULT_VOLUME;
// net connection object for net stream
var ncConnection:NetConnection;
// net stream object
var nsStream:NetStream;
// object holds all meta data
var objInfo:Object;
// shared object holding the player settings (currently only the volume)
var shoVideoPlayerSettings:SharedObject = SharedObject.getLocal("playerSettings");
// url to flv file
var strSource:String = root.loaderInfo.parameters.playlist == null ? "playlist.xml" : root.loaderInfo.parameters.playlist;
// timer for updating player (progress, volume...)
var tmrDisplay:Timer;
// loads the xml file
var urlLoader:URLLoader;
// holds the request for the loader
var urlRequest:URLRequest;
// playlist xml
var xmlPlaylist:XML;
// ###############################
// ############# STAGE SETTINGS
// ###############################
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
// ###############################
// ############# FUNCTIONS
// ###############################
// sets up the player
function initVideoPlayer():void {
// hide video controls on initialisation
mcVideoControls.visible = false;
// hide buttons
mcVideoControls.btnUnmute.visible = false;
mcVideoControls.btnPause.visible = false;
mcVideoControls.btnFullscreenOff.visible = false;
// set the progress/preload fill width to 1
mcVideoControls.mcProgressFill.mcFillRed.width = 1;
mcVideoControls.mcProgressFill.mcFillGrey.width = 1;
// set time and duration label
mcVideoControls.lblTimeDuration.htmlText = "00:00 / 00:00";
// add global event listener when mouse is released
stage.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
// add fullscreen listener
stage.addEventListener(FullScreenEvent.FULL_SCREEN, onFullscreen);
// add event listeners to all buttons
mcVideoControls.btnPause.addEventListener(MouseEvent.CLICK, pauseClicked);
mcVideoControls.btnPlay.addEventListener(MouseEvent.CLICK, playClicked);
mcVideoControls.btnStop.addEventListener(MouseEvent.CLICK, stopClicked);
mcVideoControls.btnNext.addEventListener(MouseEvent.CLICK, playNext);
mcVideoControls.btnPrevious.addEventListener(MouseEvent.CLICK, playPrevious);
mcVideoControls.btnMute.addEventListener(MouseEvent.CLICK, muteClicked);
mcVideoControls.btnUnmute.addEventListener(MouseEvent.CLICK, unmuteClicked);
mcVideoControls.btnFullscreenOn.addEventListener(MouseEvent.CLICK, fullscreenOnClicked);
mcVideoControls.btnFullscreenOff.addEventListener(MouseEvent.CLICK, fullscreenOffClicked);
mcVideoControls.btnVolumeBar.addEventListener(MouseEvent.MOUSE_DOWN, volumeScrubberClicked);
mcVideoControls.mcVolumeScrubber.btnVolumeScrubber.addEventListener(MouseEvent.MOUSE_DOWN, volumeScrubberClicked);
mcVideoControls.btnProgressBar.addEventListener(MouseEvent.MOUSE_DOWN, progressScrubberClicked);
mcVideoControls.mcProgressScrubber.btnProgressScrubber.addEventListener(MouseEvent.MOUSE_DOWN, progressScrubberClicked);
mcVideoControls.mcVideoDescription.btnDescription.addEventListener(MouseEvent.MOUSE_OVER, startDescriptionScroll);
mcVideoControls.mcVideoDescription.btnDescription.addEventListener(MouseEvent.MOUSE_OUT, stopDescriptionScroll);
// create timer for updating all visual parts of player and add
// event listener
tmrDisplay = new Timer(DISPLAY_TIMER_UPDATE_DELAY);
tmrDisplay.addEventListener(TimerEvent.TIMER, updateDisplay);
// create a new net connection, add event listener and connect
// to null because we don't have a media server
ncConnection = new NetConnection();
ncConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
ncConnection.connect(null);
// create a new netstream with the net connection, add event
// listener, set client to this for handling meta data and
// set the buffer time to the value from the constant
nsStream = new NetStream(ncConnection);
nsStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
nsStream.client = this;
nsStream.bufferTime = BUFFER_TIME;
// attach net stream to video object on the stage
vidDisplay.attachNetStream(nsStream);
// set the smoothing value from the constant
vidDisplay.smoothing = SMOOTHING;
// set default volume and get volume from shared object if available
var tmpVolume:Number = DEFAULT_VOLUME;
if(shoVideoPlayerSettings.data.playerVolume != undefined) {
tmpVolume = shoVideoPlayerSettings.data.playerVolume;
intLastVolume = tmpVolume;
}
// update volume bar and set volume
mcVideoControls.mcVolumeScrubber.x = (53 * tmpVolume) + 318;
mcVideoControls.mcVolumeFill.mcFillRed.width = mcVideoControls.mcVolumeScrubber.x - 371 + 53;
setVolume(tmpVolume);
// create new request for loading the playlist xml, add an event listener
// and load it
urlRequest = new URLRequest(strSource);
urlLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, playlistLoaded);
urlLoader.load(urlRequest);
}
function playClicked(e:MouseEvent):void {
// check's, if the flv has already begun
// to download. if so, resume playback, else
// load the file
if(!bolLoaded) {
nsStream.play(strSource);
bolLoaded = true;
}
else{
nsStream.resume();
}
vidDisplay.visible = true;
// switch play/pause visibility
mcVideoControls.btnPause.visible = true;
mcVideoControls.btnPlay.visible = false;
}
function pauseClicked(e:MouseEvent):void {
// pause video
nsStream.pause();
// switch play/pause visibility
mcVideoControls.btnPause.visible = false;
mcVideoControls.btnPlay.visible = true;
}
function stopClicked(e:MouseEvent):void {
// calls stop function
stopVideoPlayer();
}
function muteClicked(e:MouseEvent):void {
// set volume to 0
setVolume(0);
// update scrubber and fill position/width
mcVideoControls.mcVolumeScrubber.x = 318;
mcVideoControls.mcVolumeFill.mcFillRed.width = 1;
}
function unmuteClicked(e:MouseEvent):void {
// set volume to last used value or DEFAULT_VOLUME if last volume is zero
var tmpVolume:Number = intLastVolume == 0 ? DEFAULT_VOLUME : intLastVolume
setVolume(tmpVolume);
// update scrubber and fill position/width
mcVideoControls.mcVolumeScrubber.x = (53 * tmpVolume) + 318;
mcVideoControls.mcVolumeFill.mcFillRed.width = mcVideoControls.mcVolumeScrubber.x - 371 + 53;
}
function volumeScrubberClicked(e:MouseEvent):void {
// set volume scrub flag to true
bolVolumeScrub = true;
// start drag
mcVideoControls.mcVolumeScrubber.startDrag(true, new Rectangle(318, 19, 53, 0)); // NOW TRUE
}
function progressScrubberClicked(e:MouseEvent):void {
// set progress scrub flag to true
bolProgressScrub = true;
// start drag
mcVideoControls.mcProgressScrubber.startDrag(true, new Rectangle(0, 2, 432, 0)); // NOW TRUE
}
function mouseReleased(e:MouseEvent):void {
// set progress/volume scrub to false
bolVolumeScrub = false;
bolProgressScrub = false;
// stop all dragging actions
mcVideoControls.mcProgressScrubber.stopDrag();
mcVideoControls.mcVolumeScrubber.stopDrag();
// update progress/volume fill
mcVideoControls.mcProgressFill.mcFillRed.width = mcVideoControls.mcProgressScrubber.x + 5;
mcVideoControls.mcVolumeFill.mcFillRed.width = mcVideoControls.mcVolumeScrubber.x - 371 + 53;
// save the volume if it's greater than zero
if((mcVideoControls.mcVolumeScrubber.x - 318) / 53 > 0)
intLastVolume = (mcVideoControls.mcVolumeScrubber.x - 318) / 53;
}
function updateDisplay(e:TimerEvent):void {
// checks, if user is scrubbing. if so, seek in the video
// if not, just update the position of the scrubber according
// to the current time
if(bolProgressScrub)
nsStream.seek(Math.round(mcVideoControls.mcProgressScrubber.x * objInfo.duration / 432))
else
mcVideoControls.mcProgressScrubber.x = nsStream.time * 432 / objInfo.duration;
// set time and duration label
mcVideoControls.lblTimeDuration.htmlText = "" + formatTime(nsStream.time) + " / " + formatTime(objInfo.duration);
// update the width from the progress bar. the grey one displays
// the loading progress
mcVideoControls.mcProgressFill.mcFillRed.width = mcVideoControls.mcProgressScrubber.x + 5;
mcVideoControls.mcProgressFill.mcFillGrey.width = nsStream.bytesLoaded * 438 / nsStream.bytesTotal;
// update volume and the red fill width when user is scrubbing
if(bolVolumeScrub) {
setVolume((mcVideoControls.mcVolumeScrubber.x - 318) / 53);
mcVideoControls.mcVolumeFill.mcFillRed.width = mcVideoControls.mcVolumeScrubber.x - 371 + 53;
}
// chech if user is currently hovering over description label
if(bolDescriptionHover) {
// check in which direction we're currently moving
if(bolDescriptionHoverForward) {
// move to the left and check if we've shown everthing
mcVideoControls.mcVideoDescription.lblDescription.x -= 0.1;
if(mcVideoControls.mcVideoDescription.lblDescription.textWidth - 133 <= Math.abs(mcVideoControls.mcVideoDescription.lblDescription.x))
bolDescriptionHoverForward = false;
} else {
// move to the right and check if we're back to normal
mcVideoControls.mcVideoDescription.lblDescription.x += 0.1;
if(mcVideoControls.mcVideoDescription.lblDescription.x >= 0)
bolDescriptionHoverForward = true;
}
} else {
// reset label position and direction variable
mcVideoControls.mcVideoDescription.lblDescription.x = 0;
bolDescriptionHoverForward = true;
}
}
function onMetaData(info:Object):void {
// stores meta data in a object
objInfo = info;
// now we can start the timer because
// we have all the neccesary data
if(!tmrDisplay.running)
tmrDisplay.start();
}
function netStatusHandler(event:NetStatusEvent):void {
// handles net status events
switch (event.info.code) {
// trace a messeage when the stream is not found
case "NetStream.Play.StreamNotFound":
trace("Stream not found: " + strSource);
break;
// when the video reaches its end, we check if there are
// more video left or stop the player
case "NetStream.Play.Stop":
if(intActiveVid + 1 < xmlPlaylist..vid.length())
playNext();
else
stopVideoPlayer();
break;
}
}
function stopVideoPlayer():void {
// pause netstream, set time position to zero
nsStream.pause();
nsStream.seek(0);
// in order to clear the display, we need to
// set the visibility to false since the clear
// function has a bug
vidDisplay.visible = false;
// switch play/pause button visibility
mcVideoControls.btnPause.visible = false;
mcVideoControls.btnPlay.visible = true;
}
function setVolume(intVolume:Number = 0):void {
// create soundtransform object with the volume from
// the parameter
var sndTransform = new SoundTransform(intVolume);
// assign object to netstream sound transform object
nsStream.soundTransform = sndTransform;
// hides/shows mute and unmute button according to the
// volume
if(intVolume > 0) {
mcVideoControls.btnMute.visible = true;
mcVideoControls.btnUnmute.visible = false;
} else {
mcVideoControls.btnMute.visible = false;
mcVideoControls.btnUnmute.visible = true;
}
// store the volume in the flash cookie
shoVideoPlayerSettings.data.playerVolume = intVolume;
shoVideoPlayerSettings.flush();
}
function formatTime(t:int):String {
// returns the minutes and seconds with leading zeros
// for example: 70 returns 01:10
var s:int = Math.round(t);
var m:int = 0;
if (s > 0) {
while (s > 59) {
m++; s -= 60;
}
return String((m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s);
} else {
return "00:00";
}
}
function fullscreenOnClicked(e:MouseEvent):void {
// go to fullscreen mode
stage.displayState = StageDisplayState.FULL_SCREEN;
}
function fullscreenOffClicked(e:MouseEvent):void {
// go to back to normal mode
stage.displayState = StageDisplayState.NORMAL;
}
function onFullscreen(e:FullScreenEvent):void {
// check if we're entering or leaving fullscreen mode
if (e.fullScreen) {
// switch fullscreen buttons
mcVideoControls.btnFullscreenOn.visible = false;
mcVideoControls.btnFullscreenOff.visible = true;
// bottom center align controls
mcVideoControls.x = (Capabilities.screenResolutionX - 440) / 2;
mcVideoControls.y = (Capabilities.screenResolutionY - 33);
// size up video display
vidDisplay.height = (Capabilities.screenResolutionY - 33);
vidDisplay.width = vidDisplay.height * 4 / 3;
vidDisplay.x = (Capabilities.screenResolutionX - vidDisplay.width) / 2;
} else {
// switch fullscreen buttons
mcVideoControls.btnFullscreenOn.visible = true;
mcVideoControls.btnFullscreenOff.visible = false;
// reset controls position
mcVideoControls.x = 0;
mcVideoControls.y = 330;
// reset video display
vidDisplay.y = 0;
vidDisplay.x = 0;
vidDisplay.width = 440;
vidDisplay.height = 330;
}
}
function playlistLoaded(e:Event):void {
// create new xml with loaded data from loader
xmlPlaylist = new XML(urlLoader.data);
// set source of the first video but don't play it
playVid(0, false)
// show controls
mcVideoControls.visible = true;
}
function playVid(intVid:int = 0, bolPlay = true):void {
if(bolPlay) {
// stop timer
tmrDisplay.stop();
// play requested video
nsStream.play(String(xmlPlaylist..vid[intVid].@src));
// switch button visibility
mcVideoControls.btnPause.visible = true;
mcVideoControls.btnPlay.visible = false;
} else {
strSource = xmlPlaylist..vid[intVid].@src;
}
// show video display
vidDisplay.visible = true;
// reset description label position and assign new description
mcVideoControls.mcVideoDescription.lblDescription.x = 0;
mcVideoControls.mcVideoDescription.lblDescription.htmlText = (intVid + 1) + ". " + String(xmlPlaylist..vid[intVid].@desc) + "";
// update active video number
intActiveVid = intVid;
}
function playNext(e:MouseEvent = null):void {
// check if there are video left to play and play them
if(intActiveVid + 1 < xmlPlaylist..vid.length())
playVid(intActiveVid + 1);
}
function playPrevious(e:MouseEvent = null):void {
// check if we're not and the beginning of the playlist and go back
if(intActiveVid - 1 >= 0)
playVid(intActiveVid - 1);
}
function startDescriptionScroll(e:MouseEvent):void {
// check if description label is too long and we need to enable scrolling
if(mcVideoControls.mcVideoDescription.lblDescription.textWidth > 138)
bolDescriptionHover = true;
}
function stopDescriptionScroll(e:MouseEvent):void {
// disable scrolling
bolDescriptionHover = false;
}
// ###############################
// ############# INIT PLAYER
// ###############################
initVideoPlayer();
Other Posts You Might Like
I find Full Screen Button at http://www.as3tutorial.com it’s free, and jsut copy the mc your project, it’s works!
I'm trying to add the flash video player in to our college site and want to stop auto playing at first time and auto playing of next video. i have only two videos to play so, i dont want auto play function
please tell me how to do it. im new to the flash action scripting and using the flash video player template in flashmo.com
appreciate a speedy response.
thank you,
Please post on the forum in the right section, it is the fastest way to get a reply from the author, thanks :) http://www.thetechlabs.com/forum
Hi, very helpful tut! I need to have the player control appear/disappear on mouse event. I have Kotvi code working, but as he says it flickers between button mouse over. Is there any solution as this would be great addition to the player control, Many thanks Paul
Hi,
For a progressive download, I am using H264 transcode mp4 and flv files with CS4. I have set the bufferTime to 5 secs, so that the video quickly loads at the start and also regains buffer quickly after the buffer.empty event in the course of video play. While my player takes buffering breaks if the buffer is emptied, I am totally taken aback with the performance of youtube. Is there something that I am missing. Please correct me if I am wrong - as per my experience, the bytesLoaded decide if the video can be seek to the point translating bytesLoaded to time, meaning, for seeking to any point within the video, the calculation is (bytesLoaded/bytesTotal >= seeked-time/total-video-time). Although, even if the bytesLoaded is equal to bytesTotal, why should the video encounter intermittent buffer empty and buffer full states? With my knowledge, I can assert that even if the bytesLoaded is equal to bytesTotal, the buffer empty and full events are entirely related with the bufferLength. Meaning, that even if the video is completed cached with a progressive download, there would still not be seamless, uninterrupted, smooth video play, if the bufferLength is small, but making it large assures a long delay in resuming video playback and also at loading. Hence a trade-off is required. Is this a wrong assumption?
Hello guys, this is the best tutorial on flv flash players in as3, so I thank you a lot !!
Concerning the full screen mode, what's happen wenn you have two screens with different resolution ?? By me, the fullscreen mode conserve the resolution of the first screen and don't adapt himself to the new screen's resolution.
Have any one an idea to resolve this problem ?
thnx for the tut!
The code works fine in a flash file but when I put it into a class
everything is working except for the scrubber. You can move them but it has no effect on the volume and you can't change the position of the video.
So, what kind of imports do I need?
There’s been bits and pieces of information re. how to connect to an FMS server. Thanks! BUT none of the info seems to be working for me.
Does anybody have simple step by step instructions on how to edit the original source files and have the player connect to an FMS server?
Thanks folks! I’ll keep plugging away here until somebody who’s accomplished this chimes in.
Rafael, thank you for a great educative tutorial. Cris and Rodrigo - thank you for very helpful comments about show/hide control when the mouse is over/out.
I have a problem same as Chris had - I would like to show/hide control panel only when the mouse is over/out the area of this control panel, not the whole stage.
May I ask you, can anybody help me with this task - how to avoid the behavior that was described earlier by Chris on March 8th:
//call tween
import fl.transitions.Tween;
import fl.transitions.easing.*;
var outTween:Tween;
//listeners
mcVideoControls.addEventListener(MouseEvent.MOUSE_OVER, showControls);
mcVideoControls.addEventListener(MouseEvent.MOUSE_OUT,HideControls);
//the 2 funcions
function showControls(e:MouseEvent):void {
outTween = new Tween(mcVideoControls, “alpha”, None.easeNone, 0, 1, 0.5, true);
}
function HideControls(e:MouseEvent):void {
outTween = new Tween(mcVideoControls, “alpha”, None.easeNone, 1, 0, 0.5, true);
}
"The only problem is that when the mouse is on the play/pause and other buttons the mcVideoControls.addEventListeners call the functions again, so the controlbar fades-in again when i move, for example, from for the stop to the play button."
Thank you in advance for your help.
Peter Kotvi
I had made some changes at Cris code. I think that solves the problem about mouse in/out and control show/hide
import fl.transitions.Tween;
import fl.transitions.easing.*;
import flash.events.MouseEvent;
import flash.events.Event;
var outTween:Tween;
function ShowControls(evt: MouseEvent){
outTween = new Tween(mcVideoControls, "alpha", None.easeNone, 0, 1, 0.5, true);
this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, ShowControls);
}
function HideControls(evt: Event){
outTween = new Tween(mcVideoControls, "alpha", None.easeNone, 1, 0, 0.5, true);
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, ShowControls);
}
this.stage.addEventListener(Event.MOUSE_LEAVE, HideControls);
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, ShowControls);
How to set Video to play automatically:
Here's a quick fix to get it to play automatically. I've tested on our servers so it appears to work.
1. Make variable (boolean) videoState and set it to false. This tells us that the video is off.
2. In playlistLoaded, change playVid to true.
playVid(0, true);
3. In playVid function, in the if(bolPlay) statement, set videoState to true.
4. In the playClicked function, change the if condition to videoState==false.
5. Add 'videoState = true' to pauseClicked function.
This makes the buttons dictate whether the video is on or off. Please lemme know if it works! Good luck! It may not work for the playlist, I haven't tried. Its working with my playlist but I only have 1 thing lined up in the playlist.
Hi,
I like all the the post that are published. I even got to solve the problem. But can someone help me in making video gallery horizontally with thumbnails with xml
Great job, I tweened it and made it look like the Youtube player, but it's pointless to use (IMO) without flashvars. I want to be able to pass the source via flashvars. ex: \ - Didn't escape them ( if it doesnt work in escape, please help me,
Great job, I tweened it and made it look like the Youtube player, but it's pointless to use (IMO) without flashvars. I want to be able to pass the source via flashvars. ex:
Hi,
Is there any way in which we can play FMS streaming file in this player, including buffering.
Thanks & Regards,
Sagar
For all those who could not get autoplay or autostart
Here is a solution!!!
just add following two lines of code in playlistLoaded function
before playVid(0, false); as shown below
playVid(0, true);//Added by Sagar Ranpise
bolLoaded = true;//Added by Sagar Ranpise
playVid(0, false);
Hope it helps! And I also added the feature which I asked in my previous message, Thanks a lot for this awesome stuff!
Hi guys
I believe that adding this to the base layer of your video should stop the sound from playing
// Stop all sound when at this frame
SoundMixer.stopAll();
Add this to your main video action script to start again at the beginning of the playlist
// check if we're not at the beginning of the playlist and go back
if(intActiveVid - 1 >= 0)
playVid(intActiveVid - 1);
}
Hope that helps!
Em
Hi,
Awesome stuff, I would just want to know one thing that is there an option to go to first video automatically when it finishes last video?
Thanks a lot for sharing!
Take care & god bless!
With Regards,
Sagar
I am also having the problem where when i go to another page the sound on the video keeps playing! BIG PROBLEM FOR ME! anyone knows how to fix this???
oh.. great.. nice bro.. i want to know is this player able to support the live streaming?
anyone reply!!!
Hi to everybody, great great tutorial :-) :-) it's a great job.
I inserted show/hide controls with tween and alpha with the following code which creates a fade-in/out effect:
//call tween
import fl.transitions.Tween;
import fl.transitions.easing.*;
var outTween:Tween;
//listeners
mcVideoControls.addEventListener(MouseEvent.MOUSE_OVER, showControls);
mcVideoControls.addEventListener(MouseEvent.MOUSE_OUT,HideControls);
//the 2 funcions
function showControls(e:MouseEvent):void {
outTween = new Tween(mcVideoControls, "alpha", None.easeNone, 0, 1, 0.5, true);
}
function HideControls(e:MouseEvent):void {
outTween = new Tween(mcVideoControls, "alpha", None.easeNone, 1, 0, 0.5, true);
}
The only problem i hade is that when the mouse is on the play/pause and other buttons the mcVideoControls.addEventListeners call the functions again, so the controlbar "fades-in" again when i move, for example, from for the stop to the play button.I tried with mcVideoControls.mouseChildren=false;
but it doesn't let works the single buttons anymore .
Some1 of you expert in as 3.0 can has an idea how to solve?
Thanks for the help and thanks for this great guide..:-)
i would like to auto hide all the controls... Also will this player support for live streaming?
Reply me anybody...
Hello,
First of all... nice tutorial :) It helps me a lot to understand the concepts of develop a as3 videoplayer.
I'm writing because I found something that I don't know how to solve/develop in this player, once I followed all your points, I realize that If I have a video in internet and I start to play the video, I only can jump with the scroll "of time" to any time that I already download. Is there any possibility to develop a behavior as youtube? I mean, a user can scroll in the line to any time, and if this time isn't download, starts from there and forget the other previous video that isn't downloaded.
Do you know what I mean?
Thanks for your help,
Jordi
Thanks for the nice tutorial.
I am also having trouble with the progress scrubber. It lines up when the player loads however once I click play it jumps to the right. Any ideas how I could fix this?
Thanks a bunch!
Thanks a mil for this code. I'm having one little issue that's pretty maddening.
I set the first video to autoplay and it will not pause and restart.
I simply modified the code as below.
function playlistLoaded(e:Event):void {
// create new xml with loaded data from loader
xmlPlaylist = new XML(urlLoader.data);
// set source of the first video and play it
playVid(0, true)
// show controls
mcVideoControls.visible = true;
}
It doesn't seem to make sense as it's simply calling the function playVid and the pause works once I call the next video which appears to be the same function. Please reply to the whole string as there are a few requests for autoplay functionality.
Thanks again,
Rich
hey pls its urgent for me
how can i show playlist below videoplayer
is thr any way to show playlist
so pls help me out any help would be appriciated
thnk u
I wish to use multiple xml playlists and a single swf player. What code should I add to the html to pass the name of the xml file to the flash player? The download example doesn't show the code for setting the variable 'playlist'
Many thanks for any help.
Hi there,
First of all thanks for the great tutorial.. helped me a lot..
My question is how can I make the fullscreen for the video display only.. I use the player in a bigger stage and when I make it fullscreen it's not working properly..
I hope there is a solution for this, thanks anyways...
Ems
hey great work
but i want ur help!
how can i show playlist under videoplayer
im not good in actionscript
so pls help me out any help would be appriciated
thnk u
In my previous post I forgot the HTML code the >, < and #&38; characters. Sorry about that! Ugh!:
public function updateFLVLoad(event:ProgressEvent):void {
// check flv download progress
if(asURLFLVLoad.bytesLoaded <= asURLFLVLoad.bytesTotal) {
mcFLVCntl.mcFLVTimeline.mcFLVLoad.width = ((asURLFLVLoad.bytesLoaded * 356) / asURLFLVLoad.bytesTotal);
// display buffer animation and text overlay if flv file overlaps buffer
if((asBLFLV == true) && ((mcFLVCntl.mcFLVTimeline.mcFLVHelve.x + 214.55) > (mcFLVCntl.mcFLVTimeline.mcFLVLoad.width - 5))) {
asNS.pause();
// switch play/pause visibility
mcFLVCntl.btnPause.visible = false;
mcFLVCntl.btnPlay.visible = true;
// display the buffer and start playing the buffer animation
mcFLVDisplay.mcFLVBuffer.visible = true;
mcFLVDisplay.mcFLVBuffer.play();
// remove the buffer text "resume" from the display
mcFLVDisplay.mcFLVLoadTxt.visible = false;
// set the buffer setting as on
asBLBuffer = true;
}
else if(asBLBuffer) {
// remove and stop the buffer animation
mcFLVDisplay.mcFLVBuffer.visible = false;
mcFLVDisplay.mcFLVBuffer.gotoAndStop(1);
// display the buffer directions on the main stage
mcFLVDisplay.mcFLVLoadTxt.visible = true;
// switch play/pause visibility
mcFLVCntl.btnPause.visible = false;
mcFLVCntl.btnPlay.visible = true;
// reset the buffer value to allow the updatePlayDisplay function to determine setting
asBLBuffer = false;
}
}
}
public function completeFLVLoad(event:Event):void {
// when the flv file has completely downloaded, remove the progress listening events
if(asURLFLVLoad.bytesLoaded == asURLFLVLoad.bytesTotal) {
removeEventListener(Event.OPEN, initFLVLoad);
removeEventListener(ProgressEvent.PROGRESS, updateFLVLoad);
}
// maintain the flv load bar width
mcFLVCntl.mcFLVTimeline.mcFLVLoad.width = 356;
// stop the stage buffer animation
mcFLVDisplay.mcFLVBuffer.visible = false;
mcFLVDisplay.mcFLVBuffer.gotoAndStop(1);
// reset the buffer value to allow the updatePlayDisplay function to determine setting
asBLBuffer = false;
}
I simply have to thank everyone on this site for this fantastic tutorial! It has both increased my Flash capabilities and helped me dramatically improve a currently outdated player.
Much as Adam has suggested above, I did find a way to implement a buffer that works in the "real-world" expected manner. The problem with the inherent Flash buffer is that it is only accounts for internal file management. The "bufferTime" property can be working just fine, but if a user of the video player scrubs ahead too far in the player, the user is accessing data that is outside the "bufferTime" scope. The "bufferTime", itself, really has nothing to do with where the user may be actually watching the video and more to do with information in the player, itself.
Following Adam's suggestion, I built several functions that incorporate the download progress of an FLV file, as well as the position of the progress playhead (whether scrubbed or playing automatically). Now I am a little new to Actionscript, so I'm sure there may be a more efficient way to write some of what I've done. However, I've come up with the following:
public function updateFLVLoad(event:ProgressEvent):void {
// check flv download progress
if(asURLFLVLoad.bytesLoaded (mcFLVCntl.mcFLVTimeline.mcFLVLoad.width - 5))) {
asNS.pause();
// switch play/pause visibility
mcFLVCntl.btnPause.visible = false;
mcFLVCntl.btnPlay.visible = true;
// display the buffer and start playing the buffer animation
mcFLVDisplay.mcFLVBuffer.visible = true;
mcFLVDisplay.mcFLVBuffer.play();
// remove the buffer text "resume" from the display
mcFLVDisplay.mcFLVLoadTxt.visible = false;
// set the buffer setting as on
asBLBuffer = true;
}
else if(asBLBuffer) {
// remove and stop the buffer animation
mcFLVDisplay.mcFLVBuffer.visible = false;
mcFLVDisplay.mcFLVBuffer.gotoAndStop(1);
// display the buffer directions on the main stage
mcFLVDisplay.mcFLVLoadTxt.visible = true;
// switch play/pause visibility
mcFLVCntl.btnPause.visible = false;
mcFLVCntl.btnPlay.visible = true;
// reset the buffer value to allow the updatePlayDisplay function to determine setting
asBLBuffer = false;
}
}
}
public function completeFLVLoad(event:Event):void {
// when the flv file has completely downloaded, remove the progress listening events
if(asURLFLVLoad.bytesLoaded == asURLFLVLoad.bytesTotal) {
removeEventListener(Event.OPEN, initFLVLoad);
removeEventListener(ProgressEvent.PROGRESS, updateFLVLoad);
}
// maintain the flv load bar width
mcFLVCntl.mcFLVTimeline.mcFLVLoad.width = 356;
// stop the stage buffer animation
mcFLVDisplay.mcFLVBuffer.visible = false;
mcFLVDisplay.mcFLVBuffer.gotoAndStop(1);
// reset the buffer value to allow the updatePlayDisplay function to determine setting
asBLBuffer = false;
}
Wonderful tutorial and just what I was searching for. Being able to load several videos and play them is terrific. I learned a lot about constructing the nuts and bolts symbols (movieclips, buttons) and using invisible buttons. As someone very new to ActionScript 3, I really value the comments and explanations. Thank you so much!
Become a TTL VIP Member & Get Notified of The Best Changes in Technology, Plus Win Prizes in Our VIP Only Contests...









HI EVERYONE , PLEASE i am trying to make something a bit like YouTube, i have all my music videos at the side of the page, now i want to be able to click on a video and it will enter the playlist then get played. Can this be done if so please help me Please
- spam
- offensive
- disagree
- off topic
Like