您的位置:首页 > 理论基础 > 计算机网络

AS3制作全功能的FLV网络视频播放器

2010-11-08 09:06 316 查看
从本节开始,我将带领大家制作一个全功能的FLV网络播放器。我们为了方便就以优酷网的播放器为例子,来制作一个仿优酷的视频播放器。好了!我们来看一下优酷网的播放器到时是怎样运行的呢?

首先,当我们打开一个带视频的网页的时候,播放器显示该视频的一个截图:



像这样!当我们开始播放视频的时候,播放器会呈现下面界面:



我们来看!这个播放器有以下几个功能:

1、视频的播放与停止

2、视频的当前播放时间

3、视频的总时间

4、视频的加载进度

5、视频的播放进度

6、音量控制

7、全屏控制

8、视频的亮度调节

9、视频的快进

10、视频的快退

11、视频选择功能(当视频播放完毕后)

视频播放完毕之后会出现下面这个界面:



在这个界面当中,我们又可以看到几个功能,我们来总结一下:

1、4个热门视频(这4个热门视频每个一定的时间就会自动的替换)

2、热门视频的翻页功能

3、视频的重播

4、复制FLASH地址功能

5、复制HTML代码功能(这个功能我们可以不要,因为每个网站的代码都有所不同。)

6、视频搜索功能

好了!我们已经把这个视频播放器所有所需要的功能都总结了起来!接下来我们就要一步一步去实现这个播放器!

(二)

大家好!我们本节来讲解AS3制作FLV视频播放器的原理。在做播放器之前,我们先来设计一下程序的运行流程,并把这个流程制作成流程图。这样做起来,就显得方便快捷。我们可以尽量详细的描写我们程序的运行流程,不过要从宏观上去考虑。具体遇到的编程问题再慢慢去解决!



我们来看一下这个流程图(这个是偶自己取的名字)!首先是主文件接受外部的参数,包括视频地址,选项等等。然后在主文件中我们来定义一些事件,比如说按钮事件,有关视频的事件等等。透过这些事件我们又对视频流和界面元素进行了调用。最后是视频流中的一些数据进行数据处理,然后将这些数据在传递给主文件。好了!这样就完成了一个播放器的全部工作流程。

很多人都有一个不好的习惯,就是说到一个效果,拿来就做,没有一个计划。这样反而事倍功半。不仅写起来很费劲,而且返工的机率很大。所有我们在做一些FLASH交互式程序的时候一定要先构思,再动手去做。

好了!我们现在来仔细考虑,这个程序的一些细节。我们用顺序号来表示。

1、当网页被打开的时候,我们要FLASH接受几个参数。这些参数决定着播放器的一些选项。

2、网页被打开的时候,FLASH要读取自身的宽高。这个要用来对视频的宽高进行限制。

3、播放器检测视频连接是否正常,检查跨域访问权限。

4、开始播放视频。

5、视频的各个调节功能(包括进度,声音,全屏,亮度等)。

6、视频播放结束后的工作。

7、断开所有数据流!

这样,我们的程序功能就清楚可见了!根据这个来制作程序效率是非常高的。

(三)

时间很仓促,为了完成这套教程,特意抽出了3天的业余时间来制作这个FLV播放器。其中难免有BUG,如果大家发现了BUG欢迎留言给我。再不断的完善!

那么首先提一个问题,制作一个中型的FLASH交互式程序是先写文档类还是先写别的自定义类呢?我个人觉得应该先写自定义类,将我们所需要的功能都封装好后再写文档类。这样写起来比较方便。好了!废话不多说,我们本节先来写第一个类吧!

我们平常播放FLV视频要三个类,笔者感觉这样写比较麻烦。所以我的第一步就是从新封装Video类。让这个类和另外2个类封装到一起。好了这个封装的类放到了一个名为playermedia的文件夹内,代码如下:

/*A闪工作室 编写
版权所有 本实例不可用于商业用途,违者必究
2009.9.11 作者:A闪
*/
package playermedia{
import playermedia.CustomClient;
import flash.media.SoundTransform;
import flash.events.IOErrorEvent;
import flash.events.NetStatusEvent;
import flash.events.AsyncErrorEvent;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
public class Playervideo extends Video {
private var netconnection:NetConnection;
private var netstream:NetStream;
private var video_url:String;
private var videosound:SoundTransform;
public static var video_time:Number=0;
public function Playervideo():void {
CustomClient.setdata(this);
netconnection=new NetConnection ;
netconnection.connect(null);
netstream=new NetStream(netconnection);
netstream.client=new CustomClient ;
videosound = new SoundTransform();
videosound.volume = 1;
netstream.soundTransform = videosound;
this.attachNetStream(netstream);
netstream.checkPolicyFile = true;
netconnection.addEventListener(NetStatusEvent.NET_STATUS,streamnotfound);
netconnection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,netmistake);
netconnection.addEventListener(IOErrorEvent.IO_ERROR,mistake);
netstream.addEventListener(IOErrorEvent.IO_ERROR,mistake);
netstream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,netmistake);
netstream.addEventListener(NetStatusEvent.NET_STATUS,streamnotfound);
}
private function netmistake(evt:AsyncErrorEvent):void {
trace("异步错误");
}
private function streamnotfound(evt:NetStatusEvent):void {
switch (evt.info.code) {
case "NetStream.Play.Stop" :
CustomClient.stopvideo();
break;
case "NetStream.Play.Start" :
trace("视频开始播放");

break;
case "NetStream.Buffer.Empty" :
trace("数据的接收速度不足以填充缓冲区。");
break;
case "NetStream.Buffer.Full" :
trace("缓冲区已满并且流将开始播放。");
CustomClient.secplay();
break;
case "NetStream.Buffer.Flush" :
trace("数据已完成流式处理,剩余的缓冲区将被清空。");
break;
case "NetStream.Seek.Notify" :
trace("搜寻操作完成。");

break;
}
}
private function mistake(evt:IOErrorEvent):void {
//错误处理代码
trace("错了!");
}
//播放视频
public function playvideo(url:String):void {
netstream.play(url);
video_url = url;
}
//加载条进度百分比
public function loadprogress():Number {
return netstream.bytesLoaded / netstream.bytesTotal;
}
//视频的播放时间计算
public function playtime():String {
var streamminute:Number = Math.floor(netstream.time / 60);
var smin_str:String;
if (streamminute>=10) {
smin_str = String(streamminute);
} else {
smin_str = "0" + streamminute;
}
var streamsecond:Number = Math.round(netstream.time % 60);
var ssec_str:String;
if (streamsecond>=10) {
ssec_str = String(streamsecond);
} else {
ssec_str = "0" + streamsecond;
}
var newtime:String = smin_str + ":" + ssec_str;
return newtime;
}
//设置视频音量
public function setsound(sound_data:Number):void {
videosound.volume = sound_data;
netstream.soundTransform = videosound;
}
//播放或停止视频
public function playstopvideo():void {
netstream.togglePause();
}
//计算当前播放时间的百分比
public function playvideonowtime():Number {
return netstream.time / video_time;
}
//跳转视频
public function playtimevideo(whereplaytime:Number):void {
netstream.seek(whereplaytime);
netstream.play(video_url);
netstream.togglePause();
}
public function playtimemyvideo(timevideo:Number):void{
netstream.seek(timevideo);
}
}
}


.这就是我封装的类!其中用到另外一个回调函数的类!我们将来编写回调函数的类,这个类放到一个名为playermedia的文件夹内,代码如下

]/*A闪工作室 编写
版权所有 本实例不可用于商业用途,违者必究
2009.9.11 作者:A闪
*/
package playermedia{
import mathpool.Videorange;
import mathpool.Videotime;
import playermedia.Playervideo;
import Main;
import flash.media.Video;
public class CustomClient {
public static var stage_width:Number=320;
public static var stage_height:Number=280;
private static var stage_video:Video;
public function onMetaData(info:Object):void {
Videotime.caltime(info.duration);
Playervideo.video_time = info.duration;
stage_video.width = info.width;
stage_video.height = info.height;
Main._videowidth = info.width;
Main._videoheight = info.height;
Main.videowhboolean = true;
Main.timeforvideo = info.duration;
Videorange.videosize(stage_video,info.width,info.height,stage_width,stage_height);
}
//设置Video对象
public static function setdata(obj:Video):void {
stage_video = obj;
}
//视频停止
public static function stopvideo():void{
Main.video_durationboolean = false;
Main.playboolean = false;
}
//视频开始播放
public static function secplay():void{
Main.proboolean = false;
}
}
}
好了!这个类中我们又引出了两个工具类!分别是用来计算视频宽高和视频时间的类!我们将在后面两节中编写这两个工具类!

下面我们来编写这个负责计算视频时间的工具类!这个类放到一个名为mathpool的文件夹内,代码如下:

*/
package mathpool{
import Main;
public class Videotime {
public static function caltime(video_time:Number):void {
var minute:Number=Math.floor(video_time / 60);
var min_str:String;
if (minute >= 10) {
min_str=String(minute);
} else {
min_str="0" + minute;
}
var second:Number=Math.round(video_time % 60);
var sec_str:String;
if (second >= 10) {
sec_str=String(second);
} else {
sec_str="0" + second;
}
Main.videotime=min_str + ":" + sec_str;
}
}
}


这个类是比较简单的!下节中我们将编写视频宽高的工具类!其中涉及到一个算法!大家要去自己琢磨了!

下面我们就来看看这个算法究竟是什么样子的!依然是放到mathpool文件夹下,代码如下:

package mathpool{
import flash.media.Video;
public class Videorange {
public static function videosize(obj:Video,video_width:Number,video_height:Number,stage_width:Number,stage_height:Number):void {
if ((video_width/video_height)<(stage_width/(stage_height-40))) {
obj.height = stage_height-40;
obj.width = (stage_height-40)*video_width/video_height;
obj.x = (320-stage_width)/2 + Math.abs((stage_width-obj.width)/2);
obj.y = (280-stage_height)/2;
} else if ((video_width/video_height)>(stage_width/(stage_height-40))) {
obj.width = stage_width;
obj.height = stage_width*video_height/video_width;
obj.x = (320-stage_width)/2;
obj.y = (280-stage_height)/2 + Math.abs((stage_height-obj.height-40)/2);
} else if ((video_width/video_height)==(stage_width/(stage_height-40))) {
obj.width = stage_width;
obj.height = stage_height-40;
obj.x = (320-stage_width)/2;
obj.y = (280-stage_height)/2;
}
}
}
}


脚本不算多,但是其中的算法很重要!好了!关于视频类我们都写完了!后面我们要编写有关界面的类了!最多的还是涉及到位置的变换!

上一节中我们将视频类所需要的函数都写完了!本节开始我们来编写界面类!首先,我们要绘制我们所需要的一些界面元素,包括按钮等。我们就用截图的方式来向大家展示如何制作!



这就是笔者做的界面元素,分别为他们设置连接,具体连接的名称是什么大家可以在下面的脚本中查到!这个界面类是放到一个名为playerinterface文件夹内的,代码如下:

package playerinterface{
//导入工具类
import faceplace.facepool;
//导入文本类
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
//导入基类
import flash.display.Sprite;
public class Drawinterface extends Sprite {
//创建对象
private var progressbarBackground:ProgressbarBackground;
public var progressbutton:ProgressButton;
public var playandstopbutton:PlayAndStopButton;
private var timeframe:TimeFrame;
private var soundbackground:SoundBackground;
public var soundmute:SoundMute;
public var soundregulate:SoundRegulate;
public var fullscreen:FullScreen;
private var loadprogress:LoadProgress;
private var timetext:TextField;
private var loadprogress_width:Number;
public function Drawinterface():void {
//设置文本
timetext = new TextField();
timetext.width = 80;
timetext.height = 17;
timetext.autoSize = TextFieldAutoSize.CENTER;
timetext.selectable = false;
timetext.textColor = 0x000000;
timetext.text = "00:00/00:00";
//新建对象
progressbarBackground = new ProgressbarBackground();
progressbutton = new ProgressButton();
playandstopbutton = new PlayAndStopButton();
timeframe = new TimeFrame();
soundbackground = new SoundBackground();
soundmute = new SoundMute();
soundregulate = new SoundRegulate();
fullscreen = new FullScreen();
loadprogress = new LoadProgress();
//将对象添加到显示列表
addChild(progressbarBackground);
addChild(loadprogress);
addChild(progressbutton);
addChild(playandstopbutton);
playandstopbutton.gotoAndStop(2);
addChild(timeframe);
timeframe.addChild(timetext);
addChild(soundbackground);
addChild(soundmute);
soundmute.stop();
soundbackground.addChild(soundregulate);
addChild(fullscreen);
fullscreen.stop();
}
public function moveinterface(rootwidth:Number=320,rootheight:Number=280,setsound:Number=71):void{
//对显示元素进行重新的位置排列
facepool.getdata(progressbarBackground,rootwidth,rootheight,setsound);
loadprogress_width = facepool.getdata(loadprogress,rootwidth,rootheight,setsound);
facepool.getdata(progressbutton,rootwidth,rootheight,setsound);
facepool.getdata(playandstopbutton,rootwidth,rootheight,setsound);
facepool.getdata(timeframe,rootwidth,rootheight,setsound);
facepool.getdata(soundbackground,rootwidth,rootheight,setsound);
facepool.getdata(soundmute,rootwidth,rootheight,setsound);
facepool.getdata(soundregulate,rootwidth,rootheight,setsound);
facepool.getdata(fullscreen,rootwidth,rootheight,setsound);
}
//设置文本显示内容
public function showtime(now:String):void{
timetext.text = now;
}
//进度条长度
public function loadprogresswidth(percentage:Number):void{
loadprogress.width = loadprogress_width*percentage;
}
}
}


好了!这里我们又引出一个工具类!用来计算界面元素位置的!我们下节中编写该类。

这节我们来编写工具类!这个类放在名称为faceplace的文件夹内,代码如下:

package faceplace{
import flash.utils.getQualifiedClassName;
public class facepool {
public static function getdata(obj:*,thewidth:Number,theheight:Number,soundX:Number=71):* {
switch (getQualifiedClassName(obj)) {
case "ProgressbarBackground" :
obj.x = (thewidth - 320) / 2 * -1;
obj.y = (theheight-240)/2+220;
obj.width = thewidth;
break;
case "LoadProgress" :
obj.x = ((thewidth-320)/2-6)*-1;
obj.y = (theheight-240)/2+225.5;
obj.width = thewidth-12;
return obj.width;
break;
case "ProgressButton":
obj.x = (thewidth-320)/2*-1+5;
obj.y = (theheight-240)/2+230;
break;
case "PlayAndStopButton":
obj.x = (thewidth - 320) / 2 * -1+5;
obj.y = (theheight-240)/2+239;
break;
case "TimeFrame":
obj.x = (thewidth - 320) / 2 * -1+65;
obj.y = (theheight-240)/2+239;
break;
case "SoundBackground":
obj.x = (thewidth - 320) / 2+190;
obj.y = (theheight-240)/2+239;
break;
case "SoundMute":
obj.x = (thewidth - 320) / 2+193;
obj.y = (theheight-240)/2+240;
break;
case "SoundRegulate":
obj.x = soundX;
obj.y = 16;
break;
case "FullScreen":
obj.x = (thewidth - 320) / 2+285;
obj.y = (theheight-240)/2+239;
break;
}
}
}
}


好了!我们所有的自定义类都写完了!后面我们就来编写文档类!

终于到最后了!激动人心的时刻到来了!我们已经准备好了我们所需要的类,现在要做的就是写一个文档类,将这些零散的类综合起来!好了!看文档类的代码如下:

package {
//导入矩阵类
import flash.geom.Rectangle;
//导入视频参数类
import playermedia.CustomClient;
//导入视频大小调整类
import mathpool.Videorange;
//导入按钮事件
import flash.events.MouseEvent;
//导入视频类
import playermedia.Playervideo;
//导入界面类
import playerinterface.Drawinterface;
//导入JS交互类
import flash.external.ExternalInterface;
//导入计时类
import flash.utils.setInterval;
import flash.utils.clearInterval;
//导入事件类
import flash.events.Event;
//导入舞台类
import flash.display.Stage;
//导入舞台缩放类型
import flash.display.StageScaleMode;
//导入基类
import flash.display.Sprite;
public class Main extends Sprite {
//总体时间长度
public static var videotime:String = "00:00";
//界面对象
private var playerface:Drawinterface;
//视频的宽高
public static var _videowidth:Number;
public static var _videoheight:Number;
//计时器的次数
private var counter:uint = 0;
//计时对象
private var intervalId:uint;
//播放器的宽
private var stagewidth:Number = 320;
//视频地址
private var flvvideourl:String;
//视频宽高改变开关
public static var videowhboolean:Boolean = false;
//视频对象
private var flvvideo:Playervideo;
//视频的总时间长
public static var timeforvideo:Number;
//视频载入进度判断开关
private var loadvideoboolean:Boolean = false;
//舞台宽高改变开关
private var rootsizeboolean:Boolean = false;
//静音按钮开关
private var soundboolean:Boolean = false;
//音量调节按钮的X轴
private var soundbuttonX:Number = 71;
//视频播放的状态记录
public static var playboolean:Boolean = true;
//视频播放完毕判断
public static var video_durationboolean:Boolean = true;
//视频进度滑块的拖动范围
private var buttonre:Rectangle;
//时间拖动开关
public static var proboolean:Boolean = true;
//****************************************//
//构造器函数
public function Main():void {
//设置播放器的缩放类型为无缩放
stage.scaleMode = StageScaleMode.NO_SCALE;
//设置播放器的宽高响应
stage.addEventListener(Event.RESIZE,rangerevision);
//对播放器的下载进度进行监视
this.loaderInfo.addEventListener(Event.COMPLETE,loadthis);
}
//****************************************//
//播放器的宽高发生改变是进行响应的函数
private function rangerevision(evt:Event):void {
//将舞台宽赋予一个变量
stagewidth = stage.stageWidth;
//设置CustomClient类中的静态变量,将他们的值赋予舞台坐标
CustomClient.stage_width = stage.stageWidth;
CustomClient.stage_height = stage.stageHeight;
//界面元素进行位置调整
playerface.moveinterface(stage.stageWidth,stage.stageHeight,soundbuttonX);
//视频尺寸改变
if (videowhboolean) {
//调用视频类的一个函数,从而设置视频的宽高
Videorange.videosize(flvvideo,_videowidth,_videoheight,stage.stageWidth,stage.stageHeight);
}
//定义舞台上进度按钮的拖动范围
buttonre = new Rectangle(playerface.progressbutton.x,playerface.progressbutton.y,(stagewidth-10),0);
}
//****************************************//
//载入完成后执行
private function loadthis(evt:Event):void {
//运行初始化函数
init();
//删除播放器下载监视函数
this.loaderInfo.removeEventListener(Event.COMPLETE,loadthis);
}
//****************************************//
//初始化
private function init():void {
//生成视频
loadvideo();
//生成界面
playerface = new Drawinterface();
//将界面元素添加到显示列表
addChild(playerface);
//界面元素位置进行设置
playerface.moveinterface();
//对界面元素定义事件
playerface.soundregulate.addEventListener(MouseEvent.MOUSE_DOWN,sounddown);
playerface.soundregulate.addEventListener(MouseEvent.MOUSE_UP,soundup);
addEventListener(MouseEvent.MOUSE_UP,soundup);
stage.addEventListener(MouseEvent.MOUSE_UP,soundup);
flvvideo.addEventListener(MouseEvent.MOUSE_UP,soundup);
playerface.soundmute.addEventListener(MouseEvent.CLICK,soundup);
playerface.fullscreen.addEventListener(MouseEvent.CLICK,fullroot);
playerface.playandstopbutton.addEventListener(MouseEvent.CLICK,playvideo);
playerface.progressbutton.addEventListener(MouseEvent.MOUSE_DOWN,proset);
//重新定义进度滑块的拖动范围
buttonre = new Rectangle(playerface.progressbutton.x,playerface.progressbutton.y,310,0);
//JS调用
readjavascript();
//定义一个逐帧函数
addEventListener(Event.ENTER_FRAME,work);
}
//****************************************//
//生成视频对象
private function loadvideo():void {
//视频传递参数以及生成视频对象
flvvideo = new Playervideo();
//将视频添加到显示列表
addChildAt(flvvideo,0);
//定义变量的值
loadvideoboolean = true;
}
//****************************************//
//调用外部JS函数
private function readjavascript():void {
//判断该网页中的FLASH是否允许接受JS参数
if (ExternalInterface.available) {
//调试语句
try {
//对外部的JS开放一个接口
ExternalInterface.addCallback("setvideodata",acceptjsurl);
//当发生错误时进行响应
} catch (e:SecurityError) {
//跨域访问的权限错误
} catch (e:SecurityError) {
//无法回调
} catch (e:Error) {
//数据连接失败
}
//调用外部JS函数
ExternalInterface.call("sendToActionScript");
}
}
//响应JS的函数实体
/*videourl控制视频路径,playboolean控制是否开始播放*/
private function acceptjsurl(videourl:String = null):void {
//讲传递过来的参数进行赋值
flvvideourl = videourl;
flvvideo.playvideo(flvvideourl);
//判断时候接受到了视频参数
if (videourl==null&&counter==0) {
//调用调试函数
calculagraphjs();
}
}
//****************************************//
//计时,查看JS参数是否接收到
private function calculagraphjs():void {
//定义一个时间函数
intervalId = setInterval(detectvideourl,3000);
}
//对JS函数进行调用以获取视频的路径,时间函数的响应函数
private function detectvideourl():void {
//查看是否接受到路径,
if (flvvideourl==null) {
//如果没有接收到参数则调用JS的函数,再次获取参数
counter++;
ExternalInterface.call("sendToActionScript");
//如果获取函数超过3次,则不再尝试!直接报错!
if (counter==4) {
clearInterval(intervalId);
}
} else {
//当获取到了参数时,清除这个时间函数
clearInterval(intervalId);
}
}
//****************************************//
//逐帧函数
private function work(evt:Event):void {
var video_time:String;
var videopro:Number;
if (loadvideoboolean) {
//显示视频的当前播放时间和总体时间
video_time = flvvideo.playtime();
playerface.showtime(video_time+"/"+videotime);
//设置进度条长度
playerface.loadprogresswidth(flvvideo.loadprogress());
}
videopro = flvvideo.playvideonowtime();
if (proboolean==false) {
//设置进度按钮的位置
playerface.progressbutton.x = (stagewidth-10)*videopro + (320-stagewidth)/2+5;
}
if (video_durationboolean==false) {
//让播放按钮跳转到第一帧
playerface.playandstopbutton.gotoAndStop(1);
}
}
//****************************************//
//声音按钮按下响应
private function sounddown(evt:MouseEvent):void {
//声音按钮拖动
var soundre:Rectangle = new Rectangle(22,16,49,0);
evt.target.startDrag(false,soundre);
}
//*********************************************//
//鼠标抬起响应函数,对声音调节和进度调节有效
private function soundup(evt:MouseEvent):void {
//停止拖动
playerface.soundregulate.stopDrag();
playerface.progressbutton.stopDrag();
//调节视频的进度,通过进度按钮
if (stagewidth>=320) {
flvvideo.playtimemyvideo(Math.round((Math.abs((stagewidth-320)/2)+playerface.progressbutton.x)/(stagewidth-10)*timeforvideo));
} else {
flvvideo.playtimemyvideo(Math.round((playerface.progressbutton.x-(320-stagewidth)/2)/(stagewidth-10)*timeforvideo));
}
//对静音按钮和音量调节按钮作出响应
if (evt.target.name=="instance14"&&soundboolean == false) {
playerface.soundregulate.x = 22;
flvvideo.setsound(0);
playerface.soundmute.nextFrame();
soundboolean = !soundboolean;
} else if (evt.target.name=="instance14"&&soundboolean == true) {
playerface.soundregulate.x = soundbuttonX;
flvvideo.setsound((playerface.soundregulate.x-22)/49);
soundboolean = !soundboolean;
playerface.soundmute.prevFrame();
} else {
flvvideo.setsound((playerface.soundregulate.x-22)/49);
soundbuttonX = playerface.soundregulate.x;
}
}
//****************************************//
//全屏函数
private function fullroot(evt:MouseEvent):void {
switch (stage.displayState) {
case "normal" :
stage.displayState = "fullScreen";
evt.target.nextFrame();
break;
case "fullScreen" :
default :
stage.displayState = "normal";
evt.target.prevFrame();
break;
}
}
//****************************************//
//对播放按钮的点击事件进行响应的函数
private function playvideo(evt:MouseEvent):void {
if (playboolean==true) {
evt.target.prevFrame();
} else {
evt.target.nextFrame();
if (video_durationboolean==false) {
flvvideo.playtimevideo(0);
video_durationboolean = !video_durationboolean;
}
}
flvvideo.playstopvideo();
playboolean = !playboolean;
}
//****************************************//
//进度调节按钮的拖动事件响应函数
private function proset(evt:MouseEvent):void {
proboolean = true;
evt.target.startDrag(false,buttonre);
}
}
}

在FLA文件中将文档类改为Main,测试发布影片!~咦!怎么没有效果呢?别着急!我们这个FLV播放器是通过JS传递视频路径的,所以我们还需要一个HTML文件!下一节中我们再说!

前面我们已经完成了这个FLV播放器的代码编写阶段。接下来就是测试阶段了!我们写一个HTML文档!代码如下:

<!-- saved from url=(0014)about:internet -->
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>FLASH与JS交互</title>
<mce:script language="JavaScript"><!--
function sendToActionScript(value) {
window.ExternalInterfaceExample.setvideodata("aa.flv");
}
// --></mce:script>
</head>
<body>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id="ExternalInterfaceExample" width="500" height="500"
>
<param name="movie" value="flvplayerbeta1.swf" />
<param name="allowFullScreen" value="true" />
</object>
</body>
</html>


为了测试方便,我们可以自己找一段网络上的视频地址写到这个HTML文档中,也可以在同目录文件夹下放置一个FLV视频!运行网页,我们就可以看到效果了!这里笔者将播放器的运行画面截图。



这是播放器运行时候的画面!

我们的FLV播放器做完了!不知道大家有什么感想?其实做这样的一个播放器并非非常困难!只要我们用心去做。就一定能做好!

我这个播放器并不是非常的完美,其中可能还含有BUG!只是想起到一个抛砖引玉的作用!并不是让大家全班照抄来制作这样的播放器!

由于时间比较仓促,感觉这个程序的耦合度还是比较高。以后我会继续完善,陆续发出更新版本的!希望大家留意我的博客!我会在第一时间将最新版本的源码奉献给大家!

最后让大家看一下这个工程文件夹(主要是了解一下文件的结构)



很多人觉得这样将脚本复制一边有时候会出现错误!确实,为了方便大家学习,特意将这个源代码放到网上供大家下载!

点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