Chaosradio 195: Raumfahrt

Seit 18 Jahren gibt es die Sendung Chaosradio beim Sender Fritz. Ich kann mich nicht mehr daran erinnern, welche Sendung ich als erste hörte, aber es muss eine sehr frühe gewesen sein. Damals wohnte ich noch nicht im Sendegebiet und das Internet-Streaming mit dem Realplayer über ein 56k-Modem war nicht zumutbar. So saßen wir öfters mit ein paar Freunden zusammen, um die Übertragung via Satellit zu hören.

Gestern lief die 195. Ausgabe und für mich die erste, bei der ich mitwirkte. Es ist schon kurios, dass ich in in meiner ganzen aktiven CCC-Zeit von 1999 bis 2008, kein einziges Mal in der “vereinseigenen” Sendung war. Stattdessen saß ich in diversen anderen Radiostudios oder TV-Sendern.

bcc voll beleuchtet bei Nacht

Das Thema der Sendung lautete dieses Mal “Raumfahrt”. In der Fritz-Mediathek ist die Sendung bereits zum Nachhören verfügbar. In den kommenden Tagen wird sie auch im Podcast-Feed vorhanden sein und vor der Depublizierung bewahrt. Den Inhalt der Sendung hat das wunderbare Shownotes-Team transkribiert. Ein großes Danke dafür!

Mit der Sendung bin ich durchaus zufrieden, da wir viele Themen angesprochen haben und vermutlich auf ein verständliches Niveau rüber brachten.

Podcast

Auf der Rückfahrt vom Sendestudio setzte mir der Moderator Marcus Richter den Floh ins Ohr, einen eigenen Podcast zum Thema Raumfahrt zu produzieren. Dieses insbesondere deshalb, da die zwei Stunden im Radio für diesen großen Themenbereich viel zu kurz waren. Er bietet mir sogar an, sein eigenes Podcast-Equipment zu nutzen, um bloß keine verknarzte und verrauschte Sendung zu erstellen.

Das klingt verlockend! Jedoch möchte ich die deutsche Podcastwelt nicht mit einem weiteren Podcast überfüllen, der dann eh nicht gehört wird. Zum Thema Raumfahrt gibt es bereits einige Podcasts.

Ganz vorne dabei ist Raumzeit vom Onkel Tim in Kooperation mit DLR und esa. Vom Format her unterhält sich Tim mit Mitarbeitern oder Raumfahrern der beiden Organisation, also mit Professionals. Schaue ich aber auf die Publikationsfrequenz, so ist es sehr ruhig geworden um Raumzeit. Es fühlt sich ein wenig danach an, dass nach 50 Ausgaben in zwei Jahren die Luft (oder das Geld?) aus war und dann nur noch sporadisch Folgen nachgelegt wurden. Von 25 Folgen pro Jahr in 2011 und 2012 auf ganze sechs runter in 2013. Das ist sehr schade.

Das Team um den Raumfahrer Net e.V. hauen nahezu täglich kurze Podcasts zu diversen Raumfahrt-Themen raus. Hier ist das Format eher ein Newsflash, was mich ein wenig an die tägliche Sendung dradio-Sternzeit erinnert.

Erwähnenswert ist noch der Podcast AstroGeo von einem Raumfahrer Net e.V. Mitstreiter. Die Sendungen sind nicht nur auf den Weltraum bezogen, sondern sprechen auch einige Natur- und Umweltthemen auf der Erde an.

Und viel mehr Podcasts gibt es meiner Meinung nach nicht im deutschsprachigen Raum. Deshalb überlege ich tatsächlich, ein Format zu starten, das die Lücke der Amateur-Raumfahrt füllt. Alleine Monologe zu führen finde ich extrem langweilig. Ich werde mich also mal unter meinen raumfahrtbegeisterten Bekannten in Berlin umhören, ob jemand mit mir eine (un-)regelmäßige Sendung zu dem großen Oberthema “Raumfahrt” starten möchte (sprich mich an, falls ich Dich vergessen habe!). Also durchaus einzelne Themen rauspicken, um über diese ein bis zwei Stunden zu reden. Oder auch aktuelle Ereignisse, zum Beispiel den Start oder das Ende von Missionen, zu besprechen.

Darüber hinaus kann ich es mir gut vorstellen, “Außeneinsätze” zu Hobby-Raumfahrern durchzuführen, um mit denen zu quatschen. Quer durch die Bank Leute, die im Studium oder privat Satelliten bauen, mit dem Weltraum funken oder selbst startfähige Raketen konstruieren.

Dass ich die Ideen hier niederschreibe, widerspricht zwar der alten Weisheit “erst Ei, dann Gack”, doch ich brauche etwas Feedback, ob sich der Aufwand lohnt. Spaß werde ich sicherlich dabei haben; nur ich weiß auch, dass das keine Sache für “mal eben Nebenher” ist.

Eine chronologisch sortierte Historie zu #aufschrei

Im Januar 2013 wurde auf Twitter unter dem Hashtag #aufschrei eine Aktion gestartet, die eine (nicht nur) deutschlandweite Debatte über Sexismus auslöste. Bisher fehlte eine Historie mit allen Tweets zu diesem Hashtag. Aufgrund der eingeschränkten Möglichkeit von Twitter über die API darauf zuzugreifen, wird dieses nie der Fall sein. Aber zumindest für die ersten zwei Wochen konnte ich ein Archiv erstellen und in einer angenehmen Form darstellen:

http://aufschrei.konvergenzfehler.de/

Scraping

Im Herbst 2012 entwickelte ich ein Script, um die Tweets für das #refugeecamp Berlin (später #rfcamp) einzusammeln. Für mich war es etwas Fingerübung in Python und mit der Twitter-API. Eigentlich hatte ich vor, daraus eine Webseite zu erstellen, die die Aktionen (Spendenaktionen, Temperaturwerte, Bilder, Gespräche mit Politikern und vor allem die Übergriffe der Polizei) darstellt und wichtige Zeitpunkte hervorhebt. Dank Zeitmangel und fehlenden Fähigkeiten wurde daraus nichts.

Ende Januar stieß mich map an und meinte “Du hast da doch mal dieses Script zum Scraping geschrieben – kannst Du die mal auf #aufschrei ansetzen? Uns fehlt der allererste Tweet.” Gefragt, getan. Die Tools lagen noch alle einsatzbereit auf einem Server und eine knappe Stunde später hatte ich etwa 50000 Tweets runtergeladen. Großer Jubel, als wir feststellten, dass der allererste Tweet dabei war.

Das Script sucht mit der Twitter Search API nach dem angegebenen Hashtag. Dabei geht es vom aktuellen Zeitpunkt iterativ immer weiter zurück, bis keine Tweets mehr gefunden werden. Die Search API findet Tweets der vergangenen neun Tage – mehr bietet Twitter nicht an. Außerdem gibt es Beschränkungen auf 200 Tweets pro Request, aber es kann das Datum des letzten gefundene Tweets als Startadresse für eine neue Suche angegeben werden.

Zwei Kleinigkeiten, über die ich schon beim Scraping für das #refugeecamp gestolpert war: Twitter erlaubt sich, Benutzer_innen aus der Search API zu verbannen, die viel mit einem Hashtag twittern. Die Benutzerin ist nicht geblockt, aber wird nicht mehr mittels einer Suche zurück gegeben. Die andere Kleinigkeit ist die Einstellung auf “gib mir alles” und nicht nur die “most trending Tweets”. Letzteres ist der Default, weshalb die Tweets nicht chronologisch ankommen, sondern nach irgendeiner Heuristik von Twitter, die meint, das seien die interessantesten Ergebnisse für diese Suche.

Fast schon unnötig es explizit anzugeben, aber es werden nur Tweets von Accounts erfasst, die zu dem Zeitpunkt auf public geschaltet waren. Wer einen protected Account hat, wird über die Search API nicht gefunden.

JSON-Daten – und nun?

Das Scraping-Script spuckte mir nach Tagen aufgeteilt JSON-Dateien aus. Da lag nun alles drin, aber ansehnlich war es nicht. Da ich eh schon mal ein Projekt mit Django machen wollte und sogar noch ein paar Anfänge zur #refugeecamp-Geschichte rumliegen hatte, begab ich mich an die Datenbankmodellierung. Da Django das Datenbank-Backend ziemlich egal ist, wählte ich PostgreSQL. Doch trotz eines fertigen Models mussten die Daten in die Datenbank kommen. Das klappt bei Django ganz gut mit Fixtures, was JSON-Dumps der Datenbank sind.

