Zeitraffer mit Linux: Unterschied zwischen den Versionen

Aus Hobbyelektronik.org
(Seite erstellt)
 
Zeile 174: Zeile 174:
 
Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen.
 
Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen.
  
= Videos basteln =
+
= Bilder verarbeiten =
(kommt die nächsten Tage)
+
Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an.
 +
 
 +
Was macht man damit? Hier ein paar Vorschläge:
 +
 
 +
= Video =
 +
 
 +
Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit [http://www.ffmpeg.org FFmpeg] verarbeiten.
 +
 
 +
Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht.
 +
 
 +
Der Desktop-PC hat da deutlich mehr Power.
 +
 
 +
Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln:
 +
 
 +
<pre>
 +
ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4
 +
</pre>
 +
 
 +
Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden.
 +
 
 +
Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird.
 +
 
 +
Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet.
  
 
[[Kategorie:Software]]
 
[[Kategorie:Software]]
 
[[Kategorie:Linux]]
 
[[Kategorie:Linux]]
 
[[Kategorie:Raspberry Pi]]
 
[[Kategorie:Raspberry Pi]]

Version vom 10. November 2013, 16:42 Uhr

Was macht man mit einem stromsparenden Computer und einer Webcam?

Die Frage habe ich mir genau zur letzten Lernphase meines Studiums gestellt und gleich mal auf die Probe gestellt, ob es möglich ist, innerhalb einer Mittagspause eine Zeitraffer-Kamera zu basteln (siehe auch hier). Wenn man als Bash-Anfänger die die Dauer der Mittagspause an die südländische Siesta annähert kann ich schon vorweg sagen: Ja, es ist möglich!

Ausgangsmaterial

Als Computer kommt der Raspberry Pi zum Einsatz. Als Webcam dient eine Logitech C310. Um die SD-Karte etwas zu schonen darf ein billiger USB-Stick zum Einsatz, der nur als Aufnahmeziel dient.

Einrichten

Kamera

Da es sich bei der Webcam um eine mit USB-Anschluss handelt, kann sie (meines Wissens) nicht ausschließlich mit dem verwendet werden, das Raspian hergibt. Mit dem Befehl lsusb kann man herausfinden, was am USB hängt:

$ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 058f:6387 Alcor Micro Corp. Flash Drive
Bus 001 Device 005: ID 046d:081b Logitech, Inc. Webcam C310

Die Webcam ist also am Computer anhängig, genauso wie der USB-Stick.

Über den Befehl ls /dev/video* werden alle Geräte angezeigt, die mit dem Namen video anfangen. Wurden also Treiber für die Kamera gefunden, erscheint sie in der Ausgabe:

$ ls /dev/video*
/dev/video0

Weil cat /dev/video0 > foo.jpg nicht so wirklich funktioniert, muss ein Vermittler her. Ich habe gute Erfahrungen mit fswebcam gemacht. Installation und Test sehen wie folgt aus:

$ sudo apt-get install fswebcam
[...]
$ fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 testimg.jpg

Der letztere Befehl nimmt ein Bild mit der Auflösung (Parameter -r) 1280x960 auf. Das -q nach der Qualitätsstufe (hier: 85) ist Absicht - bei dem Parameter handelt es sich nicht um -q wie quality, sondern um quiet. Mit -d wird das Device gewählt und anschließend folgt die Ausgabedatei. Diese kann, sofern ein Webserver installiert ist, nach /var/www verschieben oder natürlich direkt auf dem Computer ansehen. In meinem Fall wird der Raspberry "headless" betrieben und die Datei über SSH-Filetransfer auf den Haupt-PC befördert.

Funktioniert die Kamera, kann der USB-Speicher angedockt werden:

USB-Stick einbinden

Viele Wege führen bekanntlich nach Rom, genauso kann man Speicher auf verschiedene Weisen einbinden. Das hier ist eine.

Zunächst muss ein Verzeichnis angelegt werden, in das der USB-Stick später eingebunden (gemountet) wird. In meinem Fall ist dies /media/usb:

mkdir /media/usb

Nun muss herausgefunden werden, wie man den Speicher anspricht. Am besten verwendet man dessen Universally Unique Identifier (kurz UUID). Der Vorteil an diesem ist, wie der Name schon sagt, dass er Eindeutig ist. Mit dem Befehl blkid können die UUIDs aller verfügbaren Speicher angezeigt werden:

$ blkid
/dev/sda1: UUID="0CA5-719C" TYPE="vfat" LABEL="KINGSTON"
/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="C522-EA52" TYPE="vfat"
/dev/mmcblk0p2: UUID="62ba9ec9-47d9-4421-aaee-71dd6c0f3707" TYPE="ext4"

In geistiger Umnachtung habe ich den USB-Stick "KINGSTON" genannt, das hat allerdings keine Bedeutung. Wichtig ist das, was hinter "UUID=" steht. Man kann den Stick zwar schnell mit mount einbinden, nach dem nächsten Neustart hat man ihn aber verloren und das passiert - auch wenn das System stabil läuft - mit Sicherheit.

Also muss er in die fstab (file system table) eingetragen werden. Da man mit ihr nicht spielt, muss sie mit Superuser-Rechten bearbeitet werden:

$ sudo nano /etc/fstab

Die bereits vorhandenen Einträge kann man ignorieren, hier muss der zu verwendende USB-Stick hinzugefügt werden. Ist dieser mit FAT formatiert und hat die UUID 0CA5-719C, kann folgende Zeile an das Ende der Datei geschrieben werden:

UUID=0CA5-719C  /media/usb/     vfat    defaults,auto,users,noatime,umask=000,rw  0       0

Mit Strg+X Schließen und das Speichern mit Y und Druck auf die Enter-Taste bestätigen.

Navigiert man unter /media/usb kann man nun wunderbar Dateien anlegen, ABER: Diese befinden sich NICHT auf dem USB-Stick! fstab wird nur beim Neustart gelesen. Also heißt es

$ sudo reboot

eingeben und somit die Uptime auf 0 zurücksetzen.

Mit dem Befehl df kann jetzt überprüft werden, ob der Speicher richtig eingebunden wurde. Gleichzeitig sieht man auch, wie viel Speicher bereits genutzt wird:

$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
rootfs           1838936 1775400         0 100% /
/dev/root        1838936 1775400         0 100% /
devtmpfs          110568       0    110568   0% /dev
tmpfs              23768     232     23536   1% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              47520       0     47520   0% /run/shm
/dev/mmcblk0p1     57288   18960     38328  34% /boot
/dev/sda1        4006852 1591764   2415088  40% /media/usb

Der letzte Eintrag ist der interessante: /dev/sda1 ist nach /media/usb gemountet. Wenn man sich nicht sicher ist, kann man vorher von einem anderen PC eine Datei auf dem USB-Stick ablegen und mit ls /media/usb prüfen, ob diese vorhanden ist.

(Es kann sein, dass man die Berechtigung auf den Mouting-Point noch anpassen muss, da der Artikels etwas später als das damalige Einrichten entstand, bin ich mir nicht absolut sicher)

Das Zeitraffer-Script

Die Kamera funktioniert, der Zusatzspeicher ist da - nun fehlt nur noch die zeitgesteuerte Aufnahme. Am einfachsten geht das über ein kleines Script, das wahlweise direkt im Benutzerordner (home) angelegt werden kann. Der schnellste Weg nach Hause führt über den Befehl cd.

Über den Befehl

$ nano timeshot.sh

wird Nano für die (noch nicht vorhandene) Datei timeshot.sh geöffnet. Dort kann nun folgender Code eingefügt werden:

<geshi lang="bash">

  1. !/bin/sh

dt=$(date +"%Y-%m-%d") time_now=$(date +%s) time_mid=$(date -d "00:00" +%s) mins=$((($time_now-$time_mid)/60)) timestamp=`printf "%04d" $mins` dstdir=/media/usb/timelapse/$dt/

mkdir -p $dstdir fswebcam -r 1280x960 --jpeg 85 -q -d /dev/video0 $dstdir/img_$timestamp.jpg </geshi> Ganz oben kommt erst einmal der Shebang, anschließend werden ein paar Variablen definiert: In der Variable dt steht das aktuelle Datum im Format "Jahr-Monat-Datum", anschließend wird in die Variablen time_now und time_mid der Unix-Timestamp (also die Sekunden seit dem 01.01.1970) für die aktuelle Zeit und Mitternacht des aktuellen Tags geschrieben. Anschließend wird die Differenz der beiden Werte berechnet und durch 60 geteilt. Mit dem Befehl `printf "%04d" $mins` wird die Zahl auf alles "vor dem Komma" abgeschnitten und auf 4 Zeichen mit Nullen gefüllt und in die Variable timestamp geschrieben. In timestamp steht also nichts anderes als die aktuelle Minute des Tages. Warum? Später mehr dazu.

dstdir gibt, wie sich erahnen lässt, das Zielverzeichnis des Bildes an, wobei der Ordner in der tiefsten Ebene dem aktuellen Datum entspricht. Existiert dieses Verzeichnis nicht, wird es über mkdir angelegt.

Im letzten Befehl wird das bereits bekannte Programm fswebcam aufgerufen. Der endgültige Dateiname wird hier noch zusammengebaut. Vor die Minute des Tages wird noch ein "img_" vorangestellt und noch ein ".jpg" angehängt, damit die Dateien auch einen "Nachnamen" haben.

Mit Strg+X, y, Enter ist die Datei im Dateisystem, kann aber noch nicht ausgeführt werden.

Über den Befehl

$ chmod 766

gibt man der Datei Ausführungsrechte für den eigenen Benutzer. Führt man sie nun aus, bringt sie zumindest bei mir eine Warnung (die man aber ignorieren kann):

$ ./timeshot.sh
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0

Damit man nun nicht jede Minute vor dem Rechner verbringen muss, ist es zumindest empfehlenswert, die Aufnahme zeitgesteuert auszuführen. Dafür gibt es unter Linux crontab (Zeitplan).

Mit dem Befehl crontab -e öffnet man diesen für den aktuellen Benutzer. Ganz am Ende der Datei kann man nun folgendes eintragen:

* * * * * /home/pi/timeshot.sh

Was da auf den ersten Blick etwas kryptisch aussieht ist es eigentlich nicht. /home/pi/timeshot.sh deutet zumindest einmal auf die Datei hin, die ausgeführt wird. Die Sterne vorne sind Wildcards, und bedeutet so viel wie "jede". In Cron gibt man vorne die Ausführung für die Minuten, Stunden, Tage im Monat, den Monaten und Wochentage an.

Die 5 Sterne bedeuten also: "Führe die hintenstehende Datei jede Minute, jede Stunde, jeden Tag im Monat, jeden Monat und jeden Wochentag aus". Will man in der Nacht keine schwarzen Bilder sammeln, kann man auch folgende Zeile verwenden:

* 6-21 * * * /home/pi/timeshot.sh

Heißt dann so viel wie: "Führe die hintenstehende Datei jede Minute, in den Stunden von 6 bis 21, jeden Tag im Monat, jeden Monat und jeden Wochentag aus".

Damit ist aber nicht "von 6 bis 21 Uhr!" gemeint - es werden Bilder von 6:00 Uhr bis 21:59 Uhr aufgenommen.

Bilder verarbeiten

Fotos einfach der der Bilder aufnehmen macht natürlich wenig Sinn. Zunächst ist aber erst einmal die Frage: Wie viel Daten kommen überhaupt zusammen? In meinem Fall - jede Minute (also 1440 am Tag) ein Bild 1280x960 bei 85 % Qualität sammeln sich am Tag etwa 85 MiB an.

Was macht man damit? Hier ein paar Vorschläge:

Video

Naheliegend ist natürlich, ein Video der Fotos zu erstellen. Nichts leichter als das! Das ist auch der Grund, warum sie nach dem oben angegebenen Schema durchnummeriert sind. Dateien mit diesem Schema lassen sich direkt mit FFmpeg verarbeiten.

Ich wollte es auf dem Raspberry Pi machen, musste aber sehr schnell einsehen, dass man es schlichtweg vergessen kann, zumindest bei meinen Parametern - h.264 bei 2,5 Mbit/s Bitrate. Die ersten Bilder werden noch relativ schnell zusammengefügt, irgendwann kommt man aber deutlich unter 1 fps beim Codieren. Vermutlich scheitert es hier beim RAM und vermutlich verwendet FFmpeg den in Hardware vorhandenen h.264-Codec nicht.

Der Desktop-PC hat da deutlich mehr Power.

Also Bilder übertragen, in dem Ordner eine Kommandozeile öffnen und folgenden Befehl reinklöppeln:

ffmpeg.exe -f image2 -i img_%04d.jpg -vcodec libx264 -vb 2500k -acodec null -r 25 day.mp4

Die Magie kommt vom Parameter -i, in dem alle Bilder mit dem Format img_%04d.jpg zusammengestückelt werden.

Wer den Befehl in eine Batch-Datei stecken möchte, muss das % durch %% ersetzen, damit das "%0" nicht interpretiert wird.

Allerdings gibt es ein kleines Problem: Fehlt ein Bild, wird die Erstellung dort beendet.