html5 video schlauer einbinden

Mit der Einfuehrung der <video>-Tag in HTML5 und Mozillas im vergangenen Monat eingefuehrter Unterstuetzung fuer den MP4-Container mit Ciscos freier h264-Codierung scheint endlich die Zeit der Browserweichen und mehrfach kodierter Filme vorbei. Ganz zu schweigen davon, dass sich die Notwendigkeit von Flash als Kruecke fuers Gucken von Videos damit erledigt hat. Einfach einen Film im Browser schauen, ohne erst Plugins installieren/aktivieren zu muessen. Traumhaft. Mancher wird sich vielleicht schon gar nicht mehr erinnern, dass es frueher einen ganzen Zoo propritaerer Addons dafuer brauchte. RealPlayer, Windows MediaPlayer, Quicktime… nein, was musste sich der Filmfreund doch alles auf den PC schaufeln?

diverse Player unter Windows 98

Ein Blick auf die Technik des vergangenen Jahrtausends: Video-Player-Wildwuchs

Seit dem Flash-Player mit seiner Unterstuetzung fuers MP4-Format gab es keine Notwendigkeit mehr, verschiedene Formate auf den Server zu packen. Andererseits ist Flash natuerlich auch soeine Seuche fuer sich. Doch weil sich die Webdesigner ueber Jahre so schoen daran gewoehnt haben, mittels JavaScript immer den „richtigen“ Player anzubieten, setzen sie diese Unsitte leider auch in Zeiten des <video>-Tags in HTML5 noch fort 🙁 Bloed nur, dass JavaScript als clientseitige Sprache nicht wirklich zuverlaessig ist. Noch bloeder, dass es aus gutem Grund in vielen Browsern deaktivert oder sogar vorher schon an Firewalls/Proxys unschaedlich gemacht wird. Schliesslich kann eine gute Website mit HTML und CSS locker auskommen. Wer sich also auf JS verlaesst, hat Murks schon „vorprogrammiert“. Aber ist es inzwischen denn wirklich moeglich, ein Video auf die Website zu bekommen, dass in allen Browsern und vor allem auch auf anderen Endgeraeten als PCs funktioniert? JA!

Natuerlich ist der MP4-Container heftig patentbelastet und es gibt auch noch andere gute Gruende, ein alternatives Format zu waehlen. Grundsaetzlich ist das mit dem <video>-Tag auch moeglich.

<video controls="controls">
<source src="meinFilm.mp4" type="video/mp4">
<source src="meinFilm.ogg" type="video/ogg">
<source src="meinFilm.webm" type="video/webm">
</video>

Hier mal nur die drei gaenigsten Video-Containerformate. Achtung, nicht vergessen, dass der Server die richtigen Mime-Type-Angaben in den Headern senden muss. Standtardmaessig ist das nicht immer konfiguriert. Also checken, dass beim Apachen folgendes konfiguriert ist.

AddType video/mp4 .mp4
AddType video/ogg .ogg
AddType video/webm .webm

Bei der Gelegenheit kann es auch nicht schaden, noch einen weiteren einzutragen. Mit

AddType text/vtt .vtt

klappt es dann spaeter auch mit Untertiteln. Wenn der Server die richtigen Mime-Types sendet, und der Film in allen drei Formaten auf der Platte liegt, funktioniert der <video>-Tag eigentlich jetzt schon mit allen aktuellen Browsern. Nur leider nicht mit allen mobilen Devices, die es so gibt. Doch dazu gleich mehr. Nun sieht soein Video-Fenster auf einer Webseite nicht gerade sonderlich schoen aus. Ein nettes Vorschaubild waere vielleicht ganz gut. Das laesst sich mit dem preload="metadata" bewerkstelligen. Auf den meisten Apple-Devices ist das sogar die Standard-Einstellung. Auch die Blog-Software WordPress macht das immer so. Warum das eine ziemlich bloede Idee ist, verrate ich gleich. Mit

<video preload="metadata">