Also baute ich ein Script, was mir die JSON-Search-API-Dateien in JSON-Django-Fixtures umwandelte. Damit waren die 93667 Tweets in der Datenbank gespeichert. Recht fix schrieb ich ein paar Django-Views und einfache Templates, die mir eine chronologische Sortierung ausgaben.

Aber es war hässlich.

Das mag daran liegen, dass ich aus der Zeit von HTML2 komme und es seit 1995 gewohnt bin, Webseiten in einem Texteditor zu schreiben. CSS? Gab es nicht. JavaScript? Wurde im Browser abgeschaltet, weil böse. Pures HTML – mehr nicht! Und Webdesign? Ich fahre kein Snowboard.

Irgendwer verwies mich auf Bootstrap. Nachdem ich die Doku drei Mal durchlies, konnte ich es anwenden. So wurde die Ausgabe in Django immer schöner und ganz langsam gefiel mir mein Werk.

Weniger ist mehr

So ganz im klaren darüber, was die Webseite eigentlich können sollte, war ich mir nicht. Aber es gab ein paar Ideen. So war eine der Ideen, eine interaktive Oberfläche zu bieten, in der mit Crowd-Working die Tweets mit Tags versehen werden (beispielsweise Spam, KackscheisseVorfall, etc.). Das hätte Interaktion benötigt und Schreibzugriff auf die Datenbank. Oder ich wollte coole Auswertungen machen, so mit Graphen und Zeitleiste. Alles automatisiert aus den Daten in der Datenbank. Immer wieder überlegte ich, wie ich das machen sollte. Zwischendurch lag deswegen das Projekt monatelang in der Schublade (oder eher auf dem Server) und ich packte es nicht mehr an.

Aber bevor ich gar nichts mache und die Daten vergammeln, fällte ich die Entscheidung, nur eine Timeline anzuzeigen. Einfach und simpel.

Lokal ist besser als Remote

Mit meiner ersten Darstellung einer Timeline fiel mir auf, dass Links in Tweets vom Twitter-eigenen URL-Shortener t.co zum “Zwecke der Qualitätssteigerung” gekürzt werden. Dadurch lässt sich nicht erkennen, wohin verlinkt wird, geschweige eine Ahnung vom Inhalt zu erhalten.

Also, noch einen Scraper bauen, der alle Links durchgeht, die Original-URL wiederherstellt und am besten sogar noch die HTML-Titelzeile abholt und in der Datenbank speichert. Das machte ich mit der Python Bibliothek BeautifulSoup. Zwischendurch rannte ich in einen nicht lösbaren Speicherkiller-Bug von BeautifulSoup, weshalb das Scraping immer wieder neu angestoßen werden musste. Nach ein paar Stunden hatte ich 13992 Links zusammen und bewahrte sie wertvoll in der Datenbank auf.

Dieses Scraping lief erst im Mai und Juni 2013. Etliche Links werden als Fehler angezeigt, da die Webseite nicht mehr vorhanden war – ob nun tote Webseiten, gelöscht oder vom öffentlich-rechtlichen Rundfunk depubliziert worden.

Außerdem checkte ich die Links, ob es Bilder sind. Nicht jeden Webseiten-Bilder-Dienst habe ich unterstützt und bei manchen ist es auch verdammt schwer an die Original-URL eines Bilds zu kommen. Aber ein paar große sind dabei. Diese Bilder speicherte ich auch weg. 783 Bilder mit 80MB liegen lokal vor.

Und noch etwas wollte weggespeichert werden: Die Avatare der 25888 Twitter-Benutzer_innen, die an der Aktion mitgewirkt haben. Der ein oder andere Account war inzwischen gelöscht oder gesperrt, aber viele Avatare sind zusammen gekommen. Diese stellen einen alten Stand dar – aktuelle Avatare lade ich nicht runter.

Alles wegwerfen und neu anfangen

