適用於 Chromeless Player 的 ActionScript 3.0 包裝函式

本文由外部開發人員撰寫及提交。YouTube API 和工具團隊感謝 Matthew Richmond 貢獻寶貴的時間與專業知識。


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

簡介

在本文中,我將簡單介紹適用於無邊框 YouTube 播放器的可靠 ActionScript 3.0 包裝函式。這個包裝函式會利用 ActionScript 的 ExternalInterface 類別以及 YouTube 的 JavaScript API。

Google 的 YouTube 播放器工具和無 Chrome 播放器可讓設計人員/開發人員輕鬆快速地將 YouTube 的強大功能與線上專案整合。這種方法非常適合用於預算固定且無法代管影片的小型專案。此外,如果大規模專案想要自訂使用者體驗,但又不離 YouTube 目標對象,也可以採用這種做法。

ActionScript 3.0 包裝函式螢幕擷取畫面
圖 1:ActionScript 3.0 包裝函式螢幕截圖

YouTube Flash API 和內嵌播放器是以 ActionScript 2.0 編寫而成,而且能完美搭配 ActionScript 2.0;如果您的專案是 ActionScript 3.0,則緊密整合就會變得更加複雜。雖然在 ActionScript 3.0 swf 中載入 ActionScript 2.0 播放器很簡單,但您無法直接進行通訊或傳遞任何功能呼叫到載入的播放器。這項問題更為複雜,因為來自 YouTube 伺服器的 swf 檔案會將影片載入自身。我們的包裝函式需要充分瞭解,並據此做出反應。幸運的是,ActionScript 語言包含兩個可行的解決方法,來重新連結這些巢狀但中斷連線的部分:LocalConnection 類別或 ExternalInterface 類別。此示範將著重於後者,因為 ExternalInterface 可與詳細記錄的 JavaScript API 完美搭配運作,因此能完美搭配 XHTML 網頁中的其他內容。

重要資源

開始之前,請先參閱下列相關資源和檔案。本文討論的許多主題,在下方連結中都有更詳細的說明。

深入探究

包裝函式示範總覽

ActionScript 類別檔案
圖 3:JavaScript 檔案
ActionScript 類別檔案
圖 2:ActionScript 類別檔案

ActionScript 3.0 包裝函式基本上包含兩個相互連結的部分,包括位於 src/chopingblock/video/ 的 ActionScript 3.0 類別檔案 (圖 2),以及「youTubeLoader.js」JavaScript 檔案位於 deploy/_assets/js/ (圖 3)。Flash/Flex 來源檔案會建立 YouTubeLoader ActionScript 類別的例項;XHTML 頁面會嵌入 Flash 檔案,並將其註冊至 youTubeLoader JavaScript 檔案中的函式。請務必瞭解,從這裡開始,YouTubeLoader 在 Flash 檔案中執行的所有操作,都是透過 JavaScript 函式控制。

由於 Flash 的所有功能是透過 JavaScript API 控制,因此您無法在 Flash 的「測試影片」中載入任何 YouTube 內容廣告。只有在嵌入 XHTML 網頁,並正確連線至 YouTubeLoader JavaScript 函式時,才有作用。

注意:如要測試這些呼叫,您必須在網路伺服器上執行檔案,或修改 Flash Player 的安全性設定,因為 Flash Player 會限製本機檔案和網際網路之間的呼叫。

建立 YouTubeLoader 物件

在 Flash/Flex 專案中建立 YouTubeLoader 物件的例項之前,請先確認必要檔案的套件 (資料夾) 與專案位於相同目錄 (請參閱圖 2),或已透過專案的 Classpath 定義。接著,您可以匯入套件檔案:

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 內容。建議您使用 SWFObject 嵌入任何會使用 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>

請參閱下方的範例,瞭解如何使用 SWFObject 嵌入啟用 JavaScript API 的 ActionScript 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 參數必須允許播放器 SWF 在包含 HTML 頁面的網頁上呼叫函式。

我們傳入的唯一屬性是嵌入物物件的 ID,在本例中為 youtubewrapper。這個 ID 是 youTubeLoader.js 檔案會使用 getElementById() 取得玩家參照時所用的 ID。

swfobject.embedSWF 會從 YouTube 載入播放器,並將其嵌入網頁。

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

  • swfUrlStr:這是 SWF 的網址。請注意,我們已將 enablejsapiplayerapiid 參數附加至一般 YouTube SWF 網址,以便啟用 JavaScript API 呼叫。
  • replaceElemIdStr:這是 HTML DIV ID,用於取代嵌入內容。在上述範例中為 ytapiplayer
  • widthStr - 播放器的寬度。
  • heightStr - 玩家的高度。
  • swfVersionStr - 使用者查看內容所需的最低版本。在此情況下,你需要安裝 8 以上版本。如果使用者沒有 8 或以上,他們會在 HTML DIV 中看到預設的文字行。
  • xiSwfUrlStr - (選用) 指定快速安裝 SWF 的網址。這個範例中並未使用。
  • flashVarsObj - (選用) 以 name:值組合指定 Flash 變數。這個範例中並未使用。
  • parObj - (選用) 嵌入物件參數。在本例中,我們設定了 allowScriptAccess
  • AttObj - (選用) 嵌入物件屬性。在這個範例中,我們已將 ID 設為 myytplayer

如需進一步說明,請參閱 SWFObject 說明文件

SWFID ≡ 會儲存嵌入物件 ID 的參照,以供 JavaScript API 使用。您必須針對 swf 提供的嵌入物件使用相同的 ID。

SWFID ≡ "youtubewrapper"

現在,您應該能夠成功測試專案。YouTubeLoader 物件應載入 Chromeless Player,且 YouTubeLoaderEvent.LOADED 事件處理常式應成功呼叫。現在我們準備提出影片要求,並與 YouTubeLoader 物件互動。

與播放器互動

由於這個建立無 Chrome 播放器專用的 ActionScript 3.0 包裝函式的方法,就是利用 ActionScript 的 ExternalInterface 類別,因此現在可以使用 YouTube JavaScript Player API 中的任何作業來控制載入的播放器。如果您查看「youTubeLoader.js」您的 JavaScript 檔案位於 deploy/_assets/js/ (圖 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...

有鑑於「無邊框播放器」 ActionScript 3.0 包裝函式的目標,是為了透過 ActionScript 3.0 Flash/Flex 專案提供與 YouTube API 流暢的互動,我們在「YouTubeLoader.as」中新增了完全相同的公開方法。位於 src/choppingblock/video/ 中的類別檔案 (圖 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...

ActionScript 方法會使用 ExternalInterface 類別,只在 JavaScript API 中呼叫適當的函式。

要求影片

您現在可以使用播放器參照來呼叫函式,在 ActionScript 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> 

發出其他來電

額外呼叫的運作方式與「要求視訊」完全相同;,您可以直接使用播放器參照來呼叫方法。如需可用方法的完整清單,請參閱下方內容

訂閱事件

將事件監聽器新增至播放器參照,即可訂閱事件。舉例來說,如要在玩家狀態變更時收到通知,請為 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
在「無邊框播放器」成功載入並準備好接受作業呼叫時觸發。
YouTubeLoaderEvent.STATE_CHANGE
每當玩家狀態變更時就會觸發。YouTubeLoader 類別會將 JavaScript API 號碼轉譯成相關的字串值,YouTubeLoaderEvent 類別會將目前事件儲存在名為 state 的變數中。可能的值包括未開始、已結束、正在播放、已暫停、正在緩衝、影片已cue。當 SWF 首次載入時,會廣播未啟動的事件。影片獲收錄並準備好播放時,就會播送影片自動提醒事件。
YouTubeLoaderEvent.IO_ERROR
在播放器發生錯誤時觸發。可能會出現兩個錯誤代碼:如果找不到要求的影片,系統會廣播 100。如果影片是因故遭移除,或是已標示為私人影片,就會出現這種情況。如果所要求的影片不允許在嵌入式播放器中播放,則會播放 101。

示範中的注意事項

為了示範,我們想在內嵌的 ActionScript 3 包裝函式下方加入 XHTML 表單欄位、按鈕和顯示 UI。為了讓 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)
}

示範檔案和內含的 ActionScript 程式庫都是免費軟體:您可以根據《GNU 較小的一般公共授權》條款,重新發布和/或修改該檔案。我們發布這些檔案是希望能對您有所幫助,但不提供任何保證。

結論

本文、示範來源檔案應可提供相對簡單且可靠的解決方案概要,讓您瞭解如何使用我們為自有專案開發的包裝函式庫,將 YouTube API 和嵌入式播放器整合至 ActionScript 3 環境。由於我曾評論過許多程式碼,在理想情況下,探索程式庫和重新利用這些程式碼會相當簡單。它並沒有限制,而且總有進步、重構和強化。如有任何想法,歡迎與我聯絡。

作者簡介


Matthew Richmond

Matthew Richmond 有 14 年的互動式設計、開發和建築經驗。在工作室以外的時間,他會在視覺藝術學校教授數位插圖/攝影技巧和進階 ActionScript。Matthew 是 choppingblock.com 的創辦人與設計人員,