++ Hintergrund
Seit einiger Zeit unterstützen wir unsere Mutter bei der Führung eines YouTube-Channels: http://youtube.com/huehnergarten. Das nicht ganz so kleine Projekt macht Spaß und wir lernen dabei immer wieder was dazu. Natürlich ist man auch stolz wie Oskar und möchte andere Leute auf seine Werke aufmerksam machen. Wie aber gibt man einen YouTube-Channel weiter, wenn man sich gerade mit dem Nachbarn unterhält?
Etwa so: "Geh mal auf YouTube, such nach XYZ, das sind dann die Videos."?
Hm. Das funktioniert vielleicht bei sehr technikaffinen Personen. Einfacher wäre ja sowas wie "Geh auf XYZ.de und klick' Dich da durch."
Wir dachten uns also, dass eine kleine Website nicht schlecht wäre. Auf dieser Site sollten schlicht ein paar aktuelle Videos des Channels dargestellt werden - und das möglichst wartungsarm und anstregungslos. Nichts leichter als das! (Oder so.)
++ Überlegungen
+++ Prinzip
Wir wollten also den Aufwand insgesamt so gering wie möglich halten. Wir entschieden uns daher für die Umsetzung in Form eine Nearline-Lösung. Das bedeutet, dass die Seite nicht bei jedem Zugriff neu erstellt, sondern von außerhalb regelmäßig aktualisiert werden sollte. Ein Skript sollte dafür über die wohldokumentierte YouTube-Programmierschnittstelle (API) die Video-URLs besorgen und daraus das HTML erstellen.
Also: {{YouTube > Skript > HTML > Webserver}}
Der Vorteil eines solchen Vorgehens ist, dass damit die Komplexität gering bleibt. Man benötigt keinen besonderen Server, keine neue Datenbank oder sonstige Abhängigkeiten, es genügt ein einfacher Webserver -- und der lief eh schon. //Nearline// bedeutet hier auch, dass nicht bei jedem Websitebesuch Anfragen zur YouTube-API gehen. Das wäre auch nicht notwendig, denn der YouTube-Channel wird nur alle zwei, drei Tage gepflegt.
+++ Wahl der Mittel
++++ Programmiersprache
Die Wahl der Programmiersprache ist für viele Aufgaben eher eine Geschmacksfrage. Wir entschieden uns hier für Perl.
Man sagt, Perl sei die "Schweizer Offizierskettensäge" unter den Programmiersprachen. Perl ist pragmatisch, plattformübergreifend, schon sehr lange auf dem Markt und außerordentlich weit verbreitet. Zu den besonderen Vorteilen zählt das ausgereifte Ökosystem. Dieses umfasst insbesondere viele vorgefertigte Module, die in einem zentralen Repository bereitliegen.
Die meisten Unix- und Linuxvarianten bringen von Hause aus bereits ein {{perl}} mit. Auf Windows ist [http://strawberryperl.com/ Strawberry Perl] meist die beste Wahl.
Alternativen zu Perl wären aus unserer Sicht vor allem Ruby und, mit etwas Abstand, Groovy gewesen. (Bei Groovy wäre ich mir nämlich nicht sicher gewesen, ob ich in kurzer Zeit ein passendes YouTube-Modul gefunden hätte. Hinweise gerne als Kommentar!)
++++ Bausteine
Trotz Googles [https://developers.google.com/youtube/ guter Dokumentation]: Den Zugriff auf die API von YouTube wollten wir nicht zu Fuß erledigen. Wir entschieden uns, bei Perls zentralem Repository, dem CPAN (Comprehensive Perl Archive Network), nach etwas Passendem zu suchen.
Die Oberfläche MetaCPAN eignet sich dafür besonders. https://metacpan.org/search?q=YouTube zeigte einige mögliche Kandidaten. Bei der Auswahl des passenden Pakets ließen wir uns von den klassischen Motiven leiten:
* Aktualität des Moduls. Manchmal werden Module nicht mehr weitergepflegt, verbleiben aber im CPAN.
* Dokumentation. Qualität und Umfang - oft ist weniger mehr.
* Klarheit - möglichst überschaubares Design.
Natürlich wird jedes verfügbare YouTube-Paket mehr oder minder stark durch die eigentliche YouTube-API beeinflusst.
Wir fanden, dass [https://metacpan.org/module/WebService::GData::YouTube WebService::GData::YouTube] am besten für unsere Zwecke passte.
Installation wie immer wie folgt:
nick@shenron ~ $ cpan
cpan shell -- CPAN exploration and modules installation (v1.9800)
Enter 'h' for help.
cpan[1]> install WebService::GData::YouTube
CPAN löst eventuelle Abhängigkeiten von selbst auf.
+++ Umsetzung
++++ Erste Rohfassung
use Modern::Perl;
use WebService::GData::YouTube;
use Data::Dumper; # Zum Debuggen immer ganz gut.
my $channel = "Huehnergarten";
my $yt = new WebService::GData::YouTube();
my $videos = $yt->getuservideos($channel);
say Dumper($videos);
Wir verwenden also [http://modernperl.net/ Modernes Perl] und das bewährte Data::Dumper, um eine Datenstruktur auszugeben. Im Prinzip ist der vorliegende Code schon sowas wie ein "minimaler YouTube-Client".
++++ Zweite Rohfassung
Anstatt dass wir Data::Dumper bemühen, können wir auch gleich durch die Datenstruktur laufen.
use Modern::Perl;
use WebService::GData::YouTube;
my $channel = "Huehnergarten";
my $yt = new WebService::GData::YouTube();
my $videos = $yt->getuservideos($channel);
foreach my $video (@$videos) {
say "http://www.youtube.com/embed/" . $video->video_id;
}
Die zweite Fassung gibt also alle zurückgegebenen Video-URLs aus und ist damit schon ein wenig komplexer als die erste.
Die API gibt standardmäßig 25 Videos zurück. Wir wollten die Videos aber auf der Website einbetten. Da wären schon die 25 auf einmal etwas zuviel. Überhaupt, Website! HTML! Wir könnten jetzt die ganze HTML-Seite im Perlskript zusammensetzen. Das könnte erfahrungsgemäß schnell recht hässlich werden. Besser ist eine Trennung von Programmcode und Design: Ein Templatesystem muss her.
++++ Das Ende naht!
Die Wahl fällt hier auf [http://www.template-toolkit.org/ Template::Toolkit]. Es ist mächtig, flexibel und erschlägt einen dabei nicht mit Komplexität. Man muss sich mit der nämlich auch nicht beschäftigen, wenn man sie nicht braucht.
Unser Projekt [http://edifactviewer.com EDIFACTviewer.com] setzt Template::Toolkit übrigens ebenfalls ein.
Installation ähnlich wie oben:
cpan[1]> install Template::Toolkit
Template::Toolkit lässt sich unkompliziert einbinden.
use Modern::Perl;
use WebService::GData::YouTube;
use Template;
----------------------------------------------------------------------
my $channel = "Huehnergarten";
my $howmany = 10;
----------------------------------------------------------------------
my $yt = new WebService::GData::YouTube();
$yt->query->max_results($howmany); # Anzahl Resultate setzen, default ist 25
YouTube-API: Channel abfragen.
my $videos = $yt->getuservideos($channel);
Template initialisieren. Wenn es schiefgeht: Programm abbrechen ('die').
my $tt = Template->new() || die "$Template::ERROR\n";
Hier sammeln wir die Video-URLs. Vielleicht nicht der schlaueste Namen für die Variable.
my @movies;
@$videos durchlaufen
foreach my $video (@$videos) {
# 'push' hängt einen weiteren Wert ans Array, es wird also wie ein Stack / Stapel behandelt.
push @movies, "http://www.youtube.com/embed/" . $video->video_id;
}
Das Template wird gefüllt und auf der Konsole ausgegeben. Wenn es schiefgeht: Programm abbrechen.
$tt->process('huehnergarten.tt', { movies => [ @movies ] } ) || die $tt->error(), "\n";
Der erste Parameter ist der Name des Templates und der zweite ein Hash, also
die Schlüssel-Wert-Paare, mit denen das Template gefüllt wird.
movies => [ @movies ] bedeutet in dem Fall, dass wir dem Template (dort)
"movies" bekannt machen, das eine Liste aus @movies (hier) ist.
Hier ist eine einfache Variante von {{huehnergarten.tt}}:
Hühnergarten
[% FOREACH movie = movies %]
[% END %]
Die Anweisungen an das Templatesystem sind also in eckigen Klammern. Hier wird ganz einfach ein Array abgearbeitet. {{movies}} hatten wir weiter oben per {{$tt->process}} übergeben.
Der IFRAME-Code ist dem offiziellen Einbettungsquellcode von YouTube entnommen.
Das Modell von oben ist jetzt wie folgt: {{YouTube > (Skript < Template) > HTML > Webserver}}
+++ Aufruf
Ruft man das Skript von der Kommandozeile aus auf, wird das gefüllte Template ausgegeben.
Wir haben es auf unserem Server so eingerichtet, dass das ein Cronjob übernimmt:
perl skript.pl > /apachewebserver/zielsite/index.html
That's it. Das Ergebnis: http://huehnergarten.de.
++ Mit wenig Aufwand..
Wir haben hier gezeigt, wie man mit relativ wenig Aufwand eine minimale Website für einen YouTube-Kanal erstellen kann. Über einen Cronjob nearline aktualisiert, ist sie quasi wartungsfrei. Wir haben in diesem Eintrag CPAN und MetaCPAN gestreift, uns ein YouTube-Package ausgesucht und schließlich noch ein Template-System eingebunden. Dieses macht es uns einfach, die Website weiter auszubauen.
Schaut man sich mit Data::Dumper an, welche Informationen noch in der Rückgabe von {{getuservideos();}} stecken, wird deutlich, wohin die nächsten Ausbauschritte führen könnten. Aber auch die Einbindung weiterer Datenquellen (Markdown-Textdateien, SQLite, MySQL) bietet sich an. Man könnte auch etwas Zeit in die weitere Ausfallsicherheit des Programm investieren - gibt es eine Fehlermeldung aus, wird im Cronjob nämlich trotzdem die {{index.html}} überschrieben.. Alles machbare Kleinigkeiten! :-)
Andere Kommentare