Ein paar Django Views waren zusammen gekommen, die Timeline konnte angezeigt werden, etwas Statistik war auch möglich. Aber alles sah zusammengestückelt aus. Nicht wie aus einem Guss. Da hilft nur eins: mit dem gesammelten Wissen noch mal neu machen.

Aber das geht dann recht fix. An einem Wochenende ist in etwa zehn Stunden die jetzige Seite mit allen Views entstanden. Direkt auf Bootstrap 3 aufgesetzt, mit diversen Templates, die einfach nur included werden, und nicht all zu viel Schnickschnack. Als kleine und binnen weniger Minuten umgesetzte Fingerübung kamen noch die reine Bilder– und die Linklisten-Timeline hinzu. Der “zufällige Tweet” war auch keine große Sache, musste nur etwas durchdacht werden.

Fehlte noch eine Startseite in einem etwas anderen Layout. Mit Bootstrap kein großes Problem.

Deploy

Bisher lief die Seite nur im Django Development Modus. Das ist kein Setup, was viele Requests abfrühstücken kann. Mit etwas Suche entschied ich mich für eine Kombination aus Nginx und uWSGI. Dieses Setup aufzusetzen ist nicht ganz einfach, aber es läuft sehr stabil.

Und was ich bei meinem aktuellen Job gelernt habe: Caches einsetzen. Viele Caches. Neben dem Datenbank-Cache gibt es noch einen Memcached und Nginx cached auch noch mal die uWSGI-Requests. Die Bilder werden aktuell nicht gecached, da sie im Laufe der Zeit vom Betriebssystem in die RAM-Caches geladen werden statt jedesmal auf die Festplatte zuzugreifen. Lägen sie Remote, würde auch hier ein Cache wieder Sinn machen.

Meine Freude war echt groß, als ich die Seite http://aufschrei.konvergenzfehler.de/ über dieses Setup aufrufen konnte. Und dass sie sogar auf einem Smartphone dank Bootstrap ohne Code-Änderung sehr gut aussieht!

Weiterentwicklung

Für mich ist das Projekt an dieser Stelle erstmal beendet, damit ich mich wieder anderen Dingen zuwenden kann. Aber wer gerne mit den Daten arbeiten oder die vorher genannten Ideen umsetzen möchte, kann das Projekt bei GitHub clonen. Das Fixture für die Datenbank liegt mit drin. Die Mediendateien (130MB) habe ich separat gepackt. Die Installation sollte “Standard-Django 1.5” sein.

Ich freue mich, wenn ich irgendwann in Zukunft noch tolle Projekte daraus entstehen sehe. Vielleicht eine schön aufgewertete Timeline. Oder sogar ein etwas größeres Projekt, was automatisch Hashtags mitschreibt und anzeigt, sodass in Zukunft nicht so viel Arbeit notwendig ist.

Frühlingserwachen im Zeitraffer

Vor ein paar Wochen, als es noch Winter war, fiel mir ein Bild in die Hand, das ich letzten Sommer aus dem Fenster im Arbeitszimmer geschossen habe. Ich war über den Unterschied extrem erstaunt! Zum Vergleich zwei aktuelle Bilder aus diesem Jahr:

Garten im Winter Garten im Frühjahr

Zwischen den beiden Bildern liegt ein Unterschied von 44 Tagen. Oder um genau zu sein, 29. März zu 12. Mai. Da die Prozesse in der Flora nur sehr langsam ablaufen, ist für den Menschen an sich kaum möglich, den Blumen beim wachsen zuzusehen. Hier helfen nur technische Hilfsmittel. Also schaute ich mich in meinem Haushalt um, womit ich eine Zeitrafferaufnahme über mehrere Wochen laufen lassen kann.

Man nehme:

  • Raspberry Pi (Modell B Rev. 2)
  • Logitech C525 HD Webcam
  • 16GB SD-Card
  • 10W USB-Netzteil (in diesem Fall das Apple iPad Ladegerät)
  • Doppel- und Gewebeklebeband

