首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

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();

        }

       

        /*************************************

         * 加载视频文件

         * */

        private function LoadVideo():void

        {

            // 建立连接

            var nc:NetConnection = new NetConnection();

            nc.connect(null);

           

            // 创建回调函数的对象

            var customClient:Object = new Object();

            customClient.onMetaData = metaDataHandler;

           

            // 创建视频流

            var ns:NetStream = new NetStream(nc);

            ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);

            // 回调函数的对象customClient

            // 赋值给NetStream对象的属性client

            ns.client = customClient;

            // 指定视频名

            ns.play("Bear.flv");

           

            // 视频传输到本地

            var vid:Video = new Video();

            vid.attachNetStream(ns);

           

            // 添加到舞台上

            addChild(vid);

        }

       

        /*************************************

         * 捕获连接异常

         * */

        function asyncErrorHandler(event:AsyncErrorEvent):void

        {

            // 错误处理

            trace(event.text);

        }

       

        /*************************************

         * onMetaData回调函数的事件

         * */

        function metaDataHandler(metadata:Object):void

        {

            // 输出持续时间

            trace("持续时间:" + metadata.duration);

            // 输出帧速

            trace("帧速:" + metadata.framerate);

            // 输出视频文件的高度

            trace("高度:" + metadata.height);

            // 输出视频文件的宽度

            trace("宽度:" + metadata.width);

        }

    }

   

}

编译代码,运行效果如图21.6所示。

图21.6  获取视频文件的基本信息

21.5  提示点

在视频文件中,可以嵌入提示点。提示点可以嵌入到视频文件的任意时间点上,等到视频播放到该位置时,会调用回调函数onCuePoint。提示点有很多用途,比如记录日志、显示提示信息等。提示点大体分为三种:导航提示点、事件提示点和ActionScript提示点。

— 将导航提示点嵌入到视频中,起到信息提示的作用。

— 将事件提示点嵌入到视频中,视频播放到指定提示点的位置时,触发响应的事件。

—  ActionScript提示点属于外部提示点,通过外部的代码触发。

下面的示例使用onCuePoint回调函数,输出每个提示点的信息。代码如下所示:

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();

        }

       

        /*************************************

         * 加载视频文件

         * */

        private function LoadVideo():void

        {

            // 建立连接

            var nc:NetConnection = new NetConnection();

            nc.connect(null);

           

            // 创建回调函数的对象

            var customClient:Object = new Object();

            // 处理回调函数

            customClient.onMetaData = metaDataHandler;

            customClient.onCuePoint = cuePointHandler;

           

            // 创建视频流

            var ns:NetStream = new NetStream(nc);

            ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);

            // 回调函数的对象customClient

            // 赋值给NetStream对象的属性client

            ns.client = customClient;

            // 指定视频名

            ns.play("Bear.flv");

           

            // 视频传输到本地

            var vid:Video = new Video();

            vid.attachNetStream(ns);

           

            // 添加到舞台上

            addChild(vid);

        }

       

        /*************************************

         * 捕获连接异常

         * */

        function asyncErrorHandler(event:AsyncErrorEvent):void

        {

            // 错误处理

        }

       

        /*************************************

         * onMetaData回调函数的事件

         * */

        function metaDataHandler(metadata:Object):void

        {

            // 处理onMetaData回调函数

        }

       

        /*************************************

         * onCuePoint回调函数的事件

         * */

        function cuePointHandler(cuePoint:Object):void

        {

            // 输出信息

            traceObject(cuePoint);

        }

       

        /*************************************

         * 输出回调函数的值和参数

         * */

        function traceObject(obj:Object, indent:uint = 0):void

        {

            var indentString:String = "";

            var i:uint;

            var prop:String;

            var val:*;

            for (i = 0; i < indent; i++)

            {

                indentString += "\t";

            }

            for (prop in obj)

            {

                val = obj[prop];

                if (typeof(val) == "object")

                {

                    trace(indentString + " " + prop + ": [Object]");

                    traceObject(val, indent + 1);

                }

                else

                {

                    trace(indentString + " " + prop + ": " + val);

                }

            }

        }

    }

   

}

编译代码,运行效果如图21.7所示。

图21.7  输出提示点信息

21.6  捕获摄像头的输入

除了外部的.flv视频文件之外,摄像头也是Flash Player视频的主要来源之一。在ActionScript 3.0中,也相应的提供了一些关于摄像头的类,使用这些类,可以很容易捕获来自摄像头的视频信息。

 21.6.1  Camera类

Camera类是跟摄像头有关的很重要的类。使用Camera类可以捕获连接到计算机上的摄像头,并获得相应的信息。Camera类的常用的属性如表21.4所示,常用的方法如表21.5所示,常用的事件如表21.6所示。

表21.4  Camera类常用的属性

   

   

activityLevel

指定摄像头检测的运动量

bandwidth

指定当前输出视频输入信号可以使用的最大带宽,以字节为单位

currentFPS

摄像头捕获数据的速率,以每秒帧数为单位

fps

希望摄像头在捕获数据时达到的最大速率,以每秒帧数为单位

height

当前捕获高度,以像素为单位

index

从零开始的整数,指定由names属性返回的数组中所反映的摄像头的索引

keyFrameInterval

指定进行完整传输而不由视频压缩算法进行插值处理的视频帧(称为关键帧)

loopback

指定在本地查看摄像头所捕获图像时是进行压缩和解压缩 true 以便使用Flash Media Server进行实时传输,还是不进行压缩 false

续表 

   

   

motionLevel

指定调用activity事件所需的运动量

motionTimeout

摄像头停止检测运动的时间与调用activity事件的时间之间相差的毫秒数

muted

指定用户在Flash Player隐私面板中是拒绝了对摄像头的访问 true 还是允许访问 false

name

指定由摄像头硬件返回的当前摄像头的名称

names

检索一个反映所有可用摄像头的名称的字符串数组,而不显示Flash Player隐私面板

quality

指定所需的画面质量级别,该级别由应用于每一视频帧的压缩量来确定

width

当前捕获宽度,以像素为单位

表21.5  Camera类常用的方法

   

   

getCamera

返回对用于捕获视频的Camera对象的引用

setKeyFrameInterval

指定进行完整传输而不由视频压缩算法进行插值处理的视频帧(称为关键帧)

setLoopback

指定在本地查看摄像头时是否使用压缩视频流

setMode

将摄像头的捕获模式设置为最符合指定要求的本机模式

setMotionLevel

指定调度activity事件所需的运动量

setQuality

设置每秒的最大带宽或当前输出视频输入信号所需的画面质量

表21.6  Camera类常用的事件

   

   

activity

在摄像头开始或结束会话时调度

status

在摄像头报告其状态时调度

 21.6.2  验证摄像头

在捕获摄像头的内容之前,通常需要检测用户的计算机上是否安装了摄像头。验证摄像头的方法是利用Camera的实例对象,判断这个实例是否为空,为空则没有检测到摄像头,反之,用户就已经安装了摄像头。

下面的示例作用是检测用户的计算机上是否已经安装了摄像头,示例如下所示:

package 

{

    import flash.display.Sprite;

    import flash.media.Camera;

    public class CameraExample extends Sprite

    {

        /*************************************

         * 构造函数

         * */

        public function CameraExample()

        {

            // 创建Camera对象

            var camera:Camera = Camera.getCamera();

           

            // 检测摄像头

            if (camera != null)

            {

                trace("机器上已经安装了摄像头.");

            }

            else

            {

                trace("机器上没有安装摄像头.");

            }

        }

    }

}

编译代码并运行,输出的结果如图21.8所示。

图21.8  验证摄像头

 21.6.3  输出摄像头的内容

Flash Player对摄像头的输出是有一定的限制的,需要本地计算机用户进行有效的设置,才能连接摄像头。在Flash Player播放器中,单击右键,选择【设置】命令,就会弹出一个对话框,如图21.9所示。

图21.9  摄像头的设置

默认摄像头的设置是拒绝访问的,如果要使用摄像头,必须勾上【允许】选项。摄像头的捕获要通过静态方法getCamera()来实例化一个Camera对象,然后通过Video对象显示出来。

下面的示例使用Camera对象捕获摄像头的内容,并实时监视。代码如下所示:

package 

{

    import flash.display.Sprite;

    import flash.display.StageAlign;

    import flash.display.StageScaleMode;

    import flash.events.*;

    import flash.media.Camera;

    import flash.media.Video;

    public class CameraExample extends Sprite

    {

        private var video:Video;

        /*************************************

         * 构造函数

         * */

        public function CameraExample()

        {

            // 设置舞台属性

        stage.scaleMode = StageScaleMode.NO_SCALE;

        stage.align = StageAlign.TOP_LEFT;

           

            // 创建Camera对象

            var camera:Camera = Camera.getCamera();

           

            // 检测摄像头

            if (camera != null)

            {

            camera.addEventListener(ActivityEvent.ACTIVITY, activityHandler);

            // 创建Video对象

            video = new Video(camera.width * 2, camera.height * 2);

            // 显示摄像头的内容

            video.attachCamera(camera);

            addChild(video);

            }

            else

            {

                trace("机器上没有安装摄像头.");

            }

        }

       

        /*************************************

         * 事件处理

         * */

        private function activityHandler(event:ActivityEvent):void

        {

            trace("activityHandler: " + event);

        }

    }

   

}

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论
    图书导读