also wird der Browser angewiesen, sich ein paar Meta-Daten wie zum Beispiel die Laufzeit und ein Vorschaubild zu holen. Ueblicherweise nimmt er sich dazu eins der ersten Bilder aus dem Film. Sieht dann bei einem etwas laengeren Vorspann natuerlich nicht sehr viel besser aus. Deshalb gibt es die Moeglichkeit, ein Vorschaubild mit dem Attribut poster="Vorschaubild.png" anzugeben. Das ist auch insofern die bessere Variante, wenn der Film in einem passwortgeschuetzten Verzeichnis liegt. Dann kann der Browser naemlich die Meta-Daten gar nicht holen und bloederweise versuchen dann einige Apple-Devices gar nicht erst die Zugangsdaten zu erfragen sondern verweigern gleich ganz die Anzeige des Videos. Daher ist es besser, ein poster-Bild anzugeben und preload auf „none“ zu setzen.

In WordPress laesst sich das leider nicht konfigurieren und die Goetter uebers offizielle Plugin-Verzeichnis waren leider zu doof, die Problematik zu verstehen und haben meine Erweiterung per Plugin abgelehnt 🙁

An dieser Stelle waere es gut, auch Besuchern mit aelteren oder kaputten Browsern etwas zu bieten. Wenigstens einen Hinweis. Damit der nicht das komplette Design zerschiesst, kann der auch schlicht aus dem Vorschaubild bestehen. Manche Tutorials empfehlen dort, einen Fallback auf Flash, dessen „object“- bzw. „embed“-Tag dann wiederum ein Fallback auf die Grafik macht. Ganz ehrlich: Ich „flashe“ gelegentlich auch was. Das ist dann aber eher ein Speicher 😉 Ausserdem wollte ich ja mit den Moeglichkeiten aktueller Browser auskommen und aelteren eine alternative Nutzung erlauben. Wer aber mit so alter Software noch im Netz unterwegs ist, bei dem wird vermutlich auch Flash oder zumindest dessen Einbindung kaputt sein. In den meisten Faellen duerften es ausserdem Smartphones sein, auf denen ueblicherweise eh nix geflasht ist. Zumindest nicht der Browser. Dann doch lieber gleich den eingebauten Video-Player des mobile Devices bemuehen, was vermutlich auch noch schonender fuer dessen Akku ist. Alle gaengigen Handys unterstuetzen MP4. Und seit Mozilla bei den Desktop-PCs das auch macht, laesst sich die Sache kurz wie folgt realisieren. Was im Uebrigen auch noch das Umcodieren des Videos und Speicherplatz auf dem Server spart.

<video controls="controls" preload="none" poster="meinVorschaubild.png">
<source src="meinFilm.mp4" type="video/mp4">
<a href="meinFilm.mp4"><img src="meinVorschaubild.png" title="Click to download">Your device does not support the video tag.</a>
</video>

Nun koennte die Welt so schoen sein, wenn da nicht ueber die Jahre hinweg einige kaputte Implementierungen vor allem bei Smartphones gewesen waeren, die vermutlich noch ein paar Jahre ohne entsprechende Updates weiter in Gebrauch sein werden. Der Apfel-Kram patzt oft beim Vorschaubild. Wen wundert es, denn „preload“ ist dort standardmaessig ja auf metadata gesetzt. Mit den oben beschriebenen Problemen. Gluecklicherweise laessen sich auch die Opst-Kisten zur Anzeige von was Sinnvollem ueberreden:

style="background:transparent url('meinVorschaubild.png') no-repeat 0 0; background-size: 100%; width: 100%; height: auto !important;"

als Attribut im <video>-Tag loest das Problem. Auch Android – vor allem die aelteren Androiden – funktioniert leider nicht wie erwartet. Das Poster-Bild wird oft nicht richtig skaliert. Was sich aber auch hier mittel StyleSheet fixen laesst. Viel schlimmer ist aber, dass der alternative Download-Link nicht klappt. Das laesst sich beheben durch ein