Als Betriebssystem ist ein ganz normales Raspbian von Anfang 2013 auf der SD-Card installiert. Der Kernel ist sogar noch ein 3.2.27 vom Oktober 2012. Aber er enthält bereits das für diese Kamera notwendige Modul uvcvideo, sodass nicht noch ein neuer Kernel kompiliert werden muss. Die einzigen beiden nachträglich installierten Pakete sind uvcdynctrl und motion. Ersteres, um die Webcam einzustellen und letzteres für die regelmäßigen Bilder.

Mit dem ersten Befehl werden die verfügbaren Kameras angezeigt (hier die „HD Webcam C525“ an video0) und mit dem zweiten Befehl die verfügbaren Einstellungen.

root@raspberrypi:~# uvcdynctrl -l
Listing available devices:
video0 HD Webcam C525
Media controller device /dev/media0 doesn\'t exist
ERROR: Unable to list device entities: Invalid device or device cannot be opened. (Code: 5)
root@raspberrypi:~# uvcdynctrl -c
Listing available controls for device video0:
Exposure, Auto
Exposure (Absolute)
Exposure, Auto Priority
Pan (Absolute)
Tilt (Absolute)
Focus (absolute)
Focus, Auto
Zoom, Absolute
root@raspberrypi:~#

Mit der Option -f lassen sich die verfügbaren Auflösungen anzeigen, um die Auswahl für das andere Tool, motion, einfacher zu machen.

Nach dem ersten Aufnahmetag stellte ich fest, dass die Bilder zu stark “pumpen”, was der Kameraautomatik verschuldet war. Insbesondere bei starken Kontrastwechseln durch Wolken waren die aufeinander folgenden Bilder sehr unterschiedlich. Mit uvcdynctrl lassen sich beide Werte fest einstellen.

root@raspberrypi:~# uvcdynctrl -s 'Focus, Auto' 0
root@raspberrypi:~# uvcdynctrl -s 'Focus (absolute)' 0
root@raspberrypi:~# uvcdynctrl -s 'Exposure (Absolute)' 35
ERROR: Unable to set new control value: A Video4Linux2 API call returned an unexpected error 5. (Code: 12)
root@raspberrypi:~# uvcdynctrl -s 'Exposure, Auto' 1
root@raspberrypi:~# uvcdynctrl -s 'Exposure (Absolute)' 35

Die Namen der Controls können mit der bereits vorher schon genannten Option -c herausgefunden werden. Da die Namen Leerzeichen oder andere komische Zeichen enthalten, den Namen in einfache Anführungsstriche setzen.

Der Wert ‚Exposure (Absolute)‘ lässt sich beispielsweise im ersten Anlauf nicht setzen, da bei ‚Exposure, Auto‘ noch nichts gesetzt ist. Der Wert ‚1‘ schaltet ‚Exposure, Auto‘ nicht ein, wie sich vermuten lässt, sondern schaltet dieses auf den ‚Manual Mode‘. Das lässt sich mit den Optionen -c -v herausfinden, so wie auch alle anderen möglichen setzbaren Werte:

Exposure, Auto
ID : 0x0000000f,
Type : Choice,
Flags : { CAN_READ, CAN_WRITE },
Values : { 'Manual Mode'[1], 'Aperture Priority Mode'[3] },
Default : 0

Mit dem Wert von ’35‘ bei Exposure schaltet die Kamera beispielsweise nicht auf einen sensitiveren Wert in der Nacht um, sodass es tatsächlich ab der Dämmerung auf dem Bild dunkel und nachts gar ganz dunkel ist. Laternen oder Wohnungsbeleuchtungen reichen nicht aus, um ein Bild wahrzunehmen. Die eingestellten Werte lasse sich mit den Optionen -S und -L in eine Datei speichern und laden, da sie beim Abstöpseln der Kamera oder einem Reboot verloren gehen würden.

Am besten einfach mal mit den Werten herumspielen und das Ergebnis anschauen – Stopp! Bisher ist ja nur die Kamera angeschlossen und kein Ergebnis zu sehen. Da ich den Raspberry Pi headless betreibe, also ohne Monitor, brauche ich irgendwie eine Ausgabe. Das bringt uns zu motion.

