Wrapper של ActionScript 3.0 לנגן ללא Chrome

המאמר הזה נכתב ונשלח על ידי מפתח חיצוני. צוות ממשקי ה-API והכלים של YouTube מודה למתיו ריצ'מונד על הזמן והמומחיות שלו.


Matthew Richmond, ‏ The Chopping Block, Inc.
אוקטובר 2008

מבוא

במאמר הזה אציג עטיפה (wrapper) מהימנה של ActionScript 3.0 לנגן YouTube ללא Chrome, ואסביר עליה בקצרה. ה-wrapper משתמש במחלקה ExternalInterface של ActionScript וב-JavaScript API של YouTube.

הכלים של Google Player ל-YouTube והנגן ללא Chrome מאפשרים למעצבים ולמפתחים לשלב את היכולות של YouTube בפרויקטים שלהם באינטרנט במהירות ובקלות. הגישה הזו אידיאלית לפרויקטים קטנים בתקציבים קבועים שלא מאפשרים אירוח סרטונים, וכן לפרויקטים בקנה מידה גדול ללקוחות שרוצים חוויית משתמש מותאמת אישית בלי להתרחק מהקהל שלהם ב-YouTube.

צילום מסך של ActionScript 3.0 Wrapper
איור 1: צילום מסך של ActionScript 3.0 Wrapper

ה-Flash API והנגנים המוטמעים של YouTube נכתבים ב-ActionScript 2.0 ופועלים בצורה טובה למדי עם ActionScript 2.0. עם זאת, אם הפרויקט שלכם הוא ActionScript 3.0, השילוב החלק הופך להיות קצת יותר מורכב. אמנם קל לטעון את נגני ActionScript 2.0 ל-ActionScript 3.0 swf, אבל לא ניתן לתקשר ישירות או להעביר קריאות פונקציונליות לנגן שנטען. המצב מסתבך עוד יותר כי קובץ ה-SWF שמגיע מהשרתים של YourTube טוען סרטון לתוכו. למעטפת שלנו צריכה להיות מודעו מלאה לעובדה הזו, והיא צריכה להגיב בהתאם. למרבה המזל, שפת ActionScript מכילה שתי דרכים סבירות להתחבר מחדש לחלקים המוטמעים האלה, שעדיין לא מחוברים: הכיתה LocalConnection או הכיתה ExternalInterface. הדגמה הזו תתמקד באפשרות השנייה, כי ExternalInterface פועל בצורה חלקה עם JavaScript API המפורט היטב, ולכן מתאים לכל דבר אחר בדף ה-XHTML.

מקורות מידע חשובים

לפני שנתחיל, הנה רשימה של מקורות מידע וקובצי עזר שזמינים לך. רבים מהנושאים שמוזכרים במאמר זה מפורטים בקישורים הבאים.

מעיינים לעומק

סקירה כללית של הדגמה של Wrapper

קובצי Class של ActionScript
איור 3: קובץ JavaScript
קובצי Class של ActionScript
איור 2: קובצי כיתות של ActionScript

למעשה, המעטפת של ActionScript 3.0 מורכבת משני חלקים מקושרים: קובצי הכיתה של ActionScript 3.0 שנמצאים בתיקייה src/choppingblock/video/‏ (איור 2), וקובץ ה-JavaScript 'youTubeLoader.js' שנמצא בתיקייה deploy/_assets/js/‏ (איור 3). קובץ המקור של Flash/Flex ייצור מופע של הכיתה YouTubeLoader ActionScript. דף ה-XHTML יוטמע את קובץ ה-Flash וירשם אותו עם הפונקציות בקובץ JavaScript של youTubeLoader. חשוב מאוד להבין שמכאן כל מה ש-YouTubeLoader עושה בקובץ ה-Flash נשלט באמצעות הפונקציות של JavaScript.

מכיוון שכל הפונקציונליות ב-Flash נשלטת באמצעות JavaScript API, לא תהיה לך אפשרות לטעון תוכן של YouTube בנגן 'סרטון הבדיקה' של Flash. הוא יפעל רק אם הוא יטמע בדף XHTML ויחובר כראוי לפונקציות JavaScript של youTubeLoader.

הערה: כדי לבדוק אחת מהקריאות האלו, הקובץ צריך לפעול בשרת אינטרנט או לשנות את הגדרות האבטחה של ה-Flash Player, מכיוון שנגן ה-Flash מגביל שיחות בין קבצים מקומיים לאינטרנט.

יצירת אובייקט YouTubeLoader

לפני שתוכלו ליצור מופע של אובייקט YouTubeLoader בפרויקט ה-Flash/Flex, אתם צריכים קודם לוודא שהחבילה (התיקייה) של הקבצים הנדרשים נמצאת באותה ספרייה שבה נמצא הפרויקט (ראו איור 2) או מוגדרת ב-Classpath של הפרויקטים. לאחר מכן אפשר לייבא את קובצי החבילה:

import choppingblock.video.*;

כך לקובץ ActionScript תהיה גישה לכיתות YouTubeLoader.as ו-YouTubeLoaderEvent.as. עכשיו אפשר ליצור מופע של הכיתה YouTubeLoader ואת פונקציות ה-event listener הנדרשות:

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 וחיבור ה-JavaScript של youTubeLoader

לא ניתן יהיה לטעון תוכן מ-YouTube עד שקובץ ה-swf שלכם יוטמע בקובץ XHTML ומחובר ל-JavaScript של YouTube Loader. מומלץ להשתמש ב-SWFObject כדי להטמיע נגני SWF שאפשר לגשת אליהם באמצעות JavaScript API. כך תוכלו לזהות את גרסת Flash Player של משתמש הקצה (ל-JavaScript API נדרש Flash Player 8 ואילך), וגם להסיר את התיבה 'לחיצה כדי להפעיל את אמצעי הבקרה הזה' כשמשתמשים ב-Internet Explorer כדי להציג את הנגן.

בחלק <head> בקובץ ה-XHTML, מחברים את קובצי swfobject ו-youTubeLoader:

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

בהמשך מופיעה דוגמה לשימוש ב-SWFObject כדי להטמיע קובץ SWF של ActionScript 3.0 עם JavaScript API מופעל, ולאחר מכן להעביר הפניה לקובץ ה-SWF ל-JavaScript API של youTubeLoader.

<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>

הפרמטר allowScriptAccess בקוד נדרש כדי לאפשר ל-SWF של הנגן להפעיל פונקציות בדף ה-HTML שמכיל אותו, כי הנגן ללא Chrome מתארח בדומיין שונה מדף ה-XHTML.

המאפיין היחיד שאנחנו מעבירים הוא המזהה של אובייקט ההטמעה – במקרה הזה, youtubewrapper. המזהה הזה ישמש את קובץ youTubeLoader.js כדי לקבל הפניה לנגן באמצעות getElementById().

swfobject.embedSWF יטען את הנגן מ-YouTube ויטמיע אותו בדף.

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

  • swfUrlStr - זו כתובת ה-URL של קובץ ה-SWF. חשוב לציין שהוספנו את הפרמטרים enablejsapi ו-playerapiid לכתובת ה-URL הרגילה של קובץ ה-SWF של YouTube כדי לאפשר קריאות ל-JavaScript API.
  • replaceElemIdStr – זהו מזהה ה-DIV ב-HTML שצריך להחליף בתוכן המוטמע. בדוגמה שלמעלה, זהו ytapiplayer.
  • widthStr – רוחב הנגן.
  • heightStr – הגובה של השחקן.
  • swfVersionStr – הגרסה המינימלית הנדרשת כדי שהמשתמש יוכל לראות את התוכן. במקרה כזה, נדרשת גרסה 8 ואילך. אם למשתמש אין גרסה 8 ומעלה, הוא יראה את שורת הטקסט המוגדרת כברירת מחדל ב-HTML DIV.
  • xiSwfUrlStr – (אופציונלי) מציין את כתובת ה-URL של קובץ ה-SWF להתקנה מיידית. לא בשימוש בדוגמה הזו.
  • flashVarsObj – (אופציונלי) מציין את FlashVars בזוגות שם:ערך. לא בשימוש בדוגמה הזו.
  • parObj – (אופציונלי) הפרמטרים של אובייקט ההטמעה. במקרה הזה, הגדרנו את allowScriptAccess.
  • AttObj – (אופציונלי) המאפיינים של אובייקט ההטמעה. במקרה הזה, הגדרנו את המזהה כ-myytplayer.

להסבר נוסף, ראו תיעוד בנושא SWFObject.

SWFID ≡ יאחסן הפניה למזהה של אובייקט ההטמעה לשימוש ב-JavaScript API. צריך להשתמש באותו מזהה של אובייקט ההטמעה שהקצית לקובץ ה-SWF.

SWFID ≡ "youtubewrapper"

בשלב הזה אמורה להיות לכם אפשרות לבדוק את הפרויקט בהצלחה. האובייקט YouTubeLoader אמור לטעון את הנגן ללא Chrome, והקריאה לבורר האירועים YouTubeLoaderEvent.LOADED אמורה להתבצע בהצלחה. עכשיו אנחנו מוכנים לשלוח בקשה להצגת סרטון ולנהל אינטראקציה עם האובייקט YouTubeLoader.

אינטראקציה עם הנגן

הגישה הזו ליצירת מעטפת של ActionScript 3.0 לנגן ללא Chrome מתבססת על הכיתה ExternalInterface של ActionScript, כך שאנחנו יכולים עכשיו להשתמש בכל אחת מהפעולות ב-YouTube JavaScript Player API כדי לשלוט בנגן שהוטען. אם נעיף מבט בקובץ JavaScript‏ 'youTubeLoader.js' שנמצא בתיקייה 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 לנגן ללא Chrome היא לספק אינטראקציה חלקה עם YouTube API מתוך פרויקט ActionScript 3.0 Flash/Flex, הוספנו את אותן שיטות ציבוריות לקובץ הכיתה 'YouTubeLoader.as' שנמצא ב-src/choppingblock/video/‏ (איור 2). כלומר, אפשר לקרוא לאותן פעולות ישירות לאובייקט YouTubeLoader בתוך Flash/Flex. בקובץ הכיתתי מופיעים הפרטים הבאים:

// ------------------------------------
// 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> 

שליחת שיחות נוספות

קריאות נוספות פועלות בדיוק כמו בקשה להצגת סרטון. מתוך 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;
};

הפעולות הזמינות

כדי לקרוא ל-methods של ממשק ה-API של YouTubePlayer, ראשית עליך ליצור מופע של המחלקה YouTubePlayer בתוך קובץ ה-ActionScript ולאחסן את ההפניה לאובייקט YouTubePlayer שבו ברצונך לשלוט. כדי לעשות זאת, צריך לבצע את הקריאה הבאה:

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

שיטות ציבוריות

player.loadVideoById(id:String, startSeconds:Number = 0):void
טעינה והפעלה של סרטון על סמך מזהה שצוין.
player.cueNewVideo(id:String, startSeconds:Number = 0):void
נטען אך לא מפעיל את הסרטון באופן אוטומטי על סמך המזהה שצוין.
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
הפונקציה מחזירה את המצב הנוכחי של הסרטון שנמצא כרגע ב-cue או נטען.
player.getBytesLoaded():Number
הפונקציה מחזירה את הערך של הבייטים הנוכחיים שנטענו מהסרטון הנוכחי שהוכן או נטען.
player.getBytesTotal():Number
מחזיר את הערך של סך הבייטים שנטענו של הסרטון שסומן/שנטענו כרגע.
player.getCurrentTime():Number
מחזיר את המיקום הנוכחי בזמן של הסרטון שסומן/נטען כרגע.
player.getDuration():Number
הפונקציה מחזירה את משך הזמן הנוכחי של הסרטון שנמצא כרגע ב-cue או נטען.
player.getStartBytes():Number
מחזיר את הבייטים של ההתחלה של הסרטון שסומן/נטען כרגע.
player.setVolume(newVolume:Number):void
הגדרת עוצמת הקול של הסרטון שסומן/נטען כרגע.
player.getVolume():Number
הפונקציה מחזירה את עוצמת הקול הנוכחית של הסרטון שנמצא כרגע בהמתנה או נטען.
player.mute():void
שומר את עוצמת הקול הנוכחית ומשנה את עוצמת הקול של הסרטון שנמצא כרגע ב-cue או נטען ל-0.
player.unmute():void
מחזירה את עוצמת הקול של הסרטון הנוכחי שהוכן או נטען לערך האחרון שנשמר כשהיא מושתקת.
player.getEmbedCode():String
מחזירה את קוד ההטמעה הנוכחי של YouTube לסרטון שהושמע או נטען כרגע.
player.getVideoUrl():String
מחזירה את כתובת ה-URL הנוכחית של הסרטון ב-YouTube של הסרטון הנוכחי שהוכן או נטען.

אירועים

YouTubeLoaderEvent.LOADED
האירוע הזה מופעל אחרי שהטעינה של ה-Chromeless Player מסתיימת בהצלחה והוא מוכן לקבל קריאות לפעולות.
YouTubeLoaderEvent.STATE_CHANGE
האירוע הזה מופעל בכל פעם שהמצב של הנגן משתנה. הכיתה YouTubeLoader מתרגמת את המספרים של JavaScript API לערכי המחרוזות שקשורים אליהם, והכיתה YouTubeLoaderEvent שומרת את האירוע הנוכחי במשתנה שנקרא state. הערכים האפשריים הם: לא התחיל, הסתיים, מופעל, מושהה, אגירת נתונים, סרטון עם קליפ. לאחר הטעינה הראשונה של קובץ ה-SWF, הוא ישדר אירוע שלא הופעל. כאשר הסרטון מסומן ומוכן להפעלה, ישודר אירוע סימון כסרטון.
YouTubeLoaderEvent.IO_ERROR
האירוע מופעל כשמתרחשת שגיאה בנגן. יש שני קודי שגיאה אפשריים: קוד 100 מופיע כשהסרטון המבוקש לא נמצא. המצב הזה מתרחש כשסרטון הוסר (מכל סיבה שהיא) או שסומן כפרטי. קוד 101 משודר כשהסרטון המבוקש לא מאפשר הפעלה בנגנים המוטמעים.

הערות לגבי ההדגמה

למטרות הדגמה, רצינו לכלול את שדות הטופס, הלחצנים וממשק המשתמש המוצג של XHTML מתחת למעטפת ActionScript 3 המוטמעת. כדי לעדכן את קובץ ה-SWF ואת קובץ ה-XHTML בו-זמנית, נאלצנו לכלול שתי שורות קוד בקובץ JavaScript‏ 'youTubeLoader.js' שנמצא ב-'deploy/_assets/js/' (איור 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 באמצעות ספריית העטיפה שפיתחנו לפרויקטים שלנו. הוספת תגובות לחלק גדול מהקוד, כך שקל מאוד לבדוק את הספריות ולשנות את המטרה שלהן. יש ל-AWS כמה מגבלות, ותמיד יש מקום לשיפור, לניתוח מחדש ולשיפורים. אם יש לך שאלות נוספות, אפשר ליצור איתי קשר.

ביוגרפיה של המחבר/ת


Matthew Richmond

למתיו ריצ'מונד יש 14 שנות ניסיון בעיצוב, פיתוח וארכיטקטורה אינטראקטיביים. כשהוא לא בסטודיו, הוא מלמד טכניקות של איור או צילום דיגיטלי ותוכנת ActionScript מתקדמת בבית הספר לאומנויות חזותיות. מתיו הוא שותף מייסד ומעצב ב-choppingblock.com.