Es gibt zwei Dinge mit denen mein jMediaelement Projekt allein nicht beschrieben wäre: HTML5 audio / video einerseits und Player-Script andererseits. Die von jme genutzen HTML5 Media-Elemente sind nur eine Abspieltechnologie von insgesamt dreien. Würde man den HTML5 Teil weglassen und damit lediglich Flash und VLC als Abspieltechnik dienen, hätte jme weiterhin imense Vorteile für Frontendentwickler. Das liegt unter anderem daran, daß jme eben kein reines Player-Script ist.
jme besteht aus 2 Hauptkomponeten:
- einem leichtgewichtigem, kugelsicheren reinen embed-Teil
- der “Vollversion”, welche neben dem embed-Teil, auch die DOM-API und die Markup-API (Controls) enthält
Media-Elemente einbinden schnell und einfach wie ein Bild
In vielen Fällen, in denen ein Entwickler einen Videoplayer einbinden muß, ist kein spezielles Design und kein besonderes Feature verlangt. Es geht schlicht weg darum einen Player zum Abspieln von Videos/Audios zu haben.
Der reine embed-Teil von jme ist daher in einer separaten Version als leichtgewichtiger Helper eingebunden.
Der notwendige HTML-Code ist identisch mit dem HTML5 Code:
<video src="myvideo.webm" poster="mein-poster.jpg" controls="controls"> <!-- Fallback Content --> </video>
Damit dies auch ohne Bugs und mit älteren Browsern funktioniert, kopiert man einfach die mm.embed.min.js aus dem packages Ordner vom jMediaelement-Download zusammen mit der player.swf und – falls man youtube-videos einbinden will – der yt.swf in einen gemeinsamen Ordner.
Danach kann man bei DOM-Ready seine HTML5 Media-Elemente mit jmeEmbed registieren:
$(document).ready(function(){ $('audio, video').jmeEmbed({showFallback: true}); });
Der embed Teil kümmert sich um die Erkennung von Browser- und Plugin-Features, deren Einbindung/Initialisierung, der Normalisierung der HTML5 Mediaelement Attribute sowie der hiermit zusammenhängenden Bugs. Ist die Vollversion von jme eingebunden, wird hierdurch auch die DOM-API initialisiert. Die Vorteile für den Entwickler:
- er hat einen einfachen, intuitiven und semantischen Einbindecode
- Sofern ein Video mit richtigem Container/Codec eingebunden wird, erhöht sich die Zugänglichkeit für bestimmte Endgeräte
- der Entwickler ist nicht gezwungen mehrere Video-Formate anzubieten. Letztendlich können auch nicht HTML5-Formate wie zum Beispiel flv-Dateien oder Youtube-Seiten als Datengrundlage genommen werden.
- Die jeweiligen Browser-, Plugin-Player rendern die Kontrolelemente automatisch, so daß keine weiteren HTML-/CSS-Anpassungen anfallen.
Kurz: Gegenüber der Art wie man derzeit Videos einbindet, kommt man hier mit jme schneller, semantischer und manchmal auch zugänglicher ans Ziel.
HTML ist die Schnittstelle zwischen JavaScript und CSS oder “divide et impera” – Teile und herrsche
Der zweite Teil ist keine reine JavaScript API, sondern gliedert sich in DOM-API und Markup-API auf. Dieser Aufbau ist der Erkenntnis geschuldet, daß JavaScript nur wenig HTML diktieren sollte und HTML unter anderem eine Schnittstelle zwischen einerseits JavaScript und CSS und andererseits zwischen Frontend und Backend darstellt.
Die Erstellung von funktionsfähigen Kontrollelementen ist Aufgabe der Markup-API. Features welche nicht über die Markup-API realisiert sind, können mit Hilfe der DOM-API erledigt werden.
HTML6 Control-Elemente = jme Markup-API/Kontrollklassen
Anstatt, daß durch einen JavaScript-Aufruf ein Haufen unsemantischer HTML-Code um den Player gepackt wird, besteht jme aus kleinen Bausteinen, die einfach zusammengesetzt werden können und so einen individuellen Player ermöglichen. Hierbei besteht als oberstes Prinzip, daß sich die verwendeten Bausteine flexibel in die HTML-/DOM-Welt integrieren laßen müßen.
Stell Dir vor HTML5 ist Schnee von gestern und das W3C würde mit HTML6 einige neue Elemente spezifizieren, welche als Kontrollelemente für das audio- und video-element dienen. Ein Abspiel-/-Pause Button könnte wie folgt aussehen:
<button type="play-pause">play / pause</button>
Das schöne daran, der Browser kümmert sich um Funktionalität und Zugänglichkeit und der Entwickler besitzt die Flexibilität die Kontrollelemente erstens frei zu platzieren und zweitens mit weiterem HTML anzureichen, um Sie dann beispielsweise per CSS besser zu stylen oder um ein gewünschtes Userinterface-Verhalten zu erreichen.
Damit der Browser weiß, mit welchem Mediaelement das jeweilige Kontrollelement verbunden ist, werden die Kontrollelemente gemeinsam mit dem Mediaelement in einem ebenfalls neuen Element mit dem Namen player gewrappt. Das Ergebnis sieht dann wie folgt aus:
<player> <video src="myvideo.webm"></video> <button type="play-pause">play / pause</button> </player>
Die jme Kontrollelement-Bausteine funktionieren hierbei auf ähnliche Weise. Die neuen Kontrollelemente werden durch beliebige valide Elemente mit bestimmten HTML-Klassen symbolisiert und lediglich das Wrapper-Element “player” wird durch einen JavaScript Aufruf ersetzt:
<div class="player-wrapper"> <video src="myvideo.webm" controls="controls"></video> <button class="play-pause">play / pause</button> </div>
Das jQuery-Plugin ‘jmeControl’, welches auf dem wrapper-Element aufgerufen wird, registriert hierbei sozusagen die einzelnen Kontrolelemente und ruft bei Bedarf, die embed-Methode auf. Genau wie bei der jmeEmbed-Methode muß grundsätzlich keine weitere Konfiguration vorgenommen werden.
$('div.player-wrapper').jmeControl();
Werden die nativen Kontrollelemente nicht angezeigt, wird der Flashplayer – sofern nicht ausdrücklich anders konfiguriert – automatisch in den wmode=transparent Zustand versetzt, um auch schöne Overlay-Kontrollelemente oder Overlay-Logos über dem Video erstellen zu können.
Man kann selbstverständlich auch mehrere Kontrollelemente unterbringen:
<div class="player-wrapper"> <video src="myvideo.webm" controls="controls"></video> <button class="play-pause">play / pause</button> <span class="current-time">--:--</span> </div>
jme kümmert sich hierbei nicht nur um die Funktionalität und rendert die jeweils aktuelle Zeit in das span-Element und erstellt ein Play-Pause-Toggle Verhalten aus dem button-element, sondern auch um die Zugänglichkeit. Insbesondere dann, wenn zum einfacheren Stylen statt dem button-Element ein span-Element genommen wird, fügt jme die gewollte Semantik per WAI-ARIA ein. Folgendes geschriebenes HTML ….
<div class="player-wrapper"> <video src="myvideo.webm" controls="controls"></video> <span class="play-pause">play / pause</span> <span class="current-time">--:--</span> </div>
…wird durch jme in folgendes HTML umgewandelt:
<div class="player-wrapper"> <video src="myvideo.webm"></video> <span role="button" tabindex="0" class="play-pause">play / pause</span> <span role="timer" class="current-time">--:--</span> </div>
Neben allgemein üblichen Video/Audio Kontroll-Elementen bietet jme über Plugins auch Verhaltensklassen für eine Playliste und Captions an.
Die Tatsache, daß wir eine Markup-API verwenden, die nicht von JavaScript diktiert wird, heißt aber nicht, daß wir nun alle möglichen Kontroll-/Verhaltensklassen auswendig lernen und wieder und wieder ins HTML schreiben müßen. jme bietet im utils-Ordner das jmeEmbedControls-Plugin an, welches nichts anderes macht, als einen Haufen Kontrollelemente in das Element, auf dem es aufgerufen wurde, einzufügen, um dann hierauf die jmeControl-Methode auszuführen. Diese Methode ist sozusagen das Schnellstarter-Kit für jme. Er ist bewußt ausgelagert, um jedem Webentwickler eine projektspezifische Anpassung zu ermöglichen.
einheitliche DOM-API statt vereinheitlichte JavaScript-API
Die vereinheitlichte JavaScript-API ist bei jme bewußt eine DOM-API, da nur so sich Mediaelemente, sei es nun HTML5, Flash oder VLC, in den normalen Workflow eines Frontendentwicklers integrieren können.
Ein Beispiel: JW-Player for HTML5 ist das erste HTML5 Player-Script, welches eine dokumentierte API vorweisen kann. Und obwohl jQuery, also ein klassischer DOM-Wrapper, als JavaScript Grundlage gewählt wurde, wurde keine DOM-API implementiert. Um einen Player zu scripten, sieht der Code wie folgt aus:
$.jwplayer().play();
Laut Dokumentation wird nun immer auf dem ersten eingebundenen Mediaelement die Methode play aufgerufen, möchte man nun jedoch auf einem anderen Mediaelement Methoden ausführen, muß man bereits zum Zeitpunkt der Initialisierung die Referenz auf dieses Objekt speichern und sicherstellen, daß alle Module die hiermit interagieren müßen an diese Referenz kommen:
//holen der Referenz auf ein bestimmtes Video bei der Initialisierung var player = $('#stage video').jwplayer({ flashplayer:'/static/files/player.swf', skin:'/static/files/five.xml' }); //initialisieren aller anderen videos $('video').not('#stage video').jwplayer({ flashplayer:'/static/files/player.swf', skin:'/static/files/five.xml' }); //arbeiten mit der gespeicherten Referenz //irgendwo ganz anders im script player.play();
Mit einer DOM-API sieht die Sache dagegen anders aus, denn die API ist Teil des DOMs und kann wie jede DOM-API mit der jQuery-Selektorengine selektiert werden.:
$('#stage video').play();
Ebenso wie man bei anderen DOM-Elementen auf Events horcht, Methoden chained etc., funktioniert dies auch bei jme. Das video bzw. das audio Element bleiben hierbei immer das zentrale API Element, gleichgültig ob tatsächlich HTML5 oder eben ein Plugin zur Anzeige der Mediainahlte genutzt wird.
$('video').bind('ended', function(){ $(this).attr('autoplay', true).loadSrc('my-video2.webm'); });
Kurz: nur so kann Scripten Spaß machen.
Fazit
Merkwürdig aber wahr: jme stellt in vielen Punkten einige Weltrekorde auf:
- jme ist das erste audio/video Script mit Fallback, welches eine dokumentierte DOM-API besitzt (das werden garantiert einige nachmachen, da es sooo nahe liegt)
- jme ist das erste audio/video Script, welches eine Markup-API für Kontroll- und Zustandselemente verwendet
- jme ist – und das ist wirklich traurig – das erste Script seiner Art, welches semantischen Code erlaubt/nutzt (notfalls mit WAI-ARIA forciert)
Oder anders gesagt: jme versucht nicht aus HTML5 Flash zu machen, sondern aus Flash HTML5.