适用于 Chromeless Player 的 Action 3.0 封装容器

本文由外部开发者编写和提交。 YouTube API 和工具团队感谢 Matthew Richmond 所投入的时间和专业知识。


Matthew Richmond,The Chopping Block, Inc.
2008 年 10 月

简介

在本文中,我将向大家简要介绍并介绍适用于 Chromeless YouTube 播放器的可靠 ActionScript 3.0 封装容器。该封装容器利用了 Action 的 ExternalInterface 类以及 YouTube 的 JavaScript API。

Google 的 YouTube 播放器工具和 Chromeless Player 让设计人员/开发者能够轻松快捷地将 YouTube 的强大功能集成到他们的在线项目中。这种方法非常适合采用固定预算(不允许托管视频)的小项目,以及大规模项目,适合希望保持自定义最终用户体验,同时又不会与 YouYube 受众群体保持距离的客户。

Action 3.0 封装容器屏幕截图
图 1:ActionScript 3.0 封装容器屏幕截图

YouTube 的 Flash API 和嵌入式播放器是用 JavaScript 编写的,非常适合用于 Action 2.0;不过,如果您的项目是 Action 3.0,那么无缝集成会变得更为复杂。虽然将 ActionScript 2.0 播放器加载到 ActionScript 3.0 swf 中很简单,但是您不能直接传递任何功能调用,也无法将任何功能调用传入已加载的播放器。情况更为复杂,因为来自 YourTube 服务器的 swf 文件会将视频加载到其自身中。我们的封装容器需要充分了解这一情况,并做出相应反应。幸运的是,ActionScript 语言包含两个重新连接这些嵌套但已断开连接的片段的可行权宜解决方法:LocalConnection 类或 ExternalInterface 类。本演示将重点介绍后者,因为 ExternalInterface 可与文档完备的 JavaScript API 无缝对接,因此能够与 XHTML 页面中的其他任何内容完美配合。

重要资源

在开始之前,我们列出了您可以获取的相关资源和文件。通过以下链接可详细了解本文中讨论的许多主题。

深入了解

封装容器演示概览

Action 类文件
图 3:JavaScript 文件
Action 类文件
图 2:ActionScript 类文件

Action 3.0 封装容器基本上由两个互连的部分组成:位于 src/choppingblock/video/ 中的 Action 3.0 类文件(图 2)以及位于 deploy/_assets/js/ 的“youTubeLoader.js”JavaScript 文件(图 3)。您的 Flash/Flex 源文件将创建一个 YouTubeLoader Action 类的实例;您的 XHTML 页面会嵌入该 Flash 文件,并在 youTubeLoader JavaScript 文件中向该函数注册该文件。务必要了解,从这里,YouTubeLoader 在 Flash 文件中执行的操作均通过 JavaScript 函数进行控制。

由于 Flash 中的所有功能均通过 JavaScript API 进行控制,因此您将无法在 Flash 的“测试影片”播放器中加载任何 YouTube 内容。仅当嵌入到 XHTML 页面中并正确连接到 YouTubeLoader JavaScript 函数时,它才有效。

注意:要测试其中任何一个调用,您都必须在网络服务器上运行您的文件或修改 Flash Player 的安全设置,因为 Flash Player 会限制本地文件与互联网之间的调用。

创建 YouTubeLoader 对象

要在 Flash/Flex 项目中创建 YouTubeLoader 对象的实例,您必须先确保所需文件的软件包(文件夹)与项目位于同一目录中(参见图 2),或者使用您的项目类路径进行定义。然后,您可以导入软件包文件:

import choppingblock.video.*;

这样,您的 ActionScript 文件即可访问“YouTubeLoader.as”和“YouTubeLoaderEvent.as”类。现在,您可以创建 YouTubeLoader 类的实例和必要的事件监听器:

import choppingblock.video.*;

public class YouTubeDemo extends Sprite {

  private var _youTubeLoader:YouTubeLoader;	
  
  // ------------------------------------
  // CONSTRUCTOR
  // ------------------------------------
  
  public function YouTubeDemo () {
    
    // create YouTubeLoader object
    _youTubeLoader = new YouTubeLoader();
    
    // add event listener to call youTubePlayerLoadedHandler method on load
    _youTubeLoader.addEventListener(YouTubeLoaderEvent.LOADED, youTubePlayerLoadedHandler);
    
    // create the actual loader 
    _youTubeLoader.create();
    
    // add object to the display stack
    addChild(_youTubeLoader);
  };
  
  // ------------------------------------
  // EVENT METHODS
  // ------------------------------------
  
  /**
  Called via player loaded event, lets you know you are all clear to send player commands.
  */
  private function youTubePlayerLoadedHandler (event:YouTubeLoaderEvent):void{
    //trace("YouTubeDemo: youTubePlayerLoadedHandler");
    
    // you are now clear to start making calls to the YouTubeLoader object
  };
};

现在,如果 JavaScript 文件已准备就绪且连接正确,那么应该可以成功调用 youTubePlayerLoadedHandler,我们就可以开始发出请求了。

嵌入 swf 和连接 youTubeLoader JavaScript

您的 swf 文件嵌入到 XHTML 文件中并连接到 youTubeLoader JavaScript 之前,您将无法从 YouTube 成功加载内容。我们建议您使用 {4/}Object 嵌入将使用 JavaScript API 访问的任何播放器。这让您可以检测最终用户的 Flash Player 版本(JavaScript API 需要 Flash Player 8 或更高版本),并且在使用 Internet Explorer 查看播放器时,会消除“点击激活此控件”框。

在 XHTML 文件的 <head> 部分中,连接 swfobject 和 youTubeLoader 文件:

<script type="text/javascript" src="_assets/js/swfobject.js"></script>
<script type="text/javascript" src="_assets/js/youTubeLoader.js"></script>

请参见以下示例,了解如何使用 {4/}Object 嵌入启用了 JavaScript API 的 Actions 3.0 swf,然后将对 swf 的引用传递给 youTubeLoader JavaScript API。

<script type="text/javascript">

  var flashvars = {};
  var params = {
    menu: "false",
    allowScriptAccess: "always",
    scale: "noscale"
  };
  var attributes = {
    id: "youtubewrapper"
  };

  swfobject.embedSWF("YouTubeIntegrationDemo.swf", "flashcontent", "960", "500", "9.0.0", "_assets/swf/expressInstall.swf", flashvars, params, attributes);
  
  //init the youTubeLoader JavaScript methods
  SWFID = "youtubewrapper"
    
</script>

由于 Chromeless Player 的托管网域与 XHTML 网页不同,因此需要使用代码中的 allowScriptAccess 参数来允许播放器 {4/} 调用所在 HTML 网页上的函数。

我们传入的唯一一个属性是嵌入对象(在本例中为 youtubewrapper)的 ID。此 ID 就是 youTubeLoader.js 文件用来通过 getElementById() 获取播放器引用的内容。

swfobject.embedSWF 将从 YouTube 加载播放器并将其嵌入您的网页。

swfobject.embedSWF(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj)

  • swfUrlStr - 这是 {4/} 的网址。请注意,我们在正常的 YouTube {4/} 网址后面附加了 enablejsapiplayerapiid 参数,以便启用 JavaScript API 调用。
  • replaceElemIdStr - 这是要替换为嵌入内容的 HTML DIV ID。在上面的示例中,它是 ytapiplayer
  • widthStr - 播放器的宽度。
  • heightStr - 播放器的高度。
  • swfVersionStr - 用户查看内容所需的最低版本。在此示例中,需要使用版本8或更高版本。如果用户没有安装版本 8 或更高版本,则会在 HTML DIV 中看到默认的文本行。
  • xiSwfUrlStr -(可选)指定快速安装 {4/} 的网址。本例未使用。
  • flashVarsObj -(可选)以“名称:值”对的形式指定 FlashVar。在此示例中未使用。
  • parObj -(可选)嵌入对象的参数。在本例中,我们设置了 allowScriptAccess
  • AttObj -(可选)嵌入对象的属性。在本例中,我们已将 ID 设置为 myytplayer

请参阅SWFObject文档,了解进一步的说明。

SWFID ≡ 会存储对嵌入对象的 ID 的引用,供 JavaScript API 使用。您必须使用与 swf 相同的嵌入对象的 ID。

SWFID ≡ "youtubewrapper"

此时,您应该能够成功测试您的项目。YouTubeLoader 对象应该会触发 Chromeless Player,并且 YouTubeLoaderEvent.LOADED 事件处理脚本应该可以成功调用。现在,我们就可以发出视频请求并与 YouTubeLoader 对象互动了。

与玩家互动

由于为 Chromeless Player 创建 Actions 3.0 封装容器的方法是利用 Action 的 ExternalInterface 类,因此我们现在可以使用 YouTube JavaScript Player API 中的任何操作来控制已加载的播放器。如果您查看部署/_assets/js/ 中的“youTubeLoader.js”JavaScript 文件(图 3),就会发现它包含大多数可用函数。每个操作函数会先对照 checkObj 函数进行检查,以验证 SWFID 变量在执行之前是否已正确设置。

//------------------------------------
// UTILITY METHODS
//------------------------------------

function checkObj () {
  // alert("youTubeLoader.js : checkObj");
  if (SWFID) {
    createObj();
    return true;
  } else{
    alert("YouTubeLoader: In order to call methods within a swf, you must first set the variable \"SWFID\"!");
    return false;
  };
}
  
//------------------------------------
// YOUTUBE METHODS
//------------------------------------

function loadVideoById(id, startSeconds) {
  // alert("youTubeLoader.js : loadVideoById");
  if (checkObj()) {
    obj.loadVideoById(id,startSeconds);
  };
};

function cueNewVideo(id, startSeconds) {
  // alert("youTubeLoader.js : loadVideoById");
  if (checkObj()) {
    obj.cueVideoById(id, startSeconds);
  }
}

function clearVideo() {
  // alert("youTubeLoader.js : clearVideo");
  if (checkObj()) {
    obj.clearVideo();
  }
}

// plus 17 more...

鉴于用于 Chromeless Player 的 Actions 3.0 封装容器的最终目标是,在 Actions 3.0 Flash/Flex 项目中提供与 YouTube API 的无缝交互,因此我们向位于 src/choppingblock/video/ 中的“YouTubeLoader.as”类文件添加了完全相同的公开方法(图 2)。也就是说,您可以直接在 Flash/Flex 中对 YouTubeLoader 对象调用完全相同的操作。在类文件中,您会看到:

// ------------------------------------
// YOUTUBE METHODS
// ------------------------------------

public function loadVideoById (id:String, startSeconds:Number = 0):void{
  //trace("YouTubeLoader: loadVideoById");
  ExternalInterface.call("loadVideoById", id, startSeconds);
};

public function cueNewVideo (id:String, startSeconds:Number = 0):void{
  //trace("YouTubeLoader: cueNewVideo");
  ExternalInterface.call("cueNewVideo", id, startSeconds);
};

public function clearVideo ():void{
  //trace("YouTubeLoader: clearVideo");
  ExternalInterface.call("clearVideo");
};

// plus 17 more...

使用 ExternalInterface 类,ActionScript 方法只需调用 JavaScript API 中的相应函数。

请求视频

现在,您可以通过使用播放器引用调用函数,在 Action 3.0 文件中请求视频。例如,如果您希望在用户点击按钮时播放视频,则应向按钮添加 MouseEvent.CLICK 事件监听器。示例如下:

// assuming your button was called 'myButton'
myButton.addEventListener(MouseEvent.CLICK, youtubeLoadVideoHandler);

并创建事件处理脚本方法来处理请求。示例如下:

private function youtubeLoadVideoHandler (event:MouseEvent):void{
  
  // assuming that '_youTubeLoader' is a reference to your YouTubeLoader object
  _youTubeLoader.loadVideoById( "u1zgFlCw8Aw" );
};

在 Flash/Flex 文件之外,您也可以选择通过调用相应的 JavaScript 函数来请求视频。示例如下:

 <a href="javascript:loadVideoById('u1zgFlCw8Aw')">Play</a> 

发出其他调用

其他调用的工作方式与请求视频完全相同;在 ActionScript 3 中,您只需使用播放器引用调用方法即可。如需查看可用方法的完整列表,请点击下文

订阅事件

在播放器的引用中添加事件监听器可订阅事件。例如,如需在播放器的状态发生变化时收到通知,请为 YouTubeLoaderEvent.STATE_CHANGE 添加事件监听器。示例如下:

// assuming that '_youTubeLoader' is a reference to your YouTubeLoader object
_youTubeLoader.addEventListener(YouTubeLoaderEvent.STATE_CHANGE, youTubePlayerStateChangeHandler);

并创建事件处理脚本方法来处理请求。示例如下:


private function youTubePlayerStateChangeHandler (event:YouTubeLoaderEvent):void{
  //trace("YouTubeIntegrationDemo: youTubePlayerStateChangeHandler");
  
  _stateField.text = event.state;
};

可用操作

要调用 YouTubePlayer API 方法,您必须先在 ActionScript 文件中创建 YouTubePlayer 类的实例,并存储对要控制的 YouTubePlayer 对象的引用。这可通过调用以下代码实现:

var _youTubeLoader:YouTubeLoader;
_youTubeLoader = new YouTubeLoader();

公共方法

player.loadVideoById(id:String, startSeconds:Number = 0):void
根据指定的 ID 加载和播放视频。
player.cueNewVideo(id:String, startSeconds:Number = 0):void
加载但不根据指定 ID 自动播放视频。
player.clearVideo():void
清除当前已插入/已加载的视频。
player.setSize(w:Number, h:Number):void
设置 YouTubePlayer 实例的大小。
player.play():void
播放当前已插入/已加载的视频。
player.pause():void
暂停当前已插入/已加载的视频。
player.stop():void
停止当前已插入/已加载的视频。
player.seekTo(seconds:Number):void
定位到当前已插入/已加载的视频中的指定时间。
player.getPlayerState():String
返回当前已插入/已加载视频的当前状态。
player.getBytesLoaded():Number
返回当前已插入/已加载视频的当前已加载字节的值。
player.getBytesTotal():Number
返回当前已插入/已加载视频加载的总字节数。
player.getCurrentTime():Number
返回当前已插入/加载的视频的当前位置。
player.getDuration():Number
返回当前已插入/已加载的视频的当前时长。
player.getStartBytes():Number
返回当前已插入/已加载的视频的起始字节。
player.setVolume(newVolume:Number):void
设置当前已插入/已加载视频的音量。
player.getVolume():Number
返回当前已插入/已加载的视频的当前音量。
player.mute():void
存储当前音量,并将当前已插入/已加载视频的音量更改为 0。
player.unmute():void
静音时,会将当前已插入/已加载的视频的音量值恢复到上次存储的值。
player.getEmbedCode():String
返回当前已插入/已加载的视频的当前 YouTube 嵌入代码。
player.getVideoUrl():String
返回当前已插入/已加载的视频的当前 YouTube 视频网址。

活动

YouTubeLoaderEvent.LOADED
在 Chromeless Player 成功完成加载并准备好接受操作调用后触发。
YouTubeLoaderEvent.STATE_CHANGE
每当播放器状态发生变化时触发。YouTubeLoader 类会将 JavaScript API 编号转换成其相关的字符串值,YouTubeLoaderEvent 类会将当前事件存储在名为 state 的变量中。可能的值包括:unstarted、end、playing、 paused、buffering、video cued。首次加载时,MOV 会广播未开始的事件。在视频插入完毕而且可供播放时,系统会广播已插入视频事件。
YouTubeLoaderEvent.IO_ERROR
播放器出现错误时触发。可能有两个错误代码:找不到视频时广播 100。当视频因任何原因遭到移除或标记为私享时,就会出现这种情况。如果所请求的视频不允许在嵌入式播放器中播放,则系统会广播 101。

演示注意事项

为便于演示,我们希望将 XHTML 表单字段、按钮和显示界面包括在嵌入的 Action 3 封装容器下方。为了让 swf 文件和 XHTML 同时更新,我们必须在位于“deploy/_assets/js/”的“youTubeLoader.js”JavaScript 文件中添加两行代码(图 3)。将此文件集成到您的项目中时,您需要移除以下两行 [69, 79]:

//------------------------------------
// SPECIAL YOUTUBE EVENT METHODS
//------------------------------------

function onYouTubePlayerReady(playerId) {

  if (checkObj()) {	
    obj.addEventListener("onStateChange", "onytplayerStateChange");
  };

  // PLEASE NOTE: For the purpose of this demo:
  // This calls a secondary method located in the index.html file allowing the html display to update.
  // You will most likely not need this, it's gross, remove this when you implement this code.
  secondaryOnYouTubePlayerReady(playerId);
}

function onytplayerStateChange(newState) {
    //alert("Player's new state: " + newState);
  obj.playerStateUpdateHandler(newState);

  // PLEASE NOTE: For the purpose of this demo:
  // This calls a secondary method located in the index.html file allowing the html display to update.
  // You will most likely not need this, it's gross, remove this when you implement this code.
  secondaryOnytplayerStateChange(newState)
}

演示文件和随附的 Action 库是一款免费软件:您可以重新分发该文件,并/或根据 GNU Minor 通用公共许可证条款对其进行修改。我们在发布这些文件时希望能对您有所帮助,但不作任何担保。

总结

演示源文件一文详细介绍了应该如何相对简单可靠地将 YouTube API 和嵌入式播放器集成到针对我们自己的项目开发的封装容器库中的 Action 3 环境中。因为我对代码的大部分内容进行了评论,所以理想情况下,对库进行探索和重新利用将变得相当简单。这并非不受限制,并且始终有改进、重构和增强的空间。如果您对此有任何问题,请随时与我联系。

作者个人简介


马修·里士满

Matthew Richmond 拥有 14 年的互动式设计、开发和架构经验。在工作室内时,他喜欢在视觉艺术学院讲授数字插图/摄影技巧和高级动作技巧。Matthew 是 choppingblock.com 的创始合伙人和设计师。