I worked on a project where I built a video player. So far, nothing out of normality.
The issue was that we decided to set up the video dimensions on the Flash side rather than in the CMS with checkboxes or something similar.
Video dimensions vary in width and height, but also in proportion, or aspect ratio.
The client had all sorts of videos, 640 x 480, 400 x 300, 1280 x 720, etc.
The solution is to detect the file dimensions in an onMetaData event handler and set your visual elements accordingly.
For wide screen mode I decided to draw the black stripes on top and bottom.
I use the NetStream and NetConnection objects to handle the video file.
Preview:
HD video player
Here is the source code for the video player class.
HDVideoPlayer.as:
package src{
/*Import*/
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import caurina.transitions.*;
import caurina.transitions.properties.ColorShortcuts;
/*Class*/
public class HDVideoPlayer extends MovieClip {
/*Properties*/
private var mVideo:Video;
private var ncVideo:NetConnection = new NetConnection();
private var nsVideo:NetStream;
private var netClient:Object = new Object();
private var mySound:SoundTransform;
private var videoDuration:Number;
private var actualTime:Number = 0;
private var actualTimeDragger:Number;
private var actualLength:Number;
private var volPercentage:Number;
private var pctLoaded:Number;
private var pctPlayed:Number;
private var dragTime:Number;
private var videoURL:String = new String();
private var MODE:String;
private var mBG:Sprite = new Sprite();
private var mBlackStripes:Sprite = new Sprite();
private var mBGBar:Sprite = new Sprite();
private var mProgressBar:Sprite = new Sprite();
private var mLoadBar:Sprite = new Sprite();
private var mDragger:Sprite = new Sprite();
private var mControl:MovieClip = new MovieClip();
private var mPlay:PlayPause = new PlayPause();
private var mStop:Stop = new Stop();
private var mVolume:Volume = new Volume();
private var bFull:Full = new Full();
private var bBack:Back = new Back();
private var tAlert:TextField;
private var format:TextFormat = new TextFormat();
private var volEquation:Number;
private var videoWidth:Number;
private var videoHeight:Number;
private var ratio:Number;
private var diffDragger:Number = 0;
private var overColor:uint;
/*Constructor*/
public function HDVideoPlayer(fileData:Object):void{
trace("//---> HDVideoPlayer");
videoURL = fileData.file;
overColor = 0xFFFFFF;
ColorShortcuts.init();
addEventListener(Event.ADDED_TO_STAGE, init);
};
private function init(e:Event):void{
removeEventListener(Event.ADDED_TO_STAGE, init);
addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
buildVideo();
};
private function removedFromStage(e:Event):void{
trace("// ---- HDVideoPlayer removed from stage");
mySound.volume = 0;
nsVideo.soundTransform = mySound;
nsVideo.close();
ncVideo.close();
mVideo.clear();
mVideo.alpha = 0;
removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
};
public function buildVideo ():void{
MODE = "SD";
mBG.graphics.beginFill(0x231F20, 1);
mBG.graphics.drawRect(0, 0, 400, 364);
mBG.graphics.endFill();
mBG.alpha = 0;
addChild(mBG);
mBlackStripes.graphics.beginFill(0x000000, 1);
mBlackStripes.graphics.drawRect(0, 0, 400, 300);
mBlackStripes.graphics.endFill();
addChild(mBlackStripes);
mPlay.x = 25;
mPlay.y = 14;
mControl.addChild(mPlay);
mStop.x = 64;
mStop.y = 14;
mControl.addChild(mStop);
bFull.x = 175;
bFull.y = 10;
bFull.visible = false;
mControl.addChild(bFull);
bBack.x = -12;
bBack.y = -12;
bBack.visible = false;
addChild(bBack);
mVolume.x = 302;
mVolume.y = 18;
mControl.addChild(mVolume);
mBGBar.graphics.beginFill(0x3F3F3F, 1);
mBGBar.graphics.drawRect(0, 0, 400, 3);
mBGBar.graphics.endFill();
mBGBar.x = 0;
mBGBar.y = 54;
mControl.addChild(mBGBar);
mLoadBar.graphics.beginFill(0xFFFFFF, 1);
mLoadBar.graphics.drawRect(0, 0, 400, 3);
mLoadBar.graphics.endFill();
mLoadBar.x = 0;
mLoadBar.y = 54;
mLoadBar.width = 0;
mControl.addChild(mLoadBar);
mProgressBar.graphics.beginFill(0xF5F5F5, 1);
mProgressBar.graphics.drawRect(0, 0, 400, 3);
mProgressBar.graphics.endFill();
mProgressBar.x = 0;
mProgressBar.y = 54;
mProgressBar.alpha = 0;
mControl.addChild(mProgressBar);
mDragger.graphics.beginFill(0xFFFFFF, 1);
mDragger.graphics.drawRect(0, 0, 14, 7);
mDragger.graphics.endFill();
mDragger.x = 0;
mDragger.y = 47;
mControl.addChild(mDragger);
diffDragger = mBGBar.width - mDragger.width;
tAlert = new TextField();
tAlert.autoSize = TextFieldAutoSize.CENTER;
tAlert.x = 120;
tAlert.width = 160;
tAlert.height = 14;
tAlert.textColor = 0xFFFFFF;
format.font = "Arial";
format.bold = true;
format.color = 0xFFFFFF;
format.size = 8;
tAlert.defaultTextFormat = format;
mControl.addChild(tAlert);
mControl.y = 308;
mControl.alpha = 0;
addChild(mControl);
Tweener.addTween(mDragger,{_color:overColor, time:0});
Tweener.addTween(mControl, {alpha:1, time:1, transition:"linear",
onComplete:function(){
connectVideo();
}
});
};
public function connectVideo ():void{
//Video connection
ncVideo.connect(null);
nsVideo = new NetStream(ncVideo);
nsVideo.client = this;
nsVideo.bufferTime = 5;
mVideo = new Video();
mVideo.x = 0;
mVideo.y = 0;
addChild(mVideo);
this.swapChildren(mVideo, bBack);
mVideo.attachNetStream(nsVideo);
nsVideo.play(videoURL);
mVideo.smoothing = true;
mPlay.gotoAndStop(1);
//Sound
mySound = nsVideo.soundTransform;
mySound.volume = 1;
nsVideo.soundTransform = mySound;
//Bars
mLoadBar.width = 0;
mProgressBar.width = 0;
//Listeners
nsVideo.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
bFull.addEventListener(MouseEvent.MOUSE_DOWN, buildVideoHD);
bFull.addEventListener(MouseEvent.ROLL_OVER, eventOver);
bFull.addEventListener(MouseEvent.ROLL_OUT, eventOut);
bBack.addEventListener(MouseEvent.MOUSE_DOWN, backVideo);
bBack.addEventListener(MouseEvent.ROLL_OVER, eventOver);
bBack.addEventListener(MouseEvent.ROLL_OUT, eventOut);
mPlay.addEventListener(MouseEvent.MOUSE_DOWN, pauseVideo);
mPlay.addEventListener(MouseEvent.ROLL_OVER, eventOver);
mPlay.addEventListener(MouseEvent.ROLL_OUT, eventOut);
mStop.addEventListener(MouseEvent.MOUSE_DOWN, stopVideo);
mStop.addEventListener(MouseEvent.ROLL_OVER, eventOver);
mStop.addEventListener(MouseEvent.ROLL_OUT, eventOut);
mDragger.addEventListener(MouseEvent.MOUSE_DOWN, dragSeek);
mVolume.mVolSlider.addEventListener(MouseEvent.MOUSE_DOWN, volumeScrubberClicked);
stage.addEventListener(MouseEvent.MOUSE_UP, volumeScrubberUnClicked);
mVolume.mVolSlider.addEventListener(MouseEvent.ROLL_OVER, volumeScrubberRolledOver);
mLoadBar.addEventListener(Event.ENTER_FRAME, loadBar);
mPlay.buttonMode = true;
mStop.buttonMode = true;
bFull.buttonMode = true;
bBack.buttonMode = true;
mDragger.buttonMode = true;
mVolume.mVolSlider.buttonMode = true;
mPlay.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
mStop.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
bFull.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
bBack.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
};
public function eventOver (e:MouseEvent):void{
Tweener.addTween(e.currentTarget, {alpha:1, time:0.2, transition:"linear"});
};
public function eventOut (e:MouseEvent):void{
Tweener.addTween(e.currentTarget, {alpha:.5, time:0.2, transition:"linear"});
};
public function netStatusHandler(evt:NetStatusEvent):void{
if(evt.info.code == "NetStream.FileStructureInvalid"){
tAlert.text = "File structure invalid. ";
}else if(evt.info.code == "NetStream.NoSupportedTrackFound"){
tAlert.text = "File is not supported. ";
}else if (evt.info.code == "NetStream.Play.StreamNotFound") {
tAlert.text = "Error: Stream not found. ";
}else if (evt.info.code == "NetStream.Play.Start") {
tAlert.text = "Buffering video... ";
trace("evt.info.code --->>> "+evt.info.code+"\n")
}else if (evt.info.code == "NetStream.Buffer.Empty") {
tAlert.text = "Buffering video... ";
trace("evt.info.code --->>> "+evt.info.code+"\n")
}else if (evt.info.code == "NetStream.Buffer.Full") {
mPlay.gotoAndStop(2);
trace("evt.info.code --->>> "+evt.info.code+"\n")
tAlert.text = " ";
}else if (evt.info.code == "NetStream.Play.Stop"){
mPlay.gotoAndStop(1);
trace("evt.info.code --->>> "+evt.info.code+"\n")
}
};
public function onMetaData(obj:Object):void{
for(var propName:String in obj){
//trace("**Metadata video: "+propName + " = " + obj[propName])
if (propName == "width") {
videoWidth = obj[propName]
}
if (propName == "height") {
videoHeight = obj[propName]
}
};
ratio = videoHeight/videoWidth;
ratio = Number(ratio.toFixed(4));
//trace("videoWidth original ---> "+videoWidth)
//trace("videoHeight original ---> "+videoHeight)
//trace("ratio ---> "+ratio)
addEventListener(Event.ENTER_FRAME, dragSeekBar);
videoDuration = obj.duration;
setVideo();
};
private function setVideo():void{
if (MODE == "SD") {
mVideo.width = 400;
if (ratio < 0.6) {
bFull.visible = true;
mVideo.y = 36;
}else{
mVideo.y = 0;
bFull.visible = false;
}
}else if (MODE == "HD960"){
mVideo.width = 960;
}else if (MODE == "HD640"){
mVideo.width = 640;
}
mVideo.height = Math.round(mVideo.width*ratio);
trace("mVideo.height adjusted ---> "+mVideo.height)
};
public function buildVideoHD(obj:Object):void{
if (stage.stageHeight < 810) {
MODE = "HD640";
mBG.width = 640;
mBG.height = 424;
mBlackStripes.width = 640;
mBlackStripes.height = 360;
mBGBar.width = 640;
mLoadBar.width = 640;
mProgressBar.width = 640;
mControl.y = 368;
mVolume.x = 530;
bFull.x = 300;
bFull.visible = false;
bBack.x = -13;
bBack.visible = true;
tAlert.x = 320;
mVideo.y = 0;
setVideo();
diffDragger = mBGBar.width - mDragger.width;
}else{
MODE = "HD960";
mBG.width = 960;
mBG.height = 604;
mBlackStripes.width = 960;
mBlackStripes.height = 540;
mBGBar.width = 960;
mLoadBar.width = 960;
mProgressBar.width = 960;
mControl.y = 548;
mVolume.x = 850;
bFull.x = 460;
bFull.visible = false;
bBack.x = -13;
bBack.visible = true;
tAlert.x = 480;
mVideo.y = 0;
setVideo();
diffDragger = mBGBar.width - mDragger.width;
}
};
public function backVideo(obj:Object):void{
MODE = "SD";
mBG.width = 400;
mBG.height = 364;
mBlackStripes.width = 400;
mBlackStripes.height = 300;
mBGBar.width = 400;
mLoadBar.width = 400;
mProgressBar.width = 400;
mControl.y = 308;
mVolume.x = 302;
bFull.x = 175;
bBack.visible = false;
tAlert.x = 120;
setVideo();
diffDragger = mBGBar.width - mDragger.width;
};
public function pauseVideo(evt:MouseEvent):void{
if (mPlay.currentFrame == 2) {
mPlay.gotoAndStop(1);
nsVideo.pause();
}else{
mPlay.gotoAndStop(2);
setVideo();
nsVideo.resume();
}
};
public function stopVideo(evt:MouseEvent):void{
nsVideo.pause();
nsVideo.seek(0);
mPlay.gotoAndStop(1);
};
public function loadBar(evt:Event):void{
//trace("buffer ---> "+nsVideo.bufferLength)
pctLoaded = Math.floor(nsVideo.bytesLoaded / nsVideo.bytesTotal * 100);
Tweener.addTween(mLoadBar, {width: (mBGBar.width * pctLoaded) / 100, time:1, transition:"linear"});
if (pctLoaded >= 100){
evt.currentTarget.removeEventListener(Event.ENTER_FRAME, loadBar);
}
};
public function dragSeekBar(evt:Event):void{
actualTime = nsVideo.time;
Tweener.addTween(mDragger, {x: Math.round(actualTime / videoDuration * diffDragger), time:.1, transition:"linear"});
actualTime = nsVideo.time;
if (Math.round(actualTime) == Math.round(videoDuration)){
Tweener.addTween(this, {time:1, transition:"linear",
onComplete:function(){
tAlert.text = "";
nsVideo.pause();
nsVideo.seek(0);
mPlay.gotoAndStop(1);
}
});
}
};
public function dragSeek(evt:Event):void{
//actualTimeDragger = int(((evt.currentTarget.x) / mBGBar.width) * videoDuration);
nsVideo.pause();
removeEventListener(Event.ENTER_FRAME, dragSeekBar);
Tweener.removeAllTweens();
stage.addEventListener(MouseEvent.MOUSE_UP, dragSeekOut);
evt.currentTarget.startDrag(false, new Rectangle(0,47,diffDragger,0));
};
public function dragSeekOut(evt:MouseEvent):void{
dragTime = Math.round(mDragger.x / diffDragger * videoDuration);
actualTime = dragTime;
mDragger.x = (actualTime / videoDuration * diffDragger);
nsVideo.seek(dragTime);
nsVideo.resume();
mPlay.gotoAndStop(2);
mDragger.stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_UP, dragSeekOut);
addEventListener(Event.ENTER_FRAME, dragSeekBar);
};
public function volumeScrubberClicked(evt:Event):void {
mVolume.mVolSlider.startDrag(false, new Rectangle(8, 0, 66, 0));
mVolume.mVolSlider.addEventListener(Event.ENTER_FRAME, volumeScrubberSlide);
};
public function volumeScrubberRolledOver(evt:Event):void {
evt.currentTarget.buttonMode = true;
};
public function volumeScrubberUnClicked(evt:Event):void {
mVolume.mVolSliderbuttonMode = false;
mVolume.mVolSlider.stopDrag();
mVolume.mVolSlider.removeEventListener(Event.ENTER_FRAME, volumeScrubberSlide);
};
public function volumeScrubberSlide(evt:Event):void{
volEquation = (100*(evt.currentTarget.x - 8))/66;
volPercentage = volEquation / 100;
mySound.volume = volPercentage;
nsVideo.soundTransform = mySound;
};
public 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";
}
};
};// end player class
};// end package
You can download the entire source code here:
The library contains all the visual elements and in the Main.as file you can change which video sample to play.
There are three high-def videos to play with.
I uploaded them separately because they are quite big.
So, download it from here and place it in the video folder from the HDVideo_source.zip file.