Vor einem Jahr habe ich einen Raspberry Pi Zero aufgesetzt um die Grundlage für ein Zeitraffer-Video zu erstellen, welches einen Baum im Wechsel der Jahreszeiten über ein Jahr aufnimmt. Bei 18 Aufnahmen pro Tag, sind da über 7000 Bilder aufgenommen worden (es sind tatsächlich über 13 Monate vergangen) und die Geschichte muss weiter erzählt werden.

Der Raspberry Zero 2 W hat WLAN eingebaut, was mangels Ethernet Buchse recht praktisch ist um hin und wieder die Fotos herunterzuladen und sein Betriebssystem aktuell zu halten. Ich traue einer SD Karte die ständig im Einsatz ist nicht wirklich. Da hatte ich kurz überlegt eine Freigabe meines Servers (Synology NAS) direkt einzubinden, aber dem WLAN traue ich noch weniger. Also habe ich regelmäßig die Fotos via SCP heruntergeladen und anschließend von der SD Karte gelöscht, wenn ich das Betriebssystem aktualisiert habe. Irgendwann im Laufe des Jahres habe ich, wegen einer nicht einzugrenzenden Störung, die SSID des WLAN geändert und die ursprüngliche SSID als Gast-WLAN übernommen. Leider ließ sich der Raspi nicht davon überzeugen auch das neue WLAN zu benutzen, so musste ich dann, um darauf zugreifen zu können, immer mein Notebook ins Gast-WLAN hängen, keine große Sache - dachte ich. Nach einigen Tagen reagierte der Raspi nicht mehr auf Anfragen eine SSH Verbindung aufzubauen. Ich wartete ab, bis das letzte Bild des Tages (16:30 Uhr) gemacht sein sollte und trennte ihn dann kurz vom Strom - ohne ihn zu bewegen, um den Aufnahmeausschnitt nicht zu verändern. Es zeigte sich, dass der kleine Racker fleißig weitergearbeitet hatte und alle Fotos wie gewünscht aufgenommen hatte. Nach ein paar Wochen wollte er dann aber auch nachdem ich ihn kurz vom Strom trennte, anschließend trotzdem keine SSH Verbindung mehr akzeptieren. Ich ließ ihn dann einfach in Ruhe ohne Sicherung der Bilder und ohne Updates des Betriebssystems.

Am Ende des geplanten Aufnahmezeitraumes angekommen, musste ich nur noch einen Weg finden an die Bilder zu gelangen. Windows kann mit dem ext4 Dateisystem nichts anfangen. Auch der Versuch über das Windows Subsystem für Linux (WSL2) funktionierte nicht auf Anhieb und bevor ich da viel Zeit investiere einen iSCSI Broker einzurichten den ich vermutlich nie wieder brauchen werde, habe ich einen vorhandenen USB Stick mit Linux Mint live System genutzt, um die Bilder auf den Server zu kopieren.

Da mein prefferiertes Schnittprogramm auf meinem Notebook nicht zum Laufen zu bewegen ist und mir aktuell die Kraft fehlt eine längere Sitzung am Desktop zu veranstalten, habe ich gehofft in ffmpeg einen genügsamen und potenten Helfer zu finden, aber weit gefehlt - zunächst. Ich hatte die einzelnen Fotos mit Datum und Uhrzeit im Dateinamen erstellen lassen (img-20250312-08_00.jpg), um sie gleich in der richtigen Reihenfolge vorliegen zu haben, was für einen Videoeditor mit GUI sicher auch eine gute Idee war, aber ffmpeg unterstützt unter Windows den Parameter -patteren_type glob '*.jpg' nicht, mit dem es sich die Dateien selbst in der passenden Reihenfolge zugeführt hätte. Wie ich lernen musste ist dafür POSIX Kompatibilität notwendig (welche Windows abgeht), also musste eine andere Lösung her. Ich entschied mich mit der Hilfe von Claude für einen kleinen Umweg und erstellte einem verketteten Befehl eine Textdatei, mit der ffmpeg etwas würde anfangen können.

Zuvor galt es allerdings die Dateien zu sichten und zu bereinigen. Ich kopierte die Bilder vom Server auf eine SATA SSD auf dem Notebook nach E:\Zeitraffer\, da ich das Netzwerk mit seiner Latenz aus der Codierung heraushalten wollte. Dann wählte ich einen Zeitraum von einem Jahr (12.03.2025-11.03.2026) und löschte alle darüber hinausgehenden Bilder. In der Thumbnail-Ansicht des Datei Explorers löschte ich dann noch alle Bilder, die zu dunkel oder ganz schwarz waren, denn der Aufnahmezeitraum von 8:00-16:30 Uhr ist in den Herbst.- Wintermonaten zu großzügig gewählt. Aber eigentlich war die ursprüngliche Idee ja auch 3-4 Bilder je Tag auszuwählen und nicht alle zu verarbeiten - aber bei der Durchsicht gefiel mir die umlaufende Sonne und der schmilzende Schnee doch sehr.

Verarbeitung

Die Erstellung der Dateiliste funktioniert mit Bordmitteln von Windows in der PowerShell:

Get-ChildItem E:\Zeitraffer\*.jpg | \
    Sort-Object Name | ForEach-Object { "file '$($_.fullname)'" } | \
    Out-File -Encoding utf8 E:\liste.txt
  • Get-ChildItem gibt eine Liste aller Dateien im Verzeichnis E:\Zeitraffer\ zurück, die dem Muster *.jpg entsprechen.
  • Sort-Object sortiert die Liste nach ihrem Name Attribut.
  • ForEach-Object gibt dann für jede Datei eine Zeichenfolge aus die den Wert des Attributs Fullname enthällt. Beispiel: file 'E:\Zeitraffer\img-20250312-08_00.jpg'
  • Out-File schreibt diesen dann fortlaufend, zeilenweise im UTF8 Format in die Datei E:\liste.txt

Die Installation von ffmpeg kann aus einer, mit administrativer Berechtigung aufgerufenen PowerShell erfolgen:

winget install ffmpeg

Jetzt kann ffmpeg die Arbeit in der PowerShell übergeben werden:

fmpeg -r 30 -f concat -safe 0 \
    -i e:\liste.txt -c:v libx265 -crf 20 \
    -pix_fmt yuv420p C:\Users\cs\Documents\zeitraffer.mp4
  • der Parameter -r 30 setzt die Framerate des Videos auf 30 Frames pro Sekunde.
  • der Parameter -f concat sorgt dafür, dass mehrere Mediendateien nahtlos zu einer einzigen Datei zusammengeführt werden, wobei -safe 0 die Verwendung von Dateien im aktuellen Verzeichnis erlaubt.
  • der Parameter -i e:\liste.txt übergibt die zuvor erstellte Liste mit den Bilddateien.
  • der Parameter -c:v libx265 wählt den H265 Codec zur Kodierung des Videos aus.
  • der Parameter -crf 20 lässt x265 die Bitrate automatisch anpassen und ergibt hier eine bessere Qualität als der Standardwert 23 mit fester Bitrate.
  • der Parameter -pix_fmt yuv420p erzwingt die Ausgabe von Videos im YUV 4:2:0 Pixelformat, welches für maximale Kompatibilität mit Browsern und Plattformen erforderlich ist.
  • der letzte Parameter übergibt dann noch den Namen und Pfad der Ausgabedatei, hier auf einer NVME SSD

Beispiel

Am Ende blieben 6514 Dateien in einer Auflösung von 2592x1944 Pixeln übrig, die zu einem 1,85 GB großem Video führten. Um das hier als Beispiel zu zeigen, habe ich es mit HandBrake neu in 800x600 kodiert und dabei stärker komprimiert. So bleiben lediglich 192 MB übrig.


Im Fediverse kann mitdiskutiert und Fragen beantwortet werden.

Vorheriger Beitrag