最近在项目中要用到flv播放器,由于flex自带的VideoDisplay组件不是很好用,就自己简单实现了一个,界面不是很美观,但功能都有了,正可谓麻雀虽小五脏俱全。下面是播放器的代码,还不会用flash做flv播放器的朋友,可以参考参考。
Player.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" backgroundColor="#000000" creationComplete="completeHandler()"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Script>
<![CDATA[
import mx.events.SliderEvent;
import mx.core.UIComponent;
import mx.controls.Alert;
import mx.utils.StringUtil;
private var _source:String;
private var _autoPlay:Boolean;
public var videoWidth:Number = 0;
public var videoHeight:Number = 0;
private var nc:NetConnection;
[Bindable] private var ns:NetStream;
private var videoContainer:UIComponent;
private var video:Video;
private var initIndex:int = 1;
private var rtmpUrl:String;
private var fileName:String;
private var timer:Timer;
private var totalTime:Number;
[Embed(source="assets/play.png")]
[Bindable]
private var playImage:Class;
[Embed(source="assets/pause.png")]
[Bindable]
private var pauseImage:Class;
[Embed(source="assets/stop.png")]
[Bindable]
private var stopImage:Class;
public function set source(src:String):void{ // 设置flv地址,rtmp和http都支持,绝对路径
var beginIndex:int
var endIndex:int;
this._source = src;
if(src.indexOf("rtmp") == 0){
endIndex = this._source.lastIndexOf("/");
this.rtmpUrl = this.source.substring(0, endIndex);
beginIndex = endIndex;
endIndex = this._source.lastIndexOf(".");
this.fileName = this._source.substring(beginIndex + 1, endIndex);
}
else{
this.rtmpUrl = null;
this.fileName = src;
}
if(this._autoPlay){
this.play();
}
}
public function get source():String{
return this._source;
}
public function set autoPlay(auto:Boolean):void{
this._autoPlay = auto;
}
public function get autoPlay():Boolean{
return this._autoPlay;
}
private function completeHandler():void{ //初始化完毕后设置video对象的大小,要把video对象加入到Flex的UI控件中,必须先用UIComponent或其子类包装。
this.video = new Video();
this.video.width = (this.videoWidth == 0 ? this.width : this.videoWidth);;
this.video.height = (this.videoHeight == 0 ? this.height - this.controlBar.height : this.videoHeight - this.controlBar.height);
this.videoContainer = new UIComponent();
this.videoContainer.addChild(this.video);
this.addChild(this.videoContainer);
this.videoContainer.addEventListener(MouseEvent.CLICK,videoClickHandler);
if(this._autoPlay){
this.playPauseBtn.label = "暂停";
this.playPauseBtn.setStyle("icon",this.pauseImage);
}
else{
this.playPauseBtn.label = "播放";
this.playPauseBtn.setStyle("icon",this.playImage);
}
}
private function init():void{
this.initIndex = 2;
if(StringUtil.trim(this._source) != ""){
this.nc = new NetConnection();
this.nc.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);
this.nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
this.nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErrorHandler);
this.nc.connect(this.rtmpUrl);
}
}
private function netStatusHandler(event:NetStatusEvent):void{
switch(event.info.code){
case "NetConnection.Connect.Success":
this.connectStream();
trace("NetConnection.Connect.Success");
break;
case "NetStream.Play.StreamNotFound":
trace("Stream not found At NetConnection: " + this._source);
break;
}
}
private function connectStream():void{
this.ns = new NetStream(this.nc);
this.ns.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler2);
this.ns.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
this.ns.client = {};
this.ns.client.onMetaData = metaDataHandler;
this.ns.client.onCuePoint = cuePointHandler;
this.video.attachNetStream(this.ns);
this.ns.play(this.fileName);
}
private function netStatusHandler2(event:NetStatusEvent):void{
switch(event.info.code){
case "NetConnection.Connect.Success":
trace("NetStream.Connect.Success");
break;
case "NetStream.Play.StreamNotFound":
trace("Stream not found At NetStream: " + this._source);
break;
}
}
private function ioErrorHandler(event:IOErrorEvent):void{
trace("ioErrorHandler:" + event);
}
private function securityErrorHandler(event:SecurityErrorEvent):void{
trace("securityErrorHandler: " + event);
}
private function asyncErrorHandler(event:AsyncErrorEvent):void{
trace("asyncErrorHandler:" + event);
}
private function metaDataHandler(info:Object):void{ //当获得媒体数据时,开始监听enterFrame事件,该事件是不断发生的,在该事件的handler中更新进度条
trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
this.totalTime = info.duration;
slider.maximum = this.totalTime;
this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
this.volumnSlider.setThumbValueAt(0, this.ns.soundTransform.volume * 10);
this.removeChild(this.tipHBox);
}
private function enterFrameHandler(event:Event):void{ //在该事件中不断更新进度条的位置
this.timpTip.text = this.formatTime(this.ns.time) + "/" + this.formatTime(this.totalTime);
slider.setThumbValueAt(0, this.ns.time);
}
private function cuePointHandler(info:Object):void{
trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
}
public function play():void{
if(this.initIndex == 1){
this.init();
}
else{
try{
this.ns.close();
this.ns.play(this.fileName);
}
catch(error:Error){
trace(error.message);
}
}
this.playPauseBtn.label = "暂停";
}
private function videoClickHandler(event:MouseEvent):void{
this.playPause();
}
private function playPause():void{
this.togglePlayPauseButtonLabel();
}
private function togglePlayPauseButtonLabel():void{
if(this.playPauseBtn.label == "播放"){
this.playPauseBtn.label = "暂停";
this.playPauseBtn.setStyle("icon",this.pauseImage);
this.ns.resume();
}
else{
this.playPauseBtn.label = "播放";
this.playPauseBtn.setStyle("icon",this.playImage);
this.ns.pause();
}
}
private function stop():void{
this. ns.seek(0);
this.ns.pause();
this.slider.setThumbValueAt(0,0);
this.playPauseBtn.label = "播放";
this.playPauseBtn.setStyle("icon",this.playImage);
}
//秒转成“分:秒”格式
private function formatTime(sec:Number):String{
var minutes:int = Math.floor(sec/60);
var seconds:int = Math.floor(sec-minutes*60);
var secondsString:String = seconds.toString();
if(seconds < 10){
secondsString = "0" + secondsString;
}
return minutes + ":" + secondsString;
}
private function thumbDragHandler():void{ //拖拽进度条时,删除对enterFrame事件的监听,以便使此时的进度条与播放头脱离
if(!this.ns) return;
this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function thumbReleaseHandler():void{ //拖拽释放后,根据进度条该点的值让视频的播放头跳到该时间点
if(!this.ns) return;
this.ns.seek(slider.value);
}
private function volumnChangeHandler():void{ //视频音量控制
if(!this.ns) return;
var volumn:SoundTransform = new SoundTransform();
volumn.volume = this.volumnSlider.value / 10;
this.ns.soundTransform = volumn;
}
]]>
</mx:Script>
<mx:HBox id="tipHBox" width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
<mx:Label text="Downloading..." color="#ffffff"/>
</mx:HBox>
<mx:HBox id="controlBar" y="{this.height - controlBar.height}" width="100%" backgroundColor="#CCCCCC" verticalAlign="middle"
horizontalGap="2" horizontalScrollPolicy="off" verticalScrollPolicy="off" paddingLeft="5" paddingRight="2">
<mx:LinkButton id="playPauseBtn" click="playPause()" width="16" height="16"/>
<mx:LinkButton id="stopBtn" label="停止" click="stop()" icon="{stopImage}" width="16" height="16"/>
<mx:HSlider id="slider" width="170" minimum="0" snapInterval="1"
showTrackHighlight="true" thumbDrag="thumbDragHandler()" thumbRelease="thumbReleaseHandler()"/>
<mx:Label id="timpTip" width="92" textAlign="center"/>
<mx:Image source="@Embed(source='assets/volumn.png')" width="16" height="16"/>
<mx:HSlider id="volumnSlider" width="75" minimum="0" maximum="20" snapInterval="1" change="volumnChangeHandler()" liveDragging="true"/>
</mx:HBox>
</mx:Canvas>
VideoPlayer.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" creationComplete="init()">
<mx:Script>
<![CDATA[
private function init():void{
player.source = "http://web.qqvideo.tc.qq.com/3/5KjbHbPKnDF.flv";
}
]]>
</mx:Script>
<mx:VBox width="100%">
<local:Player id="player" autoPlay="true"/>
</mx:VBox>
</mx:Application>
由于用的是网络上的视频,加载速度可能有点慢~