המאמר הזה נכתב ונשלח על ידי מפתח חיצוני. צוות הכלים וה-API של YouTube מודה למת'יו ריצ'מונד על הזמן והמומחיות שלו.
מת'יו ריצ'מונד, The Choping Block, Inc.
אוקטובר 2008
מבוא
במאמר זה אציג ואתאר בקצרה את הכלי ActionScript 3.0 Wrapper עבור נגן YouTube ללא Chrome. wrapper משתמש במחלקה ExternalInterface וב-ActionScript של YouTube.
כלי YouTube Player ו-Chromeless Player של Google מאפשרים למעצבים/מפתחים לשלב במהירות ובקלות את היכולות של YouTube בפרויקטים המקוונים שלהם. הגישה הזו מתאימה במיוחד לפרויקטים קטנים בתקציבים קבועים שלא מאפשרים לארח סרטונים, וגם לפרויקטים בקנה מידה גדול ללקוחות שרוצים חוויה מותאמת אישית של משתמש הקצה, בלי להתרחק מהקהל שלהם ב-YouYube.
איור 1: צילום מסך של מעטפת ActionScript 3.0
ממשקי ה-API של Flash והנגנים המוטמעים של YouTube נכתבים ופועלים היטב עם ActionScript 2.0. עם זאת, אם הפרויקט שלך הוא ActionScript 3.0, שילוב חלק הופך למורכב יותר. אמנם ניתן לטעון בקלות את נגני ActionScript 2.0 לתוך Swf של ActionScript 3.0, אך אין לך אפשרות ליצור קשר ישיר או להעביר קריאות פונקציונליות אל הנגן שנטען. שיטה זו מורכבת יותר, מכיוון שקובץ ה-swf שמגיע מהשרתים שלך ב-YourTube טוען סרטון לעצמו. wrapper צריך להיות מודע לעובדה הזו ולהגיב בהתאם. למזלנו, שפת ActionScript מכילה שתי דרכים לעקוף את החלקים המנותקים והמנותקים, מחלקת LocalConnection או מחלקת ממשק ה-ExternalInterface. הדגמה זו תתמקד באחרונה מפני שהממשק החיצוני פועל בצורה חלקה עם ממשק ה-API של JavaScript המתועד היטב, ולכן פועל היטב עם כל דבר אחר בדף ה-XHTML.
מקורות מידע חשובים
לפני שנתחיל, ריכזנו כאן רשימה של מקורות מידע וקבצים שקשורים לנושא. נושאים רבים במאמר זה מפורטים בפירוט בקישורים שבהמשך.
- לצפות ב-ActionScript 3.0 Wrapper ובהורדת קובצי מקור
- חומר עזר רשמי של YouTube JavaScript API API
- תיעוד לכיתה של Adobe ExternalInterface
- הטמעה של פלאש JavaScript ב-SWFObject
חפירות
סקירה כללית של מעטפת עטיפה
איור 3: קובץ JavaScript
איור 2: קבצים של ActionScript Class
Wrapper של קובץ ActionScript 3.0 מורכב בעיקר משני חלקים המחוברים זה לזה, קובצי המחלקה ActionScript 3.0 הממוקמים ב- src/chopingblock/video/ (איור 2) וקובץ ה-JavaScript 'youTubeLoader.js' הממוקם ב-deploy/_assets/js/ (איור 3). קובץ המקור מסוג Flash/Flex ייצור מופע של המחלקה ActionScripter של ActionScript; דף ה-XHTML שלך מטמיע את קובץ ה-Flash ורשום אותו בפונקציות בתוך קובץ ה-JavaScript של YouTube. חשוב להבין שכל מה ש-YouTubeLoader מבצע בקובץ ה-Flash נשלט על ידי פונקציות ה-JavaScript.
מאחר שכל הפונקציונליות בתוך Flash נשלטת באמצעות ממשק ה-API של JavaScript, לא תוכל לטעון תוכן של YouTube בנגן 'בודק סרטים' של Flash. הוא יפעל רק כאשר הוא מוטמע בדף XHTML ומחובר כראוי לפונקציות JavaScript של YouTube.
הערה: כדי לבדוק כל אחת מהקריאות האלה, הקובץ צריך להיות מופעל בשרת אינטרנט או לשנות את הגדרות האבטחה של ה-Flash Player, משום שנגן ה-Flash מגביל את הקריאות בין קבצים מקומיים לאינטרנט.
יצירת אובייקט ב-YouTubeLoader
לפני שתוכל ליצור מופע של אובייקט YouTubeLoader בפרויקט Flash/Flex שלך, עליך לוודא שהחבילה (התיקייה) של הקבצים הנדרשים נמצאת באותה ספרייה כמו הפרויקט שלך (ראה איור 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 וחיבור JavaScript של YouTubeLoader
לא תוכל לטעון בהצלחה תוכן מ-YouTube עד שקובץ ה-swf יוטמע בקובץ XHTML ויקושר ל-JavaScript של YouTubeLoader. מומלץ להשתמש ב-SWFObject כדי להטמיע נגנים שניגשים אליהם באמצעות ממשק API של JavaScript. כך תוכל לזהות את גרסת Flash Player של משתמש הקצה (ממשק ה-API של JavaScript מחייב 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 אל ממשק ה-API של JavaScript של YouTube.
<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 שמכיל, מכיוון שה-Chromeless Player מתארח בדומיין שונה מדף ה-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 הרגילה של YouTube SWF, כדי לאפשר קריאות ל-JavaScript API.replaceElemIdStr
– זהו מזהה ה-HTML DIV שיש להחליף בתוכן ההטמעה. בדוגמה שלמעלה, הערך הואytapiplayer
.widthStr
– רוחב הנגן.heightStr
– גובה השחקן.swfVersionStr
– הגרסה המינימלית הנדרשת כדי שהמשתמש יראה את התוכן. במקרה זה, יש צורך בגרסה 8 ואילך. אם למשתמש אין 8 או יותר, הוא יראה את שורת הטקסט המוגדרת כברירת מחדל ב-HTML DIV.xiSwfUrlStr
- (אופציונלי) מציין את כתובת האתר של ה-SWF של ההתקנה האקספרס. לא בשימוש בדוגמה זו.flashVarsObj
- (אופציונלי) מציין את משתני FlashV בזוגות של שם:ערך. לא בשימוש בדוגמה זו.parObj
– (אופציונלי) הפרמטרים לאובייקט ההטמעה. במקרה הזה, הגדרנו אתallowScriptAccess
.AttObj
– (אופציונלי) המאפיינים של אובייקט ההטמעה. במקרה הזה, הגדרנו את המזהה כ-myytplayer
.
לקבלת מידע נוסף, ניתן לעיין בתיעוד של SWFObject.
SWFID ≡
תשמור הפניה למזהה של אובייקט ההטמעה לצורך שימוש ב-JavaScript API. עליך להשתמש באותו מזהה של אובייקט ההטמעה שסיפקת ב-swf.
SWFID ≡ "youtubewrapper"
בשלב הזה אתם אמורים להיות מסוגלים לבדוק את הפרויקט שלכם. על האובייקט של YouTubeLoader לטעון את נגן Chromeless ולהפעיל את ה-handler של אירועים מסוג YouTubeLoaderEvent.LOADED
. עכשיו אנחנו מוכנים לשלוח בקשת וידאו ולקיים אינטראקציה עם האובייקט של YouTubeLoader.
אינטראקציה עם השחקן
הגישה הזו ליצירת מעטפת 3.0 של ActionScript ל-Chromeless Player מבוססת על הסיווג 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...
מאחר שהמטרה הסופית של Wrapper של ActionScript 3.0 עבור ה-Chromeless Player היא להציע אינטראקציה חלקה עם ממשק ה-API של YouTube מתוך פרויקט Flash/Flex של ActionScript 3.0, הוספנו את אותן שיטות ציבוריות בדיוק לקובץ המחלקה 'YouTubeLoader.as' הממוקם ב- src/choppblock/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 כדי לקרוא לפונקציה המתאימה בתוך ממשק ה-API של JavaScript.
בקשת סרטון
עכשיו אפשר לבקש סרטון מתוך קובץ ה-ActionScript 3.0 שלך על ידי קריאה לפונקציות באמצעות ההפניה לשחקן. לדוגמה, אם ברצונך להפעיל את הסרטון כאשר משתמש לוחץ על לחצן, עליך להוסיף ללחצן 'EventEvent.Click' האזנה לאירוע. תוכל לעשות זאת כך:
// assuming your button was called 'myButton' myButton.addEventListener(MouseEvent.CLICK, youtubeLoadVideoHandler);
וליצור שיטת handler של אירועים שתטפל בבקשה. תוכל לעשות זאת כך:
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 ניתן פשוט לקרוא לשיטות באמצעות הפניה של הנגן. כאן מופיעה רשימה מלאה של השיטות הזמינות.
הרשמה לאירועים
נרשמים לאירועים על ידי הוספת event listener לקובץ העזר של הנגן. לדוגמה, כדי לקבל הודעה כשהמצב של השחקן משתנה, יש להוסיף event listener של YouTubeLoaderEvent.STATE_CHANGE
. תוכל לעשות זאת כך:
// assuming that '_youTubeLoader' is a reference to your YouTubeLoader object _youTubeLoader.addEventListener(YouTubeLoaderEvent.STATE_CHANGE, youTubePlayerStateChangeHandler);
וליצור שיטת handler של אירועים שתטפל בבקשה. תוכל לעשות זאת כך:
private function youTubePlayerStateChangeHandler (event:YouTubeLoaderEvent):void{ //trace("YouTubeIntegrationDemo: youTubePlayerStateChangeHandler"); _stateField.text = event.state; };
פעולות זמינות
כדי להפעיל את שיטות ה-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
- מחזיר את המצב הנוכחי של הסרטון שנטען/נטען כרגע.
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
- מחזיר את קוד ההטמעה הנוכחי של הסרטון הנוכחי שנטען או שנטענה.
player.getVideoUrl():String
- מחזיר את כתובת ה-URL הנוכחית של הסרטון ב-YouTube של הסרטון שנלווה/נטען כרגע.
אירועים
YouTubeLoaderEvent.LOADED
- הפעלה ברגע שהטעינה של הנגן ללא Chrome הושלמה, והיא מוכנה לקבל שיחות תפעול.
YouTubeLoaderEvent.STATE_CHANGE
- מופעל בכל פעם שמצב הנגן משתנה. מחלקה של YouTubeLoader מתרגמת את המספרים ב-JavaScript API לערכי המחרוזת הקשורים אליהם, במחלקה YouTubeLoaderEvent מאוחסן האירוע הנוכחי במשתנה שנקרא
state
. ערכים אפשריים לא התחילו, הסתיימו, הופעלו, הושהו, בתהליך אגירת נתונים, הסרטון הופעל. בפעם הראשונה טעינת ה-SWF תשודר, אירוע שלא התחיל. כאשר סרטון נדלק ומוכן להפעלה, הוא ישודר אירוע. YouTubeLoaderEvent.IO_ERROR
- מופעל כשמתרחשת שגיאה בנגן. קיימים שני קודי שגיאה אפשריים: 100 משודרת כאשר הסרטון המבוקש לא נמצא. דבר זה קורה כאשר סרטון הוסר (מכל סיבה שהיא), או שהוא סומן כפרטי. 101 משודר כאשר הסרטון המבוקש אינו מאפשר הפעלה בנגנים המוטמעים.
הערות להדגמה
למטרות הדגמה, רצינו לכלול את השדות, הלחצנים וממשק המשתמש של תצוגת XHTML מתחת ל-wrapScript המוטמע של 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. קבצים אלה מופצים בתקווה שהם יהיו שימושיים, ללא כל התחייבות.
סיכום
המאמר הזה מספק סקירה וקובצי מקור עם סקירה מקיפה של פתרון פשוט ואמין יחסית, לשילוב ממשק ה-API של YouTube ונגנים מוטמעים בסביבות ActionScript 3, באמצעות ספריית wrapper שפיתחנו לפרויקטים שלנו. מכיוון שהוספתי חלק גדול מהקוד, באופן אידיאלי יהיה די ברור לסייר בספריות ולשנות את הייעוד שלהן. היא אינה מוגבלת ותמיד יש מקום לשיפור, להטמעה מחדש ולשיפור. אם יש לך רעיונות בנושא הזה, אפשר ליצור איתי קשר.
ביוגרפיה של המחבר
למתיו ריצ'מונד יש 14 שנות ניסיון בעיצוב, בארכיטקטורה ובפיתוח אינטראקטיביים. כשהוא לא נמצא בסטודיו, הוא יכול ללמוד טכניקות של איור/צילום דיגיטלי ו-ActionScript מתקדם בבית הספר לאמנויות חזותיות. מת'יו הוא מייסד שותף ומעצב בכתובת chopingblock.com.