Flash的最重要功能之一是web视频播放。 除了高级视频压缩技术和高效播放机制之外,Flash还支持丰富的视觉体验,例如用户互动、社交媒体集成、目标广告等。
为了充分利用相应的内容,网站运营者和内容拥有者希望首先知道用户是如何消费视频的,然后基于实际数据作出明智的决定。 需要回答的问题包括有多少视频已经被观看过或跳过,用户是否对视频进行暂停操作、将内容以全屏模式播放、点击广告或进行其它操作。 了解用户的互动方式对于获得视频收益来说是非常有价值的信息。 因此,视频测量是非常活跃的领域,目前已有多个公司提供解决方案,例如Omniture (归属于Adobe)、omScore、Nielsen和 Google Analytics。
某些视频消费数据总是以Flash的方式播放。 播放时间和搜寻事件等基本信息很容易获得,然而,其中某些信息在不同的视频传送机制中可能不一致。 此外,不同的视频技术-例如Open Source Media Player (OSMF)、Brightcove、JW Player和其它技术-均能够提供自己的API以便获取某种形式的视频消费信息,这使得媒体测量应用程序的开发过程变得复杂化。
Adobe Flash Player 10.3和 Adobe AIR 2.7 能够改善视频消费信息的可得性。 Adobe的目标是在无论实际使用什么类型的视频播放器的情形下均能够针对不同的视频传送机制提供一致的信息。 这将会极大地简化网站运营者、内容拥有者和测量提供者的视频测量过程。 现在,视频消费能够直接源自Adobe Flash Platform 运行时,而无论实际使用的视频播放器是什么类型。
本文为你介绍如何测量Flash视频。 首先,我将介绍Flash支持的三种不同视频传送方式。 我还将介绍新的ActionScript API,它能够支持精确的视频消耗测量。 然后,我将给出关于一个视频消费测量系统的基本概念的描述。 接下来,我将给出关于安全方面的结论。 最后,我将介绍一款与视频播放器无关的测量应用程序范例,它能够与OSMF 和JW 播放器一起使用。
要求
预备知识:
要求了解关于Adobe Flash Platform运行时、ActionScript以及 Adobe Flash Builder或 Adobe Flash Professional的高级知识。
需要下列产品:
Flash Builder
范例文件
视频传送架构
Flash 可以提供三种完全不同的视频传送机制:渐进式下载(progressive download)、流式传输(streaming)和HTTP流式传输(HTTP streaming)。 我将利用少许代码片段简单地说明所有上述三种传送机制。 如果你使用视频播放器应用程序,则这些底层的细节将是不可见的。
渐进式下载
渐进式下载是Flash提供的最简单的、因此也是使用最广泛的视频播放机制。 相应的视频文件存储于 HTTP 服务器,你需要做的所有操作是指定视频的 URL。 Flash将视频下载到浏览器的高速缓存中,然后当收到足够数量的数据时开始播放视频。
下面的范例 ActionScript 代码演示了渐进式视频播放机制:
-
private function playProgressive():void
-
{
-
var nc:NetConnection = new NetConnection();
-
nc.connect(null);
-
var ns:NetStream = new NetStream(nc);
-
ns.play("http://wwww.example.com/video.flv");
-
}
-
该方案的优点是其简单性(不需要特别的媒体流服务器)并且能够自动使用HTTP高速缓存的基础设备。 该方案的不足之处是你无法控制视频下载进程、搜寻功能有限(用户无法搜寻到没有下载的视频)以及浪费带宽(整个视频能够以网络连接的最大处理速度下载,即使视频无法观看)。 因此,渐进式下载仅仅适用于最简单的视频应用程序。 由于视频是通过HTTP传送的,因此需要提供内容保护机制。
YouTube 使用渐进视频下载方式以及特别的服务器侧组件来克服上述局限性。
流
流是指一种更高级的视频播放机制,利用这一机制,Flash Platform 客户端能够从特别的流服务器中获取视频数据,例如 Adobe Flash Media Server。流是使用 Real-Time Messaging Protocol (RTMP*)实现的,RTMP*是Adobe开发的一种开发协议。
适用于流的客户端侧 ActionScript 代码与渐进式下载的代码非常相似:
-
private function playStreaming():void
-
{
-
var nc:NetConnection = new NetConnection();
-
nc.connect("rtmp://example.com/video");
-
var ns:NetStream = new NetStream(nc);
-
ns.play("flv:video");
-
}
RTMP 流的优点是能够通过对缓存和下载的完全控制以获得最佳的性能。 目前,RTMP流已经能够支持快速启动(fast start)、搜寻(seeking)、技巧模式(trick mode)和多速率流(multi-bitrate streaming )等功能。 RTMP流没有浪费带宽,它只下载必需的视频数据。 相应的视频数据不必写入磁盘(浏览器高速缓存器或任何其它位置),而是在收到之后由Flash进行处理。
RTMP具有多种风格:它可以在 HTTP (RTMPT) 或SSL (RTMPS)上建立通道。 Flash Media Server 也可以提供加一种密格式 (RTMPE),目前许多视频网站已经使用这种加密格式。
HTTP流
HTTP 流处理功能是最近引入Flash Player 10.1的。 它将流的高级功能与HTTP高速缓存基础设备的可用性组合在一起。 相应的视频文件存储于一个web服务器。 在当前的实现方案中,复杂部分被推向视频播放器应用程序:视频下载、缓存控制、搜寻以及其它多种功能均由应用程序开发人员利用ActionScript实现。 ActionScript负责将视频消息作为一个ByteArray 提供给Flash以便进行解析、解码和显示。 相应的解析器只能读懂FLV 文件*。如果你希望播放以 MPEG-4 格式编码的视频 ,你必须利用ActionScript解析MPEG-4容器,而这是非常具有挑战性的任务。 因此,作为Flash Media Server的一个组成部分,Adobe可以提供一种HTTP插件,它能够解析 MPEG-4 容器,并且能够方便地用于 HTTP 流处理功能。
下面的代码片段可以提供播放一段FLV电影的范例代码:
-
private var httpStream:URLStream = null;
-
private function playHttpStreaming():void
-
{
-
var nc:NetConnection = new NetConnection();
-
nc.connect(null);
-
var ns:NetStream = new NetStream(nc);
-
ns.play(null);
-
-
var request:URLRequest = new URLRequest("http://wwww.example.com/video.flv");
-
httpStream = new URLStream();
-
httpStream.addEventListener(ProgressEvent.PROGRESS, onData);
-
httpStream.load(request);
-
}
-
-
private function onData(e:ProgressEvent):void
-
{
-
var b:ByteArray = new ByteArray();
-
httpStream.readBytes(b, 0, httpStream.bytesAvailable);
-
ns.appendBytes(b);
-
}
视频播放器的职责是实现搜寻(seeking)、播放列表(playlist)、多速率切换( multi-bitrate switching)及更多其它功能(而这些不是没有价值的功能)。 例如,为了实现搜寻功能,视频播放器需要对视频消息进行缓存、跟踪可搜寻点并且在进行搜寻操作时为Flash提供合适的FLV片段。 充分利用HTTP流提供的所有高级功能的最佳方法是使用 OSMF 视频播放器和 Flash Media Server HTTP 流处理功能插件。
HTTP 流处理功能的优点是能够对缓存进行全应用程序的ActionScript控制并且能够使用 HTTP 高速缓存设备。 技巧模式和多速率流能够方便地在应用程序层实现。 与渐进式播放一样,需要添加内容保护机制。
媒体测量API
Flash Player 10.3和 AIR 2.7 引入一个新的 ActionScript API 以便更好地测量视频消费。 新的API要求系统支持 SWF v12或更高版本。 确保你将你的文件发布到SWF 12 并且通过新的playerglobal.swc配置你的制作环境。这些变更可以划分为下列三种类型:
- 增强视频播放事件
- NetStream监测
- 访问页面URL
在下面各节中,我将详细地介绍这些内容。
增强视频播放事件
Adobe的目标之一是无论视频传送使用什么方法(progressive, streaming或 HTTP streaming)均能够获得相同的信息。 为了实现这一目标,我们进行了如下更改(表1给出了以粗体表示的新事件):
- 我们已经为progressive、streaming和 HTTP streaming添加了 NetStream.SeekStart.Notify 事件。 当启动一个搜寻操作时,总是派发该事件。 它包含搜寻的启动时间。 注意,如果没有下载数据,则你在渐进式模式下不能获得一个NetStream.Seek.Notify 事件。
- NetStream.Play.Complete、NetStream.Pause.Notify 和 NetStream.Unpause.Notify用于触发渐进式播放。
表1. 用于视频测量的NetStream 事件(新事件用黑体字表示)
事件 | 描述 | 渐进式 下载 | 流 | HTTP流 |
---|---|---|---|---|
NetStream.Play.Start | 播放已经启动 | 已触发 | 已触发 | 不适用 |
NetStream.Play.Stop |
放已经停止 |
已触发 | 已触发 | 不适用 |
NetStream.Play.Complete | 视频已经播放完毕;回调NetStream.client | 已触发 | 已触发 | 不适用 |
NetStream.SeekStart.Notify | 搜寻已经启动 | 已触发 | 已触发 | 已触发 |
NetStream.Seek.Notify | 搜寻操作已经完毕 | 已触发 | 已触发 | 已触发 |
NetStream.Pause.Notify | 媒体流暂停 | 已触发 | 已触发 | 已触发 |
NetStream.Unpause.Notify | 媒体流恢复 | 已触发 | 已触发 | 已触发 |
NetStream.Play.Transition | 由于比特速率流切换,媒体流转换为另一个媒体流 | 不适用 | 已触发 | 不适用 |
NetStream.Play. TransitionComplete | 在多速率情形下,媒体流已经从一种比特率变更为另一种比特率;回调NetStream.client | 不适用 | 已触发 | 不适用 |
NetStream.Buffer.Full | 缓存满并且媒体流开始播放 | 已触发 | 已触发 | 已触发 |
NetStream.Buffer.Flush | 数据已经完成流处理并且剩余缓存已经清空 | 已触发 | 已触发 | 已触发 |
NetStream.Buffer.Flush | 接收数据的速度不够快,因此不能填满缓存 | 已触发 | 已触发 | 已触发 |
对于HTTP流处理,Flash不能触发NetStream.Play.Start和NetStream.Play.Stop,因为该平台不知道视频什么时间结束。 类似地,多速率切换功能必须由应用程序实现,因此NetStream.Play.Transition 和NetStream.Play.TransitionComplete 也不适用。 对于渐进式下载,NetStream.Play.Transition和 NetStream.Play.TransitionComplete 不适用,因为它不支持多速率功能。
对HTTP 流处理功能来说,派发这些事件是视频播放器的职责;关于一个代码范例,参见下列代码片段。
-
package org.osmf.net.httpstreaming
-
{
-
public class HTTPNetStream extends NetStream
-
{
-
-
private function signalPlayStart():void
-
{
-
dispatchEvent(new NetStatusEvent(NetStatusEvent.NET_STATUS, false, false,
-
{code:"NetStream.Play.Start", level:"status"}));
-
}
-
}
NetStream监测
Flash Player 10.3和 AIR 2.7 引入了 NetMonitor 类,它支持访问属于相同安全环境的 NetStream 对象。 NetMonitor 类具有两个功能:返回一个 NetStream对象列表以及当创建一个新的 NetStream 对象时派发一个NetMonitor事件。
使用下列代码获取一个现有NetStream对象列表:
- var monitor:NetMonitor = new NetMonitor();
- var streams:Vector.<NetStream>
- = monitor.listStreams();
为了在创建一个新的NetStream对象时能够接收通知,添加一个事件侦听器:
- monitor.addEventListener(NetMonitorEvent.NET_STREAM_CREATE, netStreamCreate);
至NetMonitor对象,并且具有下列处理程序:
-
private function netStreamCreate(e:NetMonitorEvent):void
-
{
-
// e.netStream is the new NetStream
-
}
-
一旦你能够访问NetStream对象,你可以连接事件侦听器以便获得播放事件的通报。
我们已经将 NetStreamInfo类进行扩展,以便包含元数据、XMP数据*和其它关于 NetStream 对象的信息。 该功能已经添加下面属性:
- NetStreamInfo.metaData:NetStream对象收到的最后一个元数据对象。 通常,视频文件以元数据开头。 此外,当搜寻或执行一个多速率转换时,Flash Media Server 发送一个更新的元数据对象。
- NetStreamInfo.xmpData:NetStream对象收到的最后一个XMP数据对象。
- NetStreamInfo.uri:用于NetConnection.connect() 方法的URI;提供与 NetConnection.uri相似信息。你可以使用该信息将一个特定的NetStream 对象与其NetConnection 对象进行关联。 这一功能仅用于流处理并且为渐进式和HTTP流处理返回null。
- NetStreamInfo.resourceName:用于NetStream.play() 方法的资源名称。 该信息包含渐进式下载的完全URL 以及 HTTP 流处理的null。
- NetStreamInfo.isLive:该属性仅适用于流处理,并且提供媒体是否为实况或录制的信息。 该信息通过Flash Media Server与Flash Player进行通信。
最后,我们已经添加一个名称为NetDataEvent的新的事件,它在处理数据消息时,由NetStream对象派发。 这对所有媒体传送机制均适用。 数据信息由NetStream.client对象作为一个回调进行处理。 相应的缺点是明显的:如果你希望拥有多个侦听器,你必须开发一个代理机制。 通过将这些回调转换为标准的Flash事件,你可以方便地捕获这些消息。 通过使用 NetDataEvent,监测应用程序能够访问元数据、 NetStream.Play.Complete、NetStream.Transition.Complete和其它更多属性。
访问页面URL
我们已经对Security类进行扩展以便提供页面域。 由于安全因素,全页面URL不能暴露。 尽管你可以使用一个外部界面获取页面URL,但这是一个跨不同平台和浏览器的更为可靠、方便和一致的方式。 当在浏览器中禁用JavaScript时,Security.pageDomain 将不能返回合适的页面域。
与使用Flash ExternalInterface 类相比,新方法具有下列优势:
- 只有在JavaScript启用时,外部界面才能工作。
- 外部界面要求在HTML wrapper中将allowScriptAccess设置为一个许可值。
- 当页面 URL和SWF文件 URL来自不同域时,pageDomain 方法也能够正常工作;在此之前,你需要设置 allowScriptAccess="always" 以便外部界面能够正常工作。
测量视频消费
在通常情形下,视频文件是由网站运营者、内容拥有者或第三方分销公司提供的。 视频播放器负责下载和播放这些视频文件。 它们可以是 Open Source Media Framework (OSMF)、Brightcove Player、JW Player、FLVPlayback或其它基于 SWF的播放器。 最常见的情形是网站运营者提供视频播放器。 网站运营者和内容拥有者均希望收集视频消费数据,他们可以使用测量应用程序实现这一任务。 典型的测量应用程序能够收集视频消费数据、汇集视频消费数据并且将其发送到服务器进行进一步地处理和呈现。
大多数时候,测量应用程序就是一个视频播放器插件。注意,开发的处理应用程序必须位于与视频播放器相同的安全环境中。
通过使用新的API,你可以使得测量应用程序能够直接访问视频播放器的NetStream对象,也就是说,你可以开发一个不需了解视频播放器并且直接从NetStream对象获取视频消费信息的单一测量应用程序。
典型的测量应用程序能够注册一个事件侦听器以便在创建NetStream对象时可以收到通知,并且在一个列表中存储NetStream对象。 通过侦听NetStatus事件,可以确定视频状态(播放、暂停、搜寻、停止等)。 如果在视频播放开始之后加载测量应用程序,它也能够通过NetMonitor访问NetStream对象以及通过NetStreamInfo访问相应的元数据和XMP数据。 通常,测量应用程序包含一个心跳定时器,它能够使用 NetStream.time属性定期地记录播放头的位置,并且将视频消费数据传送到一个测量服务。
图1给出了一个典型的使用情形。 网站运营者提供视频播放器及测量应用程序。 内容由第三方提供以确保其广泛的可得性。
图1. 通过一个测量插件监测视频播放器播放行为
隐私
上述增强功能的焦点是使得视频测量易于实现。 因此在视频播放器和测量应用程序之间必须存在信任的关系(在网站运营者、内容拥有者和测量服务提供者之间也是如此)。 利用新的API,你只能访问属于与你的测量应用程序相同的安全环境的视频播放器对象。 例如,如果你的视频播放器利用一个属于一个不同安全环境的插件播放一段广告,则你的测量应用程序将不能获取该广告的任何信息。
网站运营者必须显示地加载测量应用程序(直接地或间接地),这意味着用户应该同意网站的相应条款和条件。
测量数据需要发送到一个服务器以便汇集和呈现。 确保所需的视频消费数据安全传输是测量应用程序(因此也是网站运营者)的职责,例如,通过使用HTTPS进行传输。
范例应用程序
下面的范例应用程序演示了一个典型的使用案例。 主应用程序 (videoPlayer.swf) 加载两个子 SWF文件:视频播放器应用程序和测量应用程序 (videoMonitor.swf)。 所有三个应用程序必须由相同的web服务器提供并且位于相同的安全环境中。
该范例使用Strobe Media Playback* 播放一个渐进式视频文件。 目前,我们没有对Strobe Media Playback进行任何改动;我们使用了预先创建的SWF应用程序。 主应用程序加载 Strobe Media Playback 并且传递该视频 URL(存储于一个不同的服务器):
-
private static const PlayerUrl:String =
-
"StrobeMediaPlayback.swf?src=http://osmf.org/videos/cathy2.flv"
如果你希望使用流处理功能,你只需改变该URL 以指向你的FMS服务器:
-
private static const PlayerUrl:String =
-
"StrobeMediaPlayback.swf?src=rtmp://example.com/videos/flv:cathy2"
你可以方便地利用任何其它视频播放器替换Strobe Media Playback。 例如,如果你希望使用JW Player*,你可以下载它并且将它复制到你的web服务器的文档根目录中,然后更新videoPlayer.as:
-
private static const PlayerUrl:String = "player.swf?file=http://osmf.org/videos/cathy2.flv"
该测量应用程序能够演示下列功能:
- 记录页面域
- 当创建新的NetStream对象时,使用NetMonitor接收通知。
- 将元数据消息作为一个事件接收
- 将NetStream.Play.Complete回调作为一个NetDataEvent接收
- 定期捕获播放时间
- 使用NetStreamInfo捕获NetConnection URI和资源名称
- 捕获播放事件(搜寻和暂停)
- 定期将视频消费数据发送到一个web服务
范例应用程序的建立非常简单。 相应的包包含下列三个文件:
- videoPlayer.as: 这是主应用程序,它加载视频播放器和监测应用程序。 请配置该视频播放器的URL。 在Flash Builder中创建一个 "videoPlayer" ActionScript 项目以便建立该应用程序。 你必须使用Flash Player v10.3 和目标 SWF v12。将生成的 videoPlayer.swf 和支持文件复制到你的web服务器的文档根目录中。
- videoMonitor.as: 这是视频监测应用程序。 在加载时,它创建一个NetStream检测器和一个周期定时器。 该应用程序保存许多 NetStream 对象,但为了简化,它只上报第一个NetStream对象的信息。 请设置你的web服务器的URL以发送视频消费信息。 应用程序使用一个查询字符串将参数传递给相应的监测器服务。 在Flash Builder中创建一个 "videoMonitor" ActionScript 项目以便建立该应用程序。 你必须使用Flash Player v10.3 和目标 SWF v12。将生成的 videoMonitor.swf 复制到你的web服务器的文档根目录中。
- monitor.cgi: 这是一个帮助应用程序,它能够解析和记录来自视频监测器应用程序的视频消费数据。 这是一个简单的Perl脚本,它必须复制到你的web服务器的cgi-bin 可执行文件夹中。 范例输出:
- Page Url: http://153.32.146.208/, Action: HeartBeat, Uri: null,
- resourceName: http://osmf.org/videos/cathy2.flv, position: 42.657
此外,下载一个你选中的视频服务器(OSMF和 JW Player,然后相应地配置videoPlayer.as),并且将其放置于你的web服务器的文档根目录中。
下一步阅读方向
本文描述了新的Flash Player 10.3 和AIR 2.7的ActionScript API,Adobe 已经将其设计用于简化视频消费的测量。 该新的API能够为网站运营者和内容拥有者获取视频消费信息提供功能强大的工具-同时它符合Flash Player 的安全模型并且遵循网站的隐私规范。 通过使用这些新功能,你能够建立功能强大的媒体测量应用程序并且能够更深入地了解消费者是如何与你的网站和媒体内容互动的,而无论你选择什么视频播放器。
关于作者
Jozsef Vass是Flash运行时基础部门视频和内容保护小组的一名资深计算机科学家。他专注于Flash Player的实时音视频方面的技术。在加入Adobe之前,Jozsef为一家开创性的VoIP技术公司工作。他撰写了多篇网络和多媒体通讯方面的文章,并且拥有3项专利。
ADC中文站原文地址:http://www.adobe.com/cn/devnet/video/articles/media-measurement-flash.html