Das Tool motion ist ein Daemon, der die Webcam ansprechen kann und diverse Aktionen durchführt. Wie der Name vermuten lässt, wurde es entwickelt, um so etwas wie eine Überwachungskamerafunktionalität mit Linux aufzubauen. Es kann regelmäßig Bilder aufnehmen, vergleichen und bei einer einstellbaren Schwelle an Änderungen Aktionen durchführen, wie beispielsweise Bilder aufnehmen oder irgend etwas anderes per Kommandozeile steuern.

In meinem Fall wollte ich drei Funktionen:

  1. Regelmäßige Aufnahme von Bildern
  2. Automatisches Erstellen eines Videos aus den Bildern
  3. Ansicht im Browser zur Überprüfung des Bildes

Bei Debian bzw. raspbian wird der motion Daemon in der Datei /etc/default/motion eingeschaltet. Die Datei /etc/motion/motion.conf dient zur Konfiguration. Als Beispiel, meine Änderungen gegenüber der Default-Configdatei:

# YU12 bzw. YUV520 Palette
# MJPEG lässt sich nicht aktivieren
v4l2_palette 8
# 720p ist mit dieser Kamera ohne Probleme möglich und da nur
# Standbilder aufgenommen werden, reicht der raspi
width 1280
height 720
# Generelle maximale Framerate für die Kamera
framerate 10
# Einstellungen für das automatische Video, hier:
# alle 300 Sekunden ein Bild und daraus täglich ein
# mpeg4 Video in der höchsten Bitrate/Qualität erstellen
ffmpeg_cap_new off
ffmpeg_timelapse 300
ffmpeg_timelapse_mode daily
ffmpeg_variable_bitrate 2
ffmpeg_video_codec mpeg4
# Intervall für jpg-Snapshots, hier alle 60 Sekunden
snapshot_intervall 60
# Text, der unten rechts im Video eingeblendet wird (Datum, Zeit)
text_right %Y-%m-%d\n%T
# Datei zum speichern; Motion speichert per default nach /tmp, was
# bei einem Reboot gelöscht wird!
target_dir /srv/motion
# die JPGs sortiert speichern, um nicht zu viele Dateien in einem
# Ordner zu haben (1 Tag = 60 Bilder ⨉ 24 Stunden = 1440 Dateien)
snapshot_filename %Y/%m/%d/%H-%M-%S
# Dateiname für die mpg-Dateien
timelapse_filename %Y%m%d-%H%M-timelapse
# Port für die Browser-Funktion angeben, um diese einzuschalten
webcam_port 8081
webcam_maxrate 10
webcam_localhost off
# Motion nicht über einen Browser-Interface konfigurieren lassen
control_port 0

LangzeitaufnahmeMotion kann einfach mit dem Init-Script gestartet werden. Jetzt kann via HTTP im Browser auf der IP des Raspi und dem Port 8081 das aktuelle Bild betrachtet werden. Die Aktualisierung braucht durchaus ein paar Sekunden, insbesondere, wenn an uvcdynctrl-Werten etwas geändert wird. Die Kamera habe ich mit Doppelklebeband von innen an die Scheibe geklebt und mit Gewebeklebeband gefixt. Das ganze Setup baute ich am 10. April auf. Am 11. und 12. April machte ich ein paar Einstellungen an motion und uvcdynctrl, um Exposure und Focus unter Kontrolle zu bekommen. Außerdem verwendete ich die Funktionen für Pan und Tilt, um nur den Ausschnitt rechts oben mit Bäumen ins Bild zu holen statt den Garten mit den Sandkästen. Am 4. Mai beendete ich die Aufnahmen, was 22 Tagen entspricht. Der raspi lief die ganze Zeit ohne Reboot oder Zucken durch. Auch wenn motion mit der Webcam-Funktion die CPU nahezu am Anschlag laufen lässt, gab es keine Hitzeprobleme oder ähnliches. Ich bin von der Stabilität dieses Kleincomputers sehr erstaunt! Selbst die Installation eines FTP-Daemons zum besseren Download der Bilddateien statt über sftp hat des raspi nicht gestört.

Nun ging ich davon aus, dass ich einfach die täglichen, von motion erstellten Videos nehmen könnte, um eine schöne Timelapse-Aufnahme zu erstellen. Doch leider stellte sich heraus, dass entweder motion oder der raspi Probleme verursachen und recht häufig Artefakte aus sich überschneidenden Bildern dargestellt werden. Außerdem sind die schwarzen Nächte recht lang, sodass ich die Videos eh hätte schneiden müssen.

Glücklicherweise hatte ich ich in der motion-Config angegeben, dass minütlich ein JPG-Bild aufgenommen werden soll. Pro Tag kommen dort so 100MiB bis 150MiB für die 1440 Bilder zusammen, je nach Sonnenscheindauer, Wetter und der damit verbundenen Anzahl an Farben. Von diesen Bilder habe ich erstmal getrost gelöscht, was wirklich Nacht ist. Also, alles zwischen 22 und 04 Uhr. Da Sonnenauf- und -untergang nicht nur vom Tag sondern auch vom Wetter abhängig sind, konnte ich keine fixen Uhrzeiten raussuchen, welche Bilder ich löschen konnte. Stattdessen benutzte ich das Tool identify aus der ImageMagick Suite. Mit der Option -format %k gibt identify die Anzahl der Farben in einem Bild aus. Stichproben ergaben, dass selbst in schwarzer Nacht die Kamera immer noch so etwa 75 Farben zurück gibt. Mit Einsetzen der Dämmerung nimmt die Anzahl der Farben schlagartig auf mehrere Tausend zu. Als guten Schwellwert ermittelte ich 100 Farben. In einer Schleife sieht das so aus:

for pic in *.jpg; do colors=$(identify -format %k ${pic}); echo "${pic}: ${colors}"; [[ "${colors}" -lt "100" ]] && rm ${pic}; done;

Zum Erstellen des Videos las ich noch mehrere Stunden lang ffmpeg-Parameter und testete diverse Einstellungen aus. Das beste Ergebnis bekam ich mit

ffmpeg -r 30 -f image2 -pattern_type glob -i "*-?0-00.jpg" -crf 18 -preset slow springtime.mp4

Das erstellt ein Video mit einer Framerate von 30 Bildern pro Sekunde (also etwas mehr als die üblichen 25 im Fernsehen oder 24 im Kino), die einem Pattern entsprechen. Das Pattern löst sich zu „alle Bilder, die zu einer Minute mit 0 am Ende aufgenommen wurden“, also „alle 10 Minuten“ auf. Mit -crf 18 -preset slow wird eine variable Bitrate mit hoher Qualität verwendet. Das Umkodieren der 1925 verwendeten Bilder hat knapp 9 Minuten gedauert; dabei sind 64 Sekunden an Film heraus gekommen. Das kommt auch von den eingegebenen Bildern hin: Bei „ein Bild alle 10 Minuten“ sind das 6 Bilder pro Stunde. Bei 30fps ist das 1/5 Sekunde pro Stunde. Im April sind es etwa 14,5 Stunden von der Morgen- bis zur Abenddämmerung, was ungefähr 2,9 Sekunden für einen Tag (die Nacht habe ich ja entfernt) ausmacht. Bei 22 Tagen mit 2,9 Sekunden komme ich auf die 64 Sekunden Film.

Viel geredet, hier ist der Film:


Link zu Vimeo

Im Laufe der Zeit neigte sich die Kamera immer weiter nach oben, da morgens die direkte Sonne auf das Fenster schien und das Klebeband gelöst hat. Aber es ist sehr schön zu beobachten, wie es von unten herauf immer grüner wurde. Der richtige Durchbruch kam dieses Jahr um den 21. April.

Update:

Die im Hintergrund zu sehende Schwarzpappel wurde am 8.8.2013 gefällt. Sie war morsch geworden und bei jedem Sturm ließ sie große Äste fallen. Es gab wohl Befürchtungen, dass sie ganz umstürzt und dabei das denkmalgeschützte Haus (der erste Nachkriegsplattenbau der DDR) zerstört. Anhand der Jahresringe konnte ich ablesen, dass sie etwa 60 Jahre alt wurde – in dieser Zeit aber enorm mit einem Umfang von über 5m wuchs.

Gefällte SchwarzpappelIm Video habe ich damit zufälligerweise den letzten Frühling dieses Baumes aufgenommen.

 

Defekte Angleichung • Lars Weiler