onclick="this.play();"

Ooops, sieht gefaehrlich nach JavaScript aus. Ist aber nen EventHandler aus HTML und funktioniert daher zuverlaessig. Klar, laesst sich das alles in ein JavaScript-Object packen. Dann faengt man sich aber wieder die Probleme bei den verschiedenen oder gar nicht vorhandenen Implementierungen ein. Von Problemen mit extern eingebundenem JS, was Fehler wirft, mal ganz zu schweigen… Also besser serverseitig klaeren. Hat auch seine Macken. Kann zum Beispiel schief gehen, wenn jemand mit gefaktem Browser-String unterwegs ist. Aber der ist es dann auch selber Schuld 😉 Mal davon ab, dass onClick dann trotzdem funktionieren sollte. Serverseitig einbinden laesst sich das dann etwa mittel PHP insgsamt nach folgendem Muster:


$video='meinVideo.mp4';
$bild ='meinBild.mp4'
echo '<video controls="controls"';
// if we do not have a poster image we try to get it from the movie
if(empty($bild)) echo ' preload="metadata"';
else echo ' preload="none" poster="'.$bild.'"';

// device specific
if(stristr($_SERVER['HTTP_USER_AGENT'],'android')) echo ' onclick="this.play();"';
if(stristr($_SERVER['HTTP_USER_AGENT'],'iphone') || stristr($_SERVER['HTTP_USER_AGENT'],'ipod') || stristr($_SERVER['HTTP_USER_AGENT'],'ipad') ){
echo ' style="background:transparent url(\''.$atts[img].'\') no-repeat 0 0; background-size: 100%; width: 100%; height: auto !important;">';
}else{ echo ' style="width: 100%; height: auto !important;">'; }

echo '<source src="'.$video.'" type="video/mp4">';
echo '<a href="'.$video.'"><img src="'.$bild.'" title="Can not play video">Your browser does not support the video tag.</a></video>';

Eigentlich ja ganz einfach 😉 Aber millionenfach noch immer krank implementiert. Allein, wenn man bedenkt, wie weit verbreitet WordPress mit seiner wenig schlauen Implementierung ist.

So und nun noch ein praktisches Beispiel.

$video='/wp-content/upload/kenia.mp4';
$bild ='/wp-content/upload/kenia.png'
echo '<video controls="controls"';
// if we do not have a poster image we try to get it from the movie
if(empty($bild)) echo ' preload="metadata"';
else echo ' preload="none" poster="'.$bild.'"';

// device specific
if(stristr($_SERVER['HTTP_USER_AGENT'],'android')) echo ' onclick="this.play();"';
if(stristr($_SERVER['HTTP_USER_AGENT'],'iphone') || stristr($_SERVER['HTTP_USER_AGENT'],'ipod') || stristr($_SERVER['HTTP_USER_AGENT'],'ipad') ){
echo ' style="background:transparent url(\''.$atts[img].'\') no-repeat 0 0; background-size: 100%; width: 100%; height: auto !important;">';
}else{ echo ' style="width: 100%; height: auto !important;">'; }

echo '<source src="'.$video.'" type="video/mp4">';
echo '<a href="'.$video.'"><img src="'.$bild.'" title="Can not play video">Your browser does not support the video tag.</a></video>';

Statt des Vorschaubildes im PNG-Format geht natuerlich auch ein JPG oder GIF.

[kissvideo mp4=http://blog.circus-sands.com/wp-content/uploads/kenia.mp4 poster=http://blog.circus-sands.com/wp-content/uploads/kenia.png][/kissvideo]

Okay, okay, ich hab gemogelt. Da das hier nen WordPress-Blog ist, klappt das mit dem direkten Einbinden von PHP-Code natuerlich nicht. Also habe ich ein eigenes video-Plugin genutzt, welches aber genau mit diesem Code arbeitet 😉

Dieser Beitrag wurde unter Allgemein, Software, Wordpress veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert