ActionScript 3.0-Wrapper für Chromeless Player

Dieser Artikel wurde von einem externen Entwickler verfasst und eingereicht. Das YouTube-Team für APIs und Tools dankt Matthew Richmond für seine Zeit und sein Know-how.


Matthew Richmond, The Chopping Block, Inc.
Oktober 2008

Einführung

In diesem Artikel stelle ich einen zuverlässigen ActionScript 3.0-Wrapper für den Chromeless YouTube-Player vor und beschreibe ihn kurz. Der Wrapper nutzt die ExternalInterface-Klasse von ActionScript und die JavaScript API von YouTube.

Mit den YouTube-Player-Tools und dem Chromeless Player von Google können Designer und Entwickler die Funktionen von YouTube schnell und einfach in ihre Onlineprojekte einbinden. Dieser Ansatz eignet sich sowohl für kleine Projekte mit einem festen Budget, bei denen kein Videohosting möglich ist, als auch für große Projekte für Kunden, die eine benutzerdefinierte Endnutzererfahrung wünschen, ohne sich von ihrer YouTube-Zielgruppe zu distanzieren.

Screenshot des ActionScript 3.0-Wrappers
Abbildung 1: Screenshot des ActionScript 3.0-Wrappers

Die Flash API und die eingebetteten Player von YouTube sind in ActionScript 2.0 geschrieben und funktionieren damit recht gut. Wenn dein Projekt jedoch ActionScript 3.0 verwendet, wird die nahtlose Integration etwas komplexer. Es ist zwar einfach, ActionScript 2.0-Player in ein ActionScript 3.0-SWF-Objekt zu laden, aber Sie können nicht direkt mit dem geladenen Player kommunizieren oder Funktionsaufrufe an ihn weitergeben. Das Ganze wird noch komplizierter, da die SWF-Datei von den YouTube-Servern ein Video in sich selbst lädt. Unser Wrapper muss sich dieser Tatsache bewusst sein und entsprechend reagieren. Glücklicherweise bietet die ActionScript-Sprache zwei plausible Problemumgehungen, um diese verschachtelten, aber getrennten Teile wieder zu verbinden: die LocalConnection-Klasse oder die ExternalInterface-Klasse. In dieser Demo liegt der Schwerpunkt auf Letzterem, da das ExternalInterface nahtlos mit der gut dokumentierten JavaScript API funktioniert und daher gut mit allem anderen auf der XHTML-Seite zusammenspielt.

Wichtige Ressourcen

Bevor wir beginnen, finden Sie hier eine Liste der zugehörigen Ressourcen und Dateien, die Ihnen zur Verfügung stehen. Viele der in diesem Artikel behandelten Themen werden über die nachfolgenden Links ausführlicher beschrieben.

Eintauchen

Wrapper-Demo – Übersicht

ActionScript-Klassendateien
Abbildung 3: JavaScript-Datei
ActionScript-Klassendateien
Abbildung 2: ActionScript-Klassendateien

Der ActionScript 3.0-Wrapper besteht im Wesentlichen aus zwei miteinander verbundenen Teilen: den ActionScript 3.0-Klassendateien in src/choppingblock/video/ (Abbildung 2) und der JavaScript-Datei „youTubeLoader.js“ in deploy/_assets/js/ (Abbildung 3). In deiner Flash-/Flex-Quelldatei wird eine Instanz der ActionScript-Klasse „YouTubeLoader“ erstellt. Die XHTML-Seite bettet die Flash-Datei ein und registriert sie mit den Funktionen in der JavaScript-Datei „YouTubeLoader“. Wichtig ist, dass Sie verstehen, dass alles, was YouTubeLoader in der Flash-Datei ausführt, über die JavaScript-Funktionen gesteuert wird.

Da alle Funktionen in Flash über das JavaScript-API gesteuert werden, können Sie KEINE YouTube-Inhalte in den "Testfilm"-Player von Flash laden. Es funktioniert nur, wenn es in eine XHTML-Seite eingebettet und ordnungsgemäß mit den YouTubeLoader-JavaScript-Funktionen verbunden ist.

Hinweis: Um einen dieser Aufrufe zu testen, muss deine Datei auf einem Webserver ausgeführt werden oder du musst die Sicherheitseinstellungen deines Flash Players ändern, da der Flash Player Aufrufe zwischen lokalen Dateien und dem Internet einschränkt.

YouTubeLoader-Objekt erstellen

Bevor du eine Instanz des YouTubeLoader-Objekts in deinem Flash-/Flex-Projekt erstellen kannst, musst du zuerst dafür sorgen, dass sich das Paket (Ordner) mit den erforderlichen Dateien im selben Verzeichnis wie dein Projekt befindet (siehe Abbildung 2) oder im Classpath deines Projekts definiert ist. Anschließend können Sie die Paketdateien importieren:

import choppingblock.video.*;

Dadurch erhält Ihre ActionScript-Datei Zugriff auf die Klassen "YouTubeLoader.as" und "YouTubeLoaderEvent.as". Jetzt kannst du eine Instanz der Klasse „YouTubeLoader“ und die erforderlichen Ereignis-Listener erstellen:

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

Wenn die JavaScript-Datei vorhanden und richtig verbunden ist, sollte youTubePlayerLoadedHandler erfolgreich aufgerufen werden und wir können Anfragen senden.

SWF-Datei einbetten und JavaScript-Code für YouTube-Videos verbinden

Sie können Inhalte von YouTube erst dann laden, wenn Ihre SWF-Datei in eine XHTML-Datei eingebettet und mit dem JavaScript-Code „youTubeLoader“ verbunden ist. Wir empfehlen zur Einbettung aller Player, auf die über die JavaScript API zugegriffen wird, die Verwendung von SWFObject. So kannst du die Flash Player-Version des Endnutzers erkennen (für die JavaScript API ist Flash Player 8 oder höher erforderlich). Außerdem wird das Kästchen „Klicken, um dieses Steuerelement zu aktivieren“ entfernt, wenn du den Player im Internet Explorer aufrufst.

Im <head>-Teil deiner XHTML-Datei verbindest du die Dateien „swfobject“ und „youTubeLoader“:

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

Im Folgenden finden Sie ein Beispiel für die Verwendung von SwFObject zur Einbettung Ihrer ActionScript 3.0-GIF-Datei mit aktiviertem JavaScript-API und zur anschließenden Übergabe einer Referenz zu Ihrer SWF-Datei an das 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>

Der Parameter allowScriptAccess im Code ist erforderlich, damit der Player-SWF Funktionen auf der enthaltenen HTML-Seite aufrufen kann, da der Chromeless Player auf einer anderen Domain als die XHTML-Seite gehostet wird.

Das einzige Attribut, das wir übergeben, ist die ID des eingebetteten Objekts – in diesem Fall „youtubewrapper“. Mit dieser ID ruft die Datei youTubeLoader.js mithilfe von getElementById() eine Referenz an den Player ab.

swfobject.embedSWF lädt den Player von YouTube und bettet ihn in deine Seite ein.

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

  • swfUrlStr: Dies ist die URL der SWF-Datei. Beachte, dass wir die Parameter enablejsapi und playerapiid an die normale YouTube-SWF-URL angehängt haben, um JavaScript API-Aufrufe zu ermöglichen.
  • replaceElemIdStr – Dies ist die HTML DIV-ID, die mit dem eingebetteten Inhalt ersetzt werden soll. Im obigen Beispiel ist es ytapiplayer.
  • widthStr – Breite des Players.
  • heightStr – Höhe des Spielers.
  • swfVersionStr: Die Mindestversion, die der Nutzer benötigt, um die Inhalte zu sehen. In unserem Fall handelt es sich dabei um die Version 8. Sollte der Nutzer diese Voraussetzung nicht erfüllen, wird die Standardtextzeile im HTML DIV angezeigt.
  • xiSwfUrlStr – (Optional) Gibt die URL des SWF-Objekts für die Expressinstallation an. Wird in diesem Beispiel nicht verwendet.
  • flashVarsObj – Optional. Gibt FlashVars in Namen/Wert-Paaren an. Wird in diesem Beispiel nicht verwendet.
  • parObj (optional): Die Parameter für das eingebettete Objekt. In diesem Fall haben wir allowScriptAccess festgelegt.
  • AttObj – (Optional) Die Attribute für das eingebettete Objekt. In diesem Fall haben wir die ID auf myytplayer festgelegt.

Nähere Informationen findest du in der SWFObject-Dokumentation.

SWFID ≡ speichert einen Verweis auf die ID des eingebetteten Objekts, das von der JavaScript API verwendet werden soll. Sie müssen dieselbe ID für das eingebettete Objekt verwenden, die Sie dem SWF-Objekt zugewiesen haben.

SWFID ≡ "youtubewrapper"

Jetzt sollten Sie Ihr Projekt erfolgreich testen können. Das YouTubeLoader-Objekt sollte den Chromeless-Player laden und der YouTubeLoaderEvent.LOADED-Ereignis-Handler sollte erfolgreich aufgerufen werden. Jetzt können wir eine Videoanfrage stellen und mit dem YouTubeLoader-Objekt interagieren.

Mit dem Spieler interagieren

Da bei diesem Ansatz zum Erstellen eines ActionScript 3.0-Wrappers für den Chromeless-Player die ExternalInterface-Klasse von ActionScript verwendet wird, können wir jetzt jeden der Vorgänge in der YouTube JavaScript Player API verwenden, um den geladenen Player zu steuern. Wenn Sie sich die JavaScript-Datei "youTubeLoader.js" in deploy/_assets/js/ ansehen (Abbildung 3), werden Sie feststellen, dass sie die meisten verfügbaren Funktionen enthält. Jede Funktionsoperation prüft zuerst mit der Funktion checkObj, ob die Variable SWFID richtig festgelegt wurde, bevor sie ausgeführt wird.

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

Da das Endziel unseres ActionScript 3.0-Wrappers für den Chromeless-Player darin besteht, eine nahtlose Interaktion mit der YouTube API innerhalb eines ActionScript 3.0-Flash-/Flex-Projekts zu ermöglichen, haben wir der Klassendatei „YouTubeLoader.as“ im Verzeichnis „src/choppingblock/video/“ (Abbildung 2) genau dieselben öffentlichen Methoden hinzugefügt. Das bedeutet, dass du genau dieselben Vorgänge direkt im YouTubeLoader-Objekt in Flash/Flex aufrufen kannst. In der Kursdatei finden Sie Folgendes:

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

Die ActionScript-Methoden verwenden die ExternalInterface-Klasse, um einfach die entsprechende Funktion innerhalb der JavaScript API aufzurufen.

Video anfragen

Du kannst jetzt ein Video direkt in deiner ActionScript 3.0-Datei anfordern, indem du Funktionen mit der Playerreferenz aufrufst. Wenn Sie beispielsweise das Video wiedergeben möchten, wenn ein Nutzer auf eine Schaltfläche klickt, fügen Sie Ihrer Schaltfläche einen MouseEvent.CLICK-Ereignis-Listener hinzu. Ein Beispiel:

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

Erstellen Sie eine Event-Handler-Methode, um die Anfrage zu verarbeiten. Ein Beispiel:

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

Außerhalb Ihrer Flash-/Flex-Datei können Sie optional ein Video anfordern, indem Sie die entsprechende JavaScript-Funktion direkt aufrufen. Ein Beispiel:

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

Zusätzliche Aufrufe

Zusätzliche Aufrufe funktionieren genau wie beim Anfordern eines Videos. In ActionScript 3 kannst du Methoden einfach über die Playerreferenz aufrufen. Eine vollständige Liste der verfügbaren Methoden finden Sie unten.

Abonnieren von Ereignissen

Du kannst Ereignisse abonnieren, indem du der Playerreferenz einen Ereignis-Listener hinzufügst. Um beispielsweise benachrichtigt zu werden, wenn sich der Player-Status ändert, kannst du einen Ereignis-Listener für YouTubeLoaderEvent.STATE_CHANGE hinzufügen. Ein Beispiel:

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

Und erstellen Sie eine Ereignis-Handler-Methode, um die Anfrage zu verarbeiten. Ein Beispiel:


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

Verfügbare Vorgänge

Damit du die Methoden der YouTubePlayer API aufrufen kannst, musst du zuerst in deiner ActionScript-Datei eine Instanz der Klasse „YouTubePlayer“ erstellen und einen Verweis auf das YouTubePlayer-Objekt speichern, das du steuern möchtest. Dazu kannst du Folgendes aufrufen:

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

Public Methods

player.loadVideoById(id:String, startSeconds:Number = 0):void
Ladet und spielt ein Video anhand der angegebenen ID ab.
player.cueNewVideo(id:String, startSeconds:Number = 0):void
Das Video wird anhand der angegebenen ID geladen, aber nicht automatisch wiedergegeben.
player.clearVideo():void
Löst das aktuell cued/geladene Video auf.
player.setSize(w:Number, h:Number):void
Legt die Größe der YouTubePlayer-Instanz fest.
player.play():void
Spielt das aktuell cued/geladene Video ab.
player.pause():void
Pausiert das aktuell angesagte/geladene Video.
player.stop():void
Stoppt das derzeit positionierte/geladene Video.
player.seekTo(seconds:Number):void
Springt im aktuell angegebenen/geladenen Video zur angegebenen Zeit.
player.getPlayerState():String
Gibt den aktuellen Status des aktuell angegebenen/geladenen Videos zurück.
player.getBytesLoaded():Number
Gibt den Wert der aktuell geladenen Bytes des aktuell angegebenen/geladenen Videos zurück.
player.getBytesTotal():Number
Gibt die Gesamtzahl der geladenen Bytes des aktuell angegebenen/geladenen Videos zurück.
player.getCurrentTime():Number
Gibt die aktuelle Zeitposition des aktuell positionierten/geladenen Videos zurück.
player.getDuration():Number
Gibt die aktuelle Dauer des aktuell angegebenen/geladenen Videos zurück.
player.getStartBytes():Number
Gibt die Startbyte des aktuell positionierten/geladenen Videos zurück.
player.setVolume(newVolume:Number):void
Legt die Lautstärke des aktuell angesagten/geladenen Videos fest.
player.getVolume():Number
Gibt die aktuelle Lautstärke des aktuell positionierten/geladenen Videos zurück.
player.mute():void
Speichert die aktuelle Lautstärke und ändert die Lautstärke des aktuell angesagten/geladenen Videos auf 0.
player.unmute():void
Setzt die Lautstärke des aktuell positionierten/geladenen Videos auf den zuletzt gespeicherten Wert zurück, wenn das Video stummgeschaltet ist.
player.getEmbedCode():String
Gibt den aktuellen YouTube-Embed-Code des aktuell angespielten/geladenen Videos zurück.
player.getVideoUrl():String
Die aktuelle YouTube-Video-URL des aktuell angegebenen/geladenen Videos.

Ereignisse

YouTubeLoaderEvent.LOADED
Wird ausgelöst, sobald der Chromeless-Player geladen wurde und bereit ist, Vorgangsaufrufe zu akzeptieren.
YouTubeLoaderEvent.STATE_CHANGE
Wird immer dann ausgelöst, wenn sich der Status des Players ändert. Die YouTubeLoader-Klasse übersetzt die JavaScript API-Zahlen in die zugehörigen Stringwerte. Die YouTubeLoaderEvent-Klasse speichert das aktuelle Ereignis in einer Variablen namens state. Mögliche Werte sind „nicht gestartet“, „beendet“, „wird wiedergegeben“, „angehalten“, „puffert“, „Video wird angespielt“. Wenn die Datei zum ersten Mal geladen wird, sendet sie ein Ereignis, das nicht gestartet wurde. Wenn das Video angetippt und zur Wiedergabe bereit ist, wird ein Ereignis für ein angetipptes Video gesendet.
YouTubeLoaderEvent.IO_ERROR
Wird ausgelöst, wenn ein Fehler im Player auftritt Es sind zwei Fehlercodes möglich: 100 wird gesendet, wenn das angeforderte Video nicht gefunden wird. Das ist der Fall, wenn ein Video aus irgendeinem Grund entfernt oder als privat gekennzeichnet wurde. 101 wird gesendet, wenn das angeforderte Video die Wiedergabe in den eingebetteten Playern nicht zulässt.

Anmerkungen zur Demo

Zu Demonstrationszwecken wollten wir die XHTML-Formularfelder, Schaltflächen und die Anzeigeoberfläche unter dem eingebetteten ActionScript 3-Wrapper einfügen. Damit die SWF-Datei UND die XHTML-Datei gleichzeitig aktualisiert werden, mussten wir zwei Codezeilen in die JavaScript-Datei „youTubeLoader.js“ im Verzeichnis „deploy/_assets/js/“ einfügen (Abbildung 3). Die folgenden beiden Zeilen [69, 79] sollten Sie entfernen, wenn Sie diese Datei in Ihr Projekt integrieren:

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

Die Demodatei und die enthaltenen ActionScript-Bibliotheken sind kostenlose Software. Sie können sie unter den Bedingungen der GNU Lesser General Public License weitergeben und/oder modifizieren. Wir versenden diese Dateien in der Hoffnung, dass sie nützlich sind, jedoch ohne Gewährleistung.

Fazit

Dieser Artikel, die Demo und die Quelldateien sollten Ihnen einen soliden Überblick über eine relativ einfache und zuverlässige Lösung zur Einbindung der YouTube API und eingebetteter Player in ActionScript 3-Umgebungen mithilfe der Wrapper-Bibliothek geben, die wir für unsere eigenen Projekte entwickelt haben. Da ich einen Großteil des Codes kommentiert habe, ist es idealerweise recht einfach, die Bibliotheken zu erkunden und wiederzuverwenden. Es hat aber auch seine Grenzen und es gibt immer Verbesserungsmöglichkeiten, Refactoring und Optimierungen. Bei Fragen kannst du dich jederzeit gern an mich wenden.

Biografie des Autors


Matthew Richmond

Matthew Richmond blickt auf 14 Jahre Erfahrung im Bereich interaktives Design, Entwicklung und Architektur zurück. Wenn er nicht im Studio ist, unterrichtet er an der School of Visual Arts digitale Illustrations-/Fotografietechniken und fortgeschrittenes ActionScript. Matthew ist Mitbegründer und Designer bei choppingblock.com.