Flash Player作为流媒体的表现形式之一,视频编码是其最大的特色。.flv文件是Flash Player基本的视频文件格式,可以在Flash Player运行时加载,不被编译到虚拟机中,这就大大减小了Flash Player文件的体积,增加了Flash Player视频文件在网络上传输的速度。
21.1 视频类
在ActionScript 3.0中,提供了一个Video类,用来处理视频。使用Video类可以控制基本的视频文件功能比如编码、滤镜等。
通过使用Video类的属性和方法,可以在程序中直接显示实时的视频流,而不用把视频文件编译到Flash Player视频文件中。其常用的属性如表21.1所示,常用的方法如表21.2所示。
表21.1 Video类常用的属性
属 性 | 说 明 |
deblocking | 指示作为后处理的一部分应用于已解码视频的滤镜的类型 |
smoothing | 指定在缩放视频时是否应进行平滑处理(插补数据) |
videoHeight | 以像素为单位指定视频流的高度 |
videoWidth | 以像素为单位指定视频流的宽度 |
表21.2 Video类常用的方法
方 法 | 说 明 |
attachCamera | 指定在应用程序窗口中Video对象的边界内显示来自摄像头的视频流 |
attachNetStream | 指定在应用程序窗口中Video对象的边界内显示视频流 |
clear | 清除该Video对象中当前显示的图像 |
21.2 加载视频文件
.flv格式是Flash Player网络传输的视频文件的基本格式。可以通过一些工具把其他的视频文件格式转换为.flv格式,比如Flash CS3自带的工具Flash Video Encode。
加载一个视频文件,通常可以分为三步实现。其步骤如下所示。
创建一个NetConnection对象。NetConnection类作用是连接到远程服务器中,调用命令,播放视频。其代码如下所示:
// 建立连接
var nc:NetConnection = new NetConnection();
nc.connect(null);
创建一个NetStream对象。NetStream类作用是通过NetConnection对象提供的连接,打开Flash Player与服务器或Flash Player与本地文件系统之间的单向流连接。其代码如下所示:
// 创建视频流
var ns:NetStream = new NetStream(nc);
// 开始播放
ns.play("lake.flv");
创建一个Video对象。调用Video类的attachNetStream事件,可以直接显示视频流。其代码如下所示:
// 视频传输到本地
// 创建Video对象
var vid:Video = new Video();
vid.attachNetStream(ns);
通过这三个步骤的操作,视频文件就被加载并播放。
下面示例说明如何播放一个本地的视频文件lake.flv。其完整的代码如下所示:
package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.events.AsyncErrorEvent;
public class VideoExample extends Sprite
{
/*************************************
* 构造函数
* */
public function VideoExample()
{
// 建立连接
var nc:NetConnection = new NetConnection();
nc.connect(null);
// 创建视频流
var ns:NetStream = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
// 指定视频名
ns.play("lake.flv");
// 视频传输到本地
var vid:Video = new Video();
vid.attachNetStream(ns);
// 添加到舞台上
addChild(vid);
}
/*************************************
* 捕获连接异常
* */
function asyncErrorHandler(event:AsyncErrorEvent):void
{
// 错误处理
}
}
}
编译代码,运行效果如图21.1所示。
图21.1 加载视频文件
21.3 视频文件的控制
视频文件的控制是指在视频在播放过程中,用户通过一些交互式的按钮或者其他组件触发事件,精确的控制视频的播放,包括停止播放、暂停播放、视频回放等。
21.3.1 从指定的位置播放
通过NetStream对象的play()方法可以回放视频文件,但是play()方法是从视频文件的开始播放的。有时候,我们需要从指定的位置或者时间开始播放,那么什么方法可以满足这个要求呢?在NetStream类中提供了seek()方法,可以搜索指定位置开始播放。其参数有一个,表示从流的开始位置算起的偏移量,以秒为单位。其语法格式如下所示:
seek(offset:Number):void
比如下面的示例作用是从第5秒开始播放一个视频文件,代码如下所示:
package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
public class VideoExample extends Sprite
{
/*************************************
* 构造函数
* */
public function VideoExample()
{
// 建立连接
var nc:NetConnection = new NetConnection();
nc.connect(null);
// 创建视频流
var ns:NetStream = new NetStream(nc);
// 指定视频名
ns.play("lake.flv");
// 从第5秒开始播放
ns.seek(5);
// 视频传输到本地
var vid:Video = new Video();
vid.attachNetStream(ns);
// 添加到舞台上
addChild(vid);
}
}
}
编译代码,运行的效果如图21.2所示。
图21.2 从指定的位置播放
21.3.2 停止
需要停止一个正在播放的视频的时候,要使用NetStream对象的close()方法。close()方法同时也停止了从服务器中下载视频。其语法格式如下所示:
close():void
如果要继续播放和从服务器中下载视频,需要再次调用NetStream对象的play()方法。下面的示例使用close()方法停止正在播放的视频,代码如下所示:
package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.events.MouseEvent;
import flash.events.AsyncErrorEvent;
import fl.controls.Button;
public class VideoExample extends Sprite
{
var ns:NetStream;
var nc:NetConnection;
var vid:Video;
/*************************************
* 构造函数
* */
public function VideoExample()
{
LoadVideo();
LoadStopButton();
}
/*************************************
* 加载视频文件
* */
private function LoadVideo():void
{
// 建立连接
nc = new NetConnection();
nc.connect(null);
// 创建视频流
ns = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
// 指定视频名
ns.play("lake.flv");
// 视频传输到本地
vid = new Video();
vid.attachNetStream(ns);
// 添加到舞台上
addChild(vid);
}
/*************************************
* 创建一个停止的按钮
* */
private function LoadStopButton():void
{
// 增加停止按钮
var stop_btn:Button = new Button();
stop_btn.label = "停止";
stop_btn.move(10, 250);
stop_btn.addEventListener(MouseEvent.CLICK, StopBtn_Click);
addChild(stop_btn);
}
/*************************************
* 创建一个停止按钮的单击事件
* */
private function StopBtn_Click(e:MouseEvent):void
{
// 停止播放
ns.close();
}
/*************************************
* 捕获连接异常
* */
function asyncErrorHandler(event:AsyncErrorEvent):void
{
// 错误处理
}
}
}
编译代码,运行效果如图21.3所示。
图21.3 停止正在播放的视频
21.3.3 暂停与回放
暂停正在播放的视频,需要使用NetStream对象的pause()方法。如果暂停之后,需要从暂停的地方播放,就需要用到resume()方法了。resume()方法作用是恢复播放暂停的视频流。其语法格式如下所示:
resume():void
下面的示例使用pause()方法和resume()方法控制正在播放的视频,示例代码如下所示:
package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.events.MouseEvent;
import flash.events.AsyncErrorEvent;
import fl.controls.Button;
public class VideoExample extends Sprite
{
var ns:NetStream;
var nc:NetConnection;
var vid:Video;
var pause_btn:Button;
/*************************************
* 构造函数
* */
public function VideoExample()
{
LoadVideo();
LoadPauseButton();
}
/*************************************
* 加载视频文件
* */
private function LoadVideo():void
{
// 建立连接
nc = new NetConnection();
nc.connect(null);
// 创建视频流
ns = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
// 指定视频名
ns.play("lake.flv");
// 视频传输到本地
vid = new Video();
vid.attachNetStream(ns);
// 添加到舞台上
addChild(vid);
}
/*************************************
* 创建一个暂停/回放按钮
* */
private function LoadPauseButton():void
{
// 增加暂停/回放按钮
pause_btn = new Button();
pause_btn.label = "暂停";
pause_btn.move(10, 250);
pause_btn.addEventListener(MouseEvent.CLICK, PauseBtn_Click);
addChild(pause_btn);
}
/*************************************
* 创建一个暂停按钮的单击事件
* */
private function PauseBtn_Click(e:MouseEvent):void
{
if(e.target.label == "暂停")
{
// 停止播放
ns.pause();
pause_btn.label = "回放";
}
else
{
// 回放
ns.resume();
pause_btn.label = "暂停";
}
}
/*************************************
* 捕获连接异常
* */
function asyncErrorHandler(event:AsyncErrorEvent):void
{
// 错误处理
}
}
}
编译代码,运行效果如图21.4所示。
图21.4 暂停和回放视频
21.3.4 控制视频的音量
控制视频中的声音,需要使用NetStream对象中的soundTransform属性,soundTransform属性返回的是一个SoundTransform对象,SoundTransform对象中的volume属性可以控制声音。
下面的示例使用Slider控件控制视频中声音的大小,代码如下所示:
package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.media.SoundTransform;
import fl.events.SliderEvent;
import flash.events.AsyncErrorEvent;
import fl.controls.Slider;
public class VideoSoundExample extends Sprite
{
var ns:NetStream;
var nc:NetConnection;
var vid:Video;
var sound_slider:Slider;
var sound:SoundTransform;
/*************************************
* 构造函数
* */
public function VideoSoundExample()
{
LoadVideo();
LoadSlider();
}
/*************************************
* 加载视频文件
* */
private function LoadVideo():void
{
// 建立连接
nc = new NetConnection();
nc.connect(null);
// 创建视频流
ns = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
// 创建声音
sound = ns.soundTransform;
// 指定视频名
ns.play("lake.flv");
// 视频传输到本地
vid = new Video();
vid.attachNetStream(ns);
// 添加到舞台上
addChild(vid);
}
/*************************************
* 创建Slider控件
* */
private function LoadSlider():void
{
sound_slider = new Slider();
sound_slider.move(10, 250);
// 声音默认值
sound_slider.value = sound.volume;
sound_slider.addEventListener(SliderEvent.CHANGE, volumeChange
Handler);
addChild(sound_slider);
}
/*************************************
* 控制声音
* */
private function volumeChangeHandler(event:SliderEvent):void
{
// 获取Slider控件的值
sound.volume = event.value;
ns.soundTransform = sound;
}
/*************************************
* 捕获连接异常
* */
function asyncErrorHandler(event:AsyncErrorEvent):void
{
// 错误处理
}
}
}
编译代码,运行效果如图21.5所示。
图21.5 视频中的音量控制
21.4 获取视频文件的信息
可以使用onMetaData回调处理函数获取视频文件的信息。视频文件的信息包括持续时间、宽度、高度及帧速等。
21.4.1 onMetaData回调方法
onMetaData是一个回调函数,使用这个回调函数,可以获取元数据的信息,也就是视频文件的信息,包括持续时间、高度、宽度、帧速、视频编码器及音频编码器等。
回调方法有很多参数,通过不同的参数,可以获取元数据不同的信息。回调方法的常用的参数如表21.3所示。
表21.3 onMetaData回调函数的常用的参数
参 数 | 说 明 |
audiocodecid | 指示已使用的音频编解码器(编码/ 解码技术) |
audiodatarate | 指示音频的编码速率,以每秒千字节为单位 |
audiodelay | 指示原始FLV文件的“time 0”在FLV文件中保持多长时间。为了正确同步音频,视频内容需要有少量的延迟 |
canSeekToEnd | 如果FLV文件是用最后一帧(它允许定位到渐进式下载影片剪辑的末尾)上的关键帧编码的,则该值为true。如果FLV文件不是用最后一帧上的关键帧编码的,则该值为false |
cuePoints | 嵌入在FLV文件中的提示点对象组成的数组,每个提示点对应一个对象。如果FLV文件不包含任何提示点,则值是未定义的 |
duration | 以秒为单位指定FLV文件的持续时间 |
framerate | 表示FLV文件的帧速率 |
height | 以像素为单位表示FLV文件的高度 |
videocodecid | 表示用于对视频进行编码的编解码器的版本 |
videodatarate | 表示FLV文件的视频数据速率 |
width | 以像素为单位表示FLV文件的宽度 |
onMetaData回调方法的关联对象是赋值给NetStream对象的client()方法的,下面的示例说明onMetaData回调方法如何使用,代码如下所示:
// 创建回调函数的对象
var customClient:Object = new Object();
customClient.onMetaData = metaDataHandler;
// 创建视频流
var ns:NetStream = new NetStream(nc);
// 回调函数的对象customClient
// 赋值给NetStream对象的属性client
ns.client = customClient;
// 指定视频名
ns.play("Bear.flv");
/*************************************
* onMetaData回调函数的事件
* */
function metaDataHandler(metadata:Object):void
{
// 处理数据
}
21.4.2 获取视频文件的基本信息
使用回调函数onMetaData可以获取视频文件的基本信息。下面的示例通过onMetaData回调函数获取视频文件的持续时间、帧速、高度和宽度,代码如下所示:
package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.events.AsyncErrorEvent;
public class CuoPointExample extends Sprite
{
var ns:NetStream;
var nc:NetConnection;
var vid:Video;
public function CuoPointExample()
{
LoadVideo();