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的文件夹内,代码如下:
.这就是我封装的类!其中用到另外一个回调函数的类!我们将来编写回调函数的类,这个类放到一个名为playermedia的文件夹内,代码如下
下面我们来编写这个负责计算视频时间的工具类!这个类放到一个名为mathpool的文件夹内,代码如下:
这个类是比较简单的!下节中我们将编写视频宽高的工具类!其中涉及到一个算法!大家要去自己琢磨了!
下面我们就来看看这个算法究竟是什么样子的!依然是放到mathpool文件夹下,代码如下:
脚本不算多,但是其中的算法很重要!好了!关于视频类我们都写完了!后面我们要编写有关界面的类了!最多的还是涉及到位置的变换!
上一节中我们将视频类所需要的函数都写完了!本节开始我们来编写界面类!首先,我们要绘制我们所需要的一些界面元素,包括按钮等。我们就用截图的方式来向大家展示如何制作!
这就是笔者做的界面元素,分别为他们设置连接,具体连接的名称是什么大家可以在下面的脚本中查到!这个界面类是放到一个名为playerinterface文件夹内的,代码如下:
好了!这里我们又引出一个工具类!用来计算界面元素位置的!我们下节中编写该类。
这节我们来编写工具类!这个类放在名称为faceplace的文件夹内,代码如下:
好了!我们所有的自定义类都写完了!后面我们就来编写文档类!
终于到最后了!激动人心的时刻到来了!我们已经准备好了我们所需要的类,现在要做的就是写一个文档类,将这些零散的类综合起来!好了!看文档类的代码如下:
在FLA文件中将文档类改为Main,测试发布影片!~咦!怎么没有效果呢?别着急!我们这个FLV播放器是通过JS传递视频路径的,所以我们还需要一个HTML文件!下一节中我们再说!
前面我们已经完成了这个FLV播放器的代码编写阶段。接下来就是测试阶段了!我们写一个HTML文档!代码如下:
为了测试方便,我们可以自己找一段网络上的视频地址写到这个HTML文档中,也可以在同目录文件夹下放置一个FLV视频!运行网页,我们就可以看到效果了!这里笔者将播放器的运行画面截图。
这是播放器运行时候的画面!
我们的FLV播放器做完了!不知道大家有什么感想?其实做这样的一个播放器并非非常困难!只要我们用心去做。就一定能做好!
我这个播放器并不是非常的完美,其中可能还含有BUG!只是想起到一个抛砖引玉的作用!并不是让大家全班照抄来制作这样的播放器!
由于时间比较仓促,感觉这个程序的耦合度还是比较高。以后我会继续完善,陆续发出更新版本的!希望大家留意我的博客!我会在第一时间将最新版本的源码奉献给大家!
最后让大家看一下这个工程文件夹(主要是了解一下文件的结构)
很多人觉得这样将脚本复制一边有时候会出现错误!确实,为了方便大家学习,特意将这个源代码放到网上供大家下载!
点击下载
首先,当我们打开一个带视频的网页的时候,播放器显示该视频的一个截图:
像这样!当我们开始播放视频的时候,播放器会呈现下面界面:
我们来看!这个播放器有以下几个功能:
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!只是想起到一个抛砖引玉的作用!并不是让大家全班照抄来制作这样的播放器!
由于时间比较仓促,感觉这个程序的耦合度还是比较高。以后我会继续完善,陆续发出更新版本的!希望大家留意我的博客!我会在第一时间将最新版本的源码奉献给大家!
最后让大家看一下这个工程文件夹(主要是了解一下文件的结构)
很多人觉得这样将脚本复制一边有时候会出现错误!确实,为了方便大家学习,特意将这个源代码放到网上供大家下载!
点击下载
相关文章推荐
- Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能 视频网站中提供的在线视频播放功能,播放的都是FLV格式的文件,它是Flash动画文件,可通过Flash制作的播放器来播
- 给FCKeditor扩展插入FLV视频功能(含播放器)--研究成功给大家分享
- 给FCKeditor扩展插入FLV视频功能(含播放器)--研究成功给大家分享
- Js网络视频播放器之VideoJs&&ckplayer(直播拉流rtmp、hls)
- html使用vcastr3.swf播放器播放flv视频
- Android 音视频深入 十三 OpenSL ES 制作音乐播放器,能暂停和调整音量(附源码下载)
- Linux系统裁减之,制作一个极度精简的Linux-3-为精简的系统增加网络功能和关机重启功能
- 制作简单视频播放器
- Html5Video标签和Source标签制作视频播放器及画面大小切换和简单弹幕效果
- flv视频网站制作 使用Flex和PHP创建自己的视频应用
- VC:制作视频播放器(ActiveX控件、工具栏、菜单栏、滑块、打开对话框))
- [转载]利用FLV组件制作的播放器,动态获取变量,控制FLV文件
- S3c2410-linux实现网络视频监控功能
- VideoView和MediaController实现网络视频播放器demo
- rtmpdump 实现flv视频数据的rtmp推流功能
- 功能:网页FLV视频在线播放代码
- 初识AS3(十八)——制作简单视频播…
- kindeditor本身支持上传flash功能,但是我们经常需要上传一些flv、mp4或则其它格式的视频。 其实具体的播放功能是通过jwplayer实现的。我只对kindeditor简单的修改了一下
- 为kindeditor添加在线播放视频功能(基于原有flash上传,mp4,flv,flash)
- HTML5网络视频webm格式制作