使用提示点和元数据

Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本

使用 NetStream 回调方法可在视频播放时捕获并处理提示点和元数据事件。

使用提示点

下表描述了可在 Flash Player 和 AIR 中用来捕获 F4V 和 FLV 提示点的回调方法。

运行时

F4V

FLV

Flash Player 9/ AIR1.0

 

OnCuePoint

   

OnMetaData

Flash Player 10

 

OnCuePoint

 

OnMetaData

OnMetaData

 

OnXMPData

OnXMPData

下面的示例使用简单的 for..in 循环来遍历 onCuePoint() 函数收到的 infoObject 参数中的每一个属性。它在收到提示点数据时,调用 trace() 函数来显示消息:

var nc:NetConnection = new NetConnection(); 
nc.connect(null); 
 
var ns:NetStream = new NetStream(nc); 
ns.client = this; 
ns.play("video.flv"); 
 
var vid:Video = new Video(); 
vid.attachNetStream(ns); 
addChild(vid); 
 
function onCuePoint(infoObject:Object):void 
{ 
    var key:String; 
    for (key in infoObject) 
    { 
        trace(key + ": " + infoObject[key]); 
    } 
}

显示以下输出:

parameters:  
name: point1 
time: 0.418 
type: navigation

此代码使用多种技术之一来设置运行回调方法的对象。您可以使用其他技术;有关详细信息,请参阅编写元数据和提示点的回调方法

使用视频元数据

可以使用 OnMetaData()OnXMPData() 函数来访问视频文件中的元数据信息,包括提示点。

使用 OnMetaData()

元数据包含有关视频文件的信息,如持续时间、宽度、高度和帧速率。添加到视频文件中的元数据信息取决于您用来编码视频文件的软件。

var nc:NetConnection = new NetConnection(); 
nc.connect(null); 
 
var ns:NetStream = new NetStream(nc); 
ns.client = this; 
ns.play("video.flv"); 
 
var vid:Video = new Video(); 
vid.attachNetStream(ns); 
addChild(vid); 
 
function onMetaData(infoObject:Object):void 
{ 
    var key:String; 
    for (key in infoObject) 
    { 
        trace(key + ": " + infoObject[key]); 
    } 
}

上面的代码生成如下输出:

width: 320 
audiodelay: 0.038 
canSeekToEnd: true 
height: 213 
cuePoints: ,, 
audiodatarate: 96 
duration: 16.334 
videodatarate: 400 
framerate: 15 
videocodecid: 4 
audiocodecid: 2
如果您的视频没有音频,则与音频相关的元数据信息(如 audiodatarate)将返回 undefined,因为在编码期间没有将音频信息添加到元数据中。

在上面的代码中,未显示提示点信息。为了显示提示点元数据,可以使用以下函数,该函数会以递归方式显示 Object 中的项目:

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

使用上面的代码片断在 onMetaData() 方法中跟踪 infoObject 参数将产生以下输出:

width: 320 
audiodatarate: 96 
audiocodecid: 2 
videocodecid: 4 
videodatarate: 400 
canSeekToEnd: true 
duration: 16.334 
audiodelay: 0.038 
height: 213 
framerate: 15 
cuePoints: [Object] 
    0: [Object] 
        parameters: [Object] 
            lights: beginning 
        name: point1 
        time: 0.418 
        type: navigation 
    1: [Object] 
        parameters: [Object] 
            lights: middle 
        name: point2 
        time: 7.748 
        type: navigation 
    2: [Object] 
        parameters: [Object] 
            lights: end 
        name: point3 
        time: 16.02 
        type: navigation

下面的示例显示 MP4 视频的元数据。它假设存在一个名为 metaDataOut 的 TextArea 对象,它将把元数据写入其中。

package 
{ 
    import flash.net.NetConnection; 
    import flash.net.NetStream; 
    import flash.events.NetStatusEvent; 
    import flash.media.Video; 
    import flash.display.StageDisplayState; 
    import flash.display.Loader; 
    import flash.display.Sprite; 
    import flash.events.MouseEvent; 
     
    public class onMetaDataExample extends Sprite 
    {     
        var video:Video = new Video(); 
         
        public function onMetaDataExample():void 
        { 
            var videoConnection:NetConnection = new NetConnection(); 
            videoConnection.connect(null); 
             
            var videoStream:NetStream = new NetStream(videoConnection); 
            videoStream.client = this; 
             
            addChild(video); 
            video.x = 185; 
            video.y = 5; 
                     
            video.attachNetStream(videoStream); 
             
            videoStream.play("video.mp4"); 
                         
            videoStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
        } 
                     
        public function onMetaData(infoObject:Object):void 
        { 
            for(var propName:String in infoObject) 
            { 
                metaDataOut.appendText(propName + "=" + infoObject[propName] + "\n"); 
            } 
        } 
         
        private function netStatusHandler(event:NetStatusEvent):void 
        { 
            if(event.info.code == "NetStream.Play.Stop") 
                stage.displayState = StageDisplayState.NORMAL; 
        } 
    } 
}

对于此视频,onMetaData() 函数将生成以下输出:

moovposition=731965 
height=352 
avclevel=21 
videocodecid=avc1 
duration=2.36 
width=704 
videoframerate=25 
avcprofile=88 
trackinfo=[object Object]

使用信息对象

下表显示了在 onMetaData() 回调函数接收的 Object 中传递给 onMetaData() 回调函数的可能的视频元数据值。

参数

说明

aacaot

AAC 音频对象类型;支持 0、1 或 2。

avclevel

AVC IDC 级别号,如 10、11、20、21 等等。

avcprofile

AVC 配置文件号,如 55、77、100 等等。

audiocodecid

指示所用音频编解码器(编码/解码技术)的字符串 -- 例如“Mp3”或“mp4a”

audiodatarate

一个数字,指示音频的编码速率,以每秒千字节为单位。

audiodelay

一个数字,指示原始 FLV 文件的“time 0”在 FLV 文件中保持多长时间。为了正确同步音频,视频内容需要有少量的延迟。

canSeekToEnd

一个布尔值,如果 FLV 文件是用最后一帧(它允许定位到渐进式下载视频文件的末尾)上的关键帧编码的,则该值为 true。如果 FLV 文件不是用最后一帧上的关键帧编码的,则该值为 false

cuePoints

嵌入在 FLV 文件中的提示点对象组成的数组,每个提示点对应一个对象。如果 FLV 文件不包含任何提示点,则值是未定义的。每个对象都具有以下属性:

  • type:一个字符串,它将提示点的类型指定为“navigation”或“event”。

  • name:一个字符串,表示提示点的名称。

  • time:一个数字,表示以秒为单位的提示点的时间,精确到 3 位小数(毫秒)。

  • parameters:一个可选对象,包含用户在创建提示点时指定的名称-值对。

duration

一个数字,以秒为单位指定视频文件的持续时间。

framerate

一个数字,表示 FLV 文件的帧速率。

height

一个数字,以像素为单位表示 FLV 文件的高度。

seekpoints

一个数组,其中将可用的关键帧作为时间戳列出,单位为毫秒。可选。

tags

一个键-值对数组,这些键/值对表示“ilst”原子中的信息,相当于 MP4 文件中的 ID3 标签。iTunes 使用这些标签。可用于显示插图(如果有插图)。

trackinfo

一个对象,提供有关 MP4 文件中所有轨道的信息(包括其采样描述 ID)。

videocodecid

一个字符串,表示用于编码视频的编解码器版本。- 例如,“avc1”或“VP6F”

videodatarate

一个数字,表示 FLV 文件的视频数据速率。

videoframerate

MP4 视频的帧速率。

width

一个数字,以像素为单位表示 FLV 文件的宽度。

下表显示 videocodecid 参数的可能值:

videocodecid

编解码器名称

2

Sorenson H.263

3

屏幕视频(仅限 SWF 版本 7 和更高版本)

4

VP6(仅限 SWF 版本 8 和更高版本)

5

带有 Alpha 通道的 VP6 视频(仅限 SWF 版本 8 和更高版本)

下表显示 audiocodecid 参数的可能值:

audiocodecid

编解码器名称

0

未压缩

1

ADPCM

2

Mp3

4

Nellymoser,16 kHz 单声

5

Nellymoser,8kHz 单声

6

Nellymoser

10

AAC

11

Speex

使用 onXMPData()

onXMPData() 回调函数接收 Adobe F4V 或 FLV 视频文件中嵌入的 Adobe 可扩展元数据平台 (XMP) 专用信息。XMP 元数据包括提示点以及其他视频元数据。Flash Player 10 和 Adobe AIR 1.5 中引入了 XMP 元数据支持,并且后续版本都支持这种元数据。

下面的示例处理 XMP 元数据中的提示点数据:

package 
{ 
    import flash.display.*; 
    import flash.net.*; 
    import flash.events.NetStatusEvent; 
    import flash.media.Video; 
     
    public class onXMPDataExample extends Sprite 
    { 
        public function onXMPDataExample():void 
        { 
            var videoConnection:NetConnection = new NetConnection(); 
            videoConnection.connect(null); 
             
            var videoStream:NetStream = new NetStream(videoConnection); 
            videoStream.client = this; 
            var video:Video = new Video(); 
             
            addChild(video); 
             
            video.attachNetStream(videoStream); 
             
            videoStream.play("video.f4v"); 
        } 
         
        public function onMetaData(info:Object):void { 
            trace("onMetaData fired"); 
        } 
         
        public function onXMPData(infoObject:Object):void 
        { 
            trace("onXMPData Fired\n"); 
             //trace("raw XMP =\n"); 
             //trace(infoObject.data); 
            var cuePoints:Array = new Array(); 
            var cuePoint:Object; 
            var strFrameRate:String; 
            var nTracksFrameRate:Number; 
            var strTracks:String = ""; 
            var onXMPXML = new XML(infoObject.data); 
            // Set up namespaces to make referencing easier 
            var xmpDM:Namespace = new Namespace("http://ns.adobe.com/xmp/1.0/DynamicMedia/"); 
            var rdf:Namespace = new Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); 
            for each (var it:XML in onXMPXML..xmpDM::Tracks) 
            { 
                 var strTrackName:String = it.rdf::Bag.rdf::li.rdf::Description.@xmpDM::trackName; 
                 var strFrameRateXML:String = it.rdf::Bag.rdf::li.rdf::Description.@xmpDM::frameRate; 
                 strFrameRate = strFrameRateXML.substr(1,strFrameRateXML.length); 
                 
                 nTracksFrameRate = Number(strFrameRate);  
                 
                 strTracks += it; 
            } 
            var onXMPTracksXML:XML = new XML(strTracks); 
            var strCuepoints:String = ""; 
            for each (var item:XML in onXMPTracksXML..xmpDM::markers) 
            { 
                strCuepoints += item; 
            } 
            trace(strCuepoints); 
        } 
    } 
}

对于名为 startrekintro.f4v 的短视频文件,此示例生成以下跟踪行。这些行显示了 XMP 元数据中用于导航的提示点数据以及事件提示点:

onMetaData fired 
onXMPData Fired 
 
<xmpDM:markers xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/" xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:x="adobe:ns:meta/"> 
  <rdf:Seq> 
    <rdf:li> 
      <rdf:Description xmpDM:startTime="7695905817600" xmpDM:name="Title1" xmpDM:type="FLVCuePoint" xmpDM:cuePointType="Navigation"> 
        <xmpDM:cuePointParams> 
          <rdf:Seq> 
            <rdf:li xmpDM:key="Title" xmpDM:value="Star Trek"/> 
            <rdf:li xmpDM:key="Color" xmpDM:value="Blue"/> 
          </rdf:Seq> 
        </xmpDM:cuePointParams> 
      </rdf:Description> 
    </rdf:li> 
    <rdf:li> 
      <rdf:Description xmpDM:startTime="10289459980800" xmpDM:name="Title2" xmpDM:type="FLVCuePoint" xmpDM:cuePointType="Event"> 
        <xmpDM:cuePointParams> 
          <rdf:Seq> 
            <rdf:li xmpDM:key="William Shatner" xmpDM:value="First Star"/> 
            <rdf:li xmpDM:key="Color" xmpDM:value="Light Blue"/> 
          </rdf:Seq> 
        </xmpDM:cuePointParams> 
      </rdf:Description> 
    </rdf:li> 
  </rdf:Seq> 
</xmpDM:markers> 
onMetaData fired
注: 在 XMP 数据中,时间是作为 DVA 刻度存储的,而不是秒。若要计算提示点时间,请将启动时间除以帧速率。例如,启动时间 7695905817600 除以帧速率 254016000000 等于 30:30。

若要查看全部原始 XMP 元数据,包括帧速率,请删除位于 onXMPData() 函数开头的第二和第三条 trace() 语句之前的注释标识符 (//)。

使用图像元数据

onImageData 事件通过 AMF0 数据通道将图像数据作为字节数组发送。该数据可以是 JPEG、PNG 或 GIF 格式。可定义 onImageData() 回调方法来处理此信息,这与定义 onCuePointonMetaData 的回调方法的方式相同。下面的示例使用 onImageData() 回调方法访问并显示图像数据。

public function onImageData(imageData:Object):void 
{ 
    // display track number 
    trace(imageData.trackid); 
    var loader:Loader = new Loader(); 
    //imageData.data is a ByteArray object 
    loader.loadBytes(imageData.data); 
    addChild(loader); 
} 

使用文本元数据

onTextData 事件通过 AMF0 数据通道发送文本数据。文本数据为 UTF-8 格式,并且包含有关基于 3GP 计时文本规范的格式化的更多信息。此规范定义了标准化的字幕格式。可定义 onTextData() 回调方法来处理此信息,这与定义 onCuePointonMetaData 的回调方法的方式相同。在下面的示例中,onTextData() 方法显示曲目 ID 号和对应的曲目文本。

public function onTextData(textData:Object):void 
{ 
    // display the track number 
    trace(textData.trackid); 
    // displays the text, which can be a null string, indicating old text 
    // that should be erased 
    trace(textData.text); 
}