Zeitraffer Videos mit Webcam und Raspberry Pi

Winterzeit ist Bastelzeit, so auch dieses Jahr. Um das rege Treiben an meinem Vogelhäuschen etwas einfangen zu können, wollte ich davon Zeitrafferaufnahmen erstellen.

Da bei mir bereits ein Raspberry Pi rund um die Uhr läuft (Heimautomatisierung mit „Home Assistant“), schien es naheliegend, den dafür zu nutzen. Als Kamera hab ich ebenfalls auf etwas zurückgegriffen, dass schon vorlag, eine einfache Logitech C615 Webcam. Da gibt es sicher bessere, was sich auch positiv auf die Bildqualität auswirken würde, aber ich wollte dafür nix investieren.

How to Zeitraffer

Nach der ersten Idee kam die Frage, wie man das Zeitraffer-Thema angeht.

Das habe ich mir dann etwas einfach gemacht, indem ich festgelegt habe, dass ich zwischen 7 und 17 Uhr alle 10 Sekunden ein Bild aufnehmen möchte. Damit läuft man zwar Gefahr, dass auch mal nix los ist, Teile der Videos dunkel sind oder sonstwas, aber es verkompliziert das Thema nicht zusätzlich.

Bei 10 Sekunden „Auflösung“ sollte zudem auch ein kurzer Stop eines Vogel erfasst werden, so dass man im Video auch was sieht.

Die einzelnen Bilder kann man dann zu einem Video zusammensetzen und fertig.

Bilder mit der Webcam über die Kommandozeile aufnehmen

Um viele Bilder intervallgesteuert aufnehmen zu können, bietet sich eine kommandozeilenbasierte Lösung an. Ich habe hier fswebcam gewählt, weil das gut dokumentiert ist und auch ohne Probleme sofort mit meiner Webcam zusammengearbeitet hat.

Ich nutze in meinem Crontab (dazu später mehr) folgenden Aufruf für fswebcam:

/usr/bin/fswebcam -d /dev/video0 -r 1920x1080 --banner-colour „#dd000000“ --line-colour „#ff000000“ -D 1 -F 5 /home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg

-d /dev/video0 definiert hier das erste Videogerät (meine Webcam) als Eingabegerät

-r 1920x1080 legt die Größe des gemachten Bildes fest

--banner-colour und --line-colour definieren die Hintergrundfarben des Timestamps bzw. des Bildoverlays, den fswebcam automatisch erzeugt. Kann man auch komplett deaktivieren, wenn man das nicht möchte,

-D 1 legt fest, dass nach dem „Öffnen des Gerätes“ eine Sekunde gewartet wird, das kann hilfreich sein, bis die Webcam vollständig einsatzbereit ist-

-F 5 definiert, dass dann 5 Einzelbilder aus dem Videostream als Eingangssignal genutzt und kombiniert werden, das kann helfen Bildrauschen zu verringern, bringt aber auch die Gefahr von Geisterbildern mit sich.

/home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg gibt Dateiname, -typ und den Speicherort an, ich organisiere das datums- und zeitbasiert, deshalb werden hier Variablen genutzt

Auflösungen der Webcam herausfinden

Mögliche Werte für den Parameter zur Auflösung lassen sich übrigens „relativ“ einfach feststellen:

Über lsusb lassen sich Informationen über angeschlossene Geräte erhalten. Dabei gibt es eine Bus-ID und eine Device-ID, bei mir sieht das so aus:

pi@pi:~ $ lsusb  
Bus 001 Device 005: ID 046d:082c Logitech, Inc. HD Webcam C615  
Bus 001 Device 006: ID 1cf1:0030 Dresden Elektronik  
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter  
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub  
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Mit Bus- und Device-ID kann man den Aufruf von lsusb nun verfeinern, um Informationen für die angeschlossene Webcam (Bus 001, Device 005) abzurufen:

lsusb -s 001:005 -v | egrep „Width|Height“

Hiermit erzeugt man eine umfrangreiche (“verbose“, -v) Ausgabe der Geräteinformationen und füttert diesen Informationsstrom gleich in ein GREP, also eine Suche nach regulären Ausdrücken, in diesem Fall nach Text der „Width“ oder „Height“ enthält. Das Ergebnis ist dann eine mehr oder weniger lange Liste von Zahlenpaaren, die die möglichen Auflösungen sind.

[...]  
wWidth         1280  
wHeight         720  
wWidth         1600  
wHeight         896  
wWidth         1920  
wHeight        1080  

Die maximale Auflösung sollte das letzte Paar dieser Liste sein. Da man aus der hohen Auflösung auch das beste Video rausholen kann, habe ich also diese genommen, auch wenn die Bilder dann etwas größer werden.

Zurück zum Aufruf von fswebcam. Dieser erzeugt nun, mit den Parameter von weiter oben, jeweils ein JPEG in 1920 x 1080 Pixel und speichert das unter dem aktuellen Datums- und Zeitwert ab.

Automatisierung von fswebcam über Crontab

Wenn ich die Aufnahme nicht von Hand auslösen möchte, muss der Pi das automatisch machen. Ich habe für die Automatisierung auf Crontab oder kurz einfach „Cron“ zurückgegriffen, dass regelmäßig Aufgaben ausführen kann.

Die minimale „Zeitauflösung“ für Crons ist dabei eine Minute. Zu lang also um alle 10 Sekunden ein Bild zu machen. Hier kommt ein kleiner „Trick“ ins Spiel: Vor der Aufnahme des Bildes lassen wir den Cron einfach X Sekunden warten, um so die gewünschte Verzögerung zueinander hinzubekommen.

Mit crontab -e kann man die Editierung der Crons beginnen und dann z.B. folgendes eintragen:

* 7-16 * * * /usr/bin/fswebcam -d /dev/video0 -r 1920x1080 --banner-colour "#dd000000" --line-colour "#ff000000" -D 1 -F 5 /home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg
* 7-16 * * * sleep 10 && /usr/bin/fswebcam -d /dev/video0 -r 1920x1080 --banner-colour "#dd000000" --line-colour "#ff000000" -D 1 -F 5 /home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg
* 7-16 * * * sleep 20 && /usr/bin/fswebcam -d /dev/video0 -r 1920x1080 --banner-colour "#dd000000" --line-colour "#ff000000" -D 1 -F 5 /home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg
* 7-16 * * * sleep 30 && /usr/bin/fswebcam -d /dev/video0 -r 1920x1080 --banner-colour "#dd000000" --line-colour "#ff000000" -D 1 -F 5 /home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg
* 7-16 * * * sleep 40 && /usr/bin/fswebcam -d /dev/video0 -r 1920x1080 --banner-colour "#dd000000" --line-colour "#ff000000" -D 1 -F 5 /home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg
* 7-16 * * * sleep 50 && /usr/bin/fswebcam -d /dev/video0 -r 1920x1080 --banner-colour "#dd000000" --line-colour "#ff000000" -D 1 -F 5 /home/pi/cam/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d\%H\%M\%S).jpg

Das ist unser bekannter fswebcam-Aufruf kombiniert mit der Crontab-spezifischen Angabe für das Ausführungsintervall, in diesem Fall „jede Minute von 7 bis 16 Uhr (an jedem Tag)“. Einen praktischen Helfer für diese Syntax gibt es übrigens hier.

Das ist zunächst etwas wenig intuitiv, aber Crontab arbeitet „einschließend“. Wenn ich 7-17 als Intervall schreibe, dann läuft auch in jeder Minute der 17. Stunde noch der Job.

Wenn ich also bis 17.00 Uhr Fotos machen will, dann muss ich den Endzeitpunkt auf * 16 * * * setzen, dann läuft der Job zuletzt um 16.59 Uhr.

Wie bereits erwähnt, nutze ich hier einen Trick und verkette ein Schlafintervall (sleep 10) mit dem Aufruf der Webcam. So kann ich selbst bei minutengenauer Auflösung von Crontab auf eine höhere Auflösung „runterrechnen“.

Das Ganze ist übrigens jetzt nicht exakt auf die Sekunde genau. Aufwecken der Webcam, Foto machen und speichern etc. dauert auch alles etwas, aber so im Groben und Ganzen ist das ein 10-sekündiges Intervall.

Sobald man die Editierung des Crontab-Datei beendet hat, führt das System diese Crons aus, d.h. ab dem Moment erzeugt der Pi z.B. alle 10 Sekunden ein Bild, kein Neustart erforderlich oder ähnliches.

Bilder einmal am Tag in ein Archiv verpacken

Da der Pi etwas schwach auf der Brust sein kann, was das Erzeugen des Videos angeht, lasse ich meinen Abends alle Bilder des Tages in ein Archiv packen, das ich dann auf meinen Hauptrechner runterladen und dort zu einem Video zusammenrechnen lassen kann.

Dazu habe ich ebenfalls einen Eintrag im Crontab angelegt.

15 17 * * * tar -czvf /home/pi/cam/$(date +\%Y\%m\%d).tar.gz /home/pi/cam/$(date +\%Y\%m\%d) --warning=no-file-changed && rm -rf /home/pi/cam/$(date +\%Y\%m\%d)

Jeden Tag um 17:15 Uhr erzeuge ich ein .tar-Archiv, das als Dateiname das aktuelle Datum trägt und lege dort alle Bilder aus dem tagesaktuellen Ordner ab (die bekannte Variable für Datum ist hier wieder im Einsatz). Wenn diese Operation geglückt ist, lösche ich den Ordner mit seinen Bildern (rm -rf [...]).

Die Verkettung der beiden Befehle mit dem doppelten Ampersand (&&) bedeutet hier übrigens, dass der zweite Befehl nur dann ausgeführt wird, wenn der erste ohne Fehler abgeschlossen hat. Sollte es also ein Problem beim Erstellen des Archivs geben, dann lösche ich nicht aus Versehen die Originaldaten.

Kleiner Schönheitsfehler: Wenn man auf diese Art und Weise das Archiv erstellt, wird man eine Warnung erhalten „file changed as we read it“. Diese Antwort bei StackOverflow erklärt, woher das stammt und was man dagegen tun kann. Ich mache das etwas „unsauberer“ und unterdrücke einfach entsprechende Warnungen über den Parameter --warning, da ich mir ziemlich sicher bin, dass kein anderer Prozess was an diesen Dateien macht.

Bilder zu einem Video zusammenfügen

Nachdem ich die Archive auf meinen Hauptrechner heruntergeladen und entpackt habe, nutze ich ffmpeg um die Biler zu einem Video zusammenzufügen.

ffmpeg ist unfassbar mächtig und flexibel, jeder der sich für Audo-/Videothemen interessiert, sollte da mal ein paar Stunden mit verbringen und sich ein wenig einlesen. Ich glaub damit kann man wirklich alles machen.

Für unseren Anwendungszweck wird es nicht ganz so wild.

ffmpeg -framerate 12 -pattern_type glob -i '*.jpg' video.mp4

Dieser Aufruf erstellt ein Video mit einer Framerate von 12 fps (2 Minuten Echtzeit = 1 Sekunde Video) aus einem Eingangsstrom von Bildern.

Der Eingangsstrom ist dabei das Ergebnis eines glob-Aufrufs mit dem weit gefassten Parameter *.jpg, also allen Dateien, die auf .jpg enden. Da die Dateien nach Dateinamen sortiert sind, und der aus Datum und Uhrzeit besteht, ist die Reihenfolge automatisch korrekt.

Man kann das natürlich nur auf einzelne Unterverzeichnisse anwenden oder das glob so abwandeln, dass es tagesbasierte Videos erzeugt, ganz wie man möchte.

Endergebnis

Das Endergebnis will ich natürlich nicht vorenthalten. Hier mal das Video eines einzelnen Tages.

Verbesserungsmöglichkeiten

Der limitierende Faktor bei diesem Ansatz ist natürlich die verwendete Webcam und ihre Qualität. Eine bessere Webcam liefert bessere Bilder, damit wird natürlich auch das Video besser.

Wenn man das Ganze auf ein anderes Level heben möchte, dann bietet sich Bilderkennung mit einem Tool wie OpenCV an. Damit könnte man dann nur Bilder oder Videos aufzeichnen, wenn tatsächlich Bewegung am Vogelhäuschen herrscht. Eine schnelle Suche ergibt, dass da genug Material für diesen Ansatz existiert.


Über mich

Ich bin gelernter Mediengestalter, studierter Druck- und Medientechniker und leidenschaftlicher Tüftler und Bastler.

Beruflich beschäftige ich mich mit der digitalen Transformation von Unternehmen, sowie der Automatisierung von Unternehmensprozessen, in der Druck- und Medienbranche. Mehr dazu findet sich im Lebenslauf.

Privat interessieren mich Kaffee(maschinen), Themen rund um Webentwicklung, das Internet im Allgemeinen und Speziellen und vieles, vieles mehr.

Ich freue mich auf Feedback per E-Mail unter kontakt@flomei.de, einen Euro für die Kaffeekasse oder etwas von meiner Amazon Wunschliste.