Kann ich mit dem Kameramodul ein 24-Stunden-Video auf dem Raspberry Pi aufnehmen?

12

Ist es bei einer SD-Karte mit ausreichender Kapazität theoretisch möglich, ein 24-Stunden-Video mit einem Kameramodul aufzunehmen, oder ist die Aufnahmedauer begrenzt? Hat jemand das versucht?

Denken Sie, dass 64 GB für eine 360p-Aufnahmequalität ausreichen?

Joel
quelle

Antworten:

20

Ich muss zugeben, dass mir die 2-Gbit-Beschränkung im Aktien-Build von Raspivid nicht bewusst war (wie in der Antwort von Linus erwähnt). Eine Alternative (wenn Sie keine Lust haben, das Userland neu zu kompilieren) wäre die Verwendung von Picamera (Python unterstützt 64-Bit-Dateizeiger ab Werk). Beispiel: Folgendes sollte ein Breitbild-360p-Video in H.264 24 Stunden lang aufnehmen:

import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (640, 360)
    camera.framerate = 24
    camera.start_recording('one_day.h264')
    camera.wait_recording(24 * 60 * 60)
    camera.stop_recording()

Der nächste Teil der Frage ist, ob das auf eine 64-GB-SD-Karte passt. Meine Vermutung ist "wahrscheinlich", aber lassen Sie uns das überprüfen ...

Dem H.264-Encoder von Pi kann eine Bitratenbegrenzung mit dem bitrateParameter in der start_recording- Methode der Kamera oder dem --bitrateParameter in Raspivid zugewiesen werden. Sowohl bei Raspivid als auch bei Picamera beträgt der Standardwert 17 Mbit / s (Megabit pro Sekunde). Theoretisch kann ein 24-Stunden-Video, das mit der Standardeinstellung aufgenommen wurde, nicht größer sein als:

  24         hours
* 60         minutes per hour
* 60         seconds per minute
* 17000000   bits per second
/ 8          bits per byte
/ 1073741824 bytes per gig
  ----------
  170.990825 Gb

Hmm ... das ist größer als ich erwartet hatte, aber okay. Beachten Sie, dass die Standardeinstellung von 17 Mbit / s bei der Standardaufnahmeauflösung nützlich sein soll, die bei Raspivid 1080p beträgt (Picamera verwendet jedoch standardmäßig die Anzeigeauflösung oder 720p, wenn kein Display angezeigt wird) schien "freundlicher", als ich es schrieb). Wenn Sie nur mit 360p aufnehmen, können Sie wahrscheinlich mit einer viel niedrigeren Bitratengrenze davonkommen.

Das andere, was zu beachten ist, ist, dass die Bitratengrenze genau das ist: eine obere Grenze. Wenn der Encoder nicht alle 17 Millionen Bits benötigt, um die Bewegungsdauer einer Sekunde gut genug darzustellen, werden nicht so viele verwendet. Indem Sie an der Quantisierung des Encoders qualityherumspielen (das ist der Parameter in picamera und der--qpParameter in Raspivid) können wir auch die Idee des Encoders anpassen, was "gut genug" bedeutet. Die Qualität wird durch einen Wert zwischen 0 und 40 dargestellt. Niedrigere Werte bedeuten bessere Qualität, also ist 1 wahnsinnig gut und 40 ist lächerlich schlecht. Typische "gut genug" Werte liegen bei 20-25. Der Wert 0 (der auch der Standardwert ist) scheint etwas Besonderes zu sein. Ich bin mir nicht sicher, was es genau für den Encoder bedeutet (das müsste man bei den Firmware-Entwicklern erfragen), aber es scheint eine ähnliche Qualität zu liefern wie Werte um 15-20 (dh sehr gut).

Unter der Annahme einer durchschnittlichen Qualität (sagen wir 20), welche Art von Bitrate benötigen wir, um Breitbild-360p-Videos aufzunehmen? Ich habe die folgende raspivid-Befehlszeile zweimal ausgeführt, um Videos im Wert von 30 Sekunden aufzuzeichnen, und dann die erste Aufnahme damit verbracht, die Kamera herumzuwedeln (unter der Annahme, dass mehr Bewegung mehr Bandbreite erfordert und wir hier die Grenzen testen möchten) und die zweite mit der Szene absolut statisch:

raspivid --width 640 --height 360 --framerate 24 --bitrate 17000000 --qp 20 --timeout 30000 --output test.h264

Die resultierenden Dateien hatten eine Größe von 673675 Bytes (658 KB) bzw. 2804555 Bytes (2,7 MB). Die vom Encoder erzeugten Bitraten betrugen also:

  673675   bytes
* 8        bits per byte
/ 30       seconds
  --------
  179646.6 bits per second (static scene)

  2804555  bytes
* 8        bits per byte
/ 30       seconds
  --------
  747881.3 bits per second (full motion scene)

Wenn wir diese Werte in die obige Gleichung einfügen, können wir realistisch erwarten, dass Videos mit ähnlichen Einstellungen im Wert von 24 Stunden eine Größe zwischen 1,8 und 7,5 GB haben. Wir können sicherstellen, dass es definitiv nicht größer als das ist, indem wir die Bitrate auf 750000 einstellen, wovon wir wissen, dass der Encoder genügend Platz für die Wiedergabe von Bewegungen in unserer gewünschten Qualität bietet (20), oder Sie könnten mit niedrigeren Qualitäten experimentieren (z. B. 25) ), um festzustellen, ob sie akzeptabel wären, und senken Sie die Bitratengrenze entsprechend. Das heißt, es ist zu bedenken, dass Sie wahrscheinlich 2 GB mit der Datei brechen, so dass Sie, wie oben erwähnt, wahrscheinlich auf das 64-Bit-Dateizeigerproblem stoßen, es sei denn, Sie verwenden Python oder kompilieren das Benutzerland neu.

Als Referenz wird hier das Python-Skript von oben geändert, um die soeben diskutierten Grenzen einzuschließen:

import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (640, 360)
    camera.framerate = 24
    camera.start_recording('one_day.h264', quality=20, bitrate=750000)
    camera.wait_recording(24 * 60 * 60)
    camera.stop_recording()

Um auf den Kommentar von goldilocks zu Linus 'Antwort zu antworten: Das Aufteilen der Videodatei in mehrere Teile ist recht einfach (und würde Probleme mit 64-Bit-Dateizeigern leicht beseitigen). Mit raspivid können Sie mit dem --segmentParameter festlegen, dass alle n Millisekunden eine neue Datei geöffnet werden soll , z. B. um jede Stunde eine Datei aufzuzeichnen ( %02dder Dateiname wird durch eine Zahl ersetzt, z. B. 01, 02, 03, .. .):

raspivid --width 640 --height 360 --framerate 24 --bitrate 750000 --qp 20 --timeout $((24*60*60*1000)) --segment $((1*60*60*1000)) --output hour%02d.h264

Alternativ können Sie mit picamera die Methode record_sequence verwenden, um nach der Zeit aufzuteilen:

import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (640, 360)
    camera.framerate = 24
    for filename in camera.record_sequence([
            'hour%02d.h264' % (h + 1)
            for h in range(24)
            ], quality=20, bitrate=750000):
        camera.wait_recording(60 * 60)

Oder basierend auf der Dateigröße. Im folgenden Beispiel habe ich festgelegt, dass 100 Dateien erstellt werden, die bei Erreichen von jeweils> 1 MB überschrieben werden, und den Ausgabe-Iterator in einer eigenen Funktion platziert, um zu demonstrieren, dass es möglich ist, auch unendliche Iteratoren record_sequencezu verwenden:

import io
import itertools
import picamera

def outputs():
    for i in itertools.count(1):
        yield io.open('file%02d.h264' % i, 'wb')

with picamera.PiCamera() as camera:
    camera.resolution = (640, 360)
    camera.framerate = 24
    for output in camera.record_sequence(
            outputs(), quality=20, bitrate=750000):
        while output.tell() < 1048576:
            camera.wait_recording(0.1)
        if output.name == 'file99.h264':
            break

Oder ... na ja, für welche Grenze Sie sich den Code auch immer vorstellen können!

Dave Jones
quelle
+1 Ich habe Ihre ansonsten spektakuläre Antwort so bearbeitet, dass sie Syntax-Hervorhebungen enthält.
Jacobm001
Ah, danke - ich sollte wahrscheinlich irgendwann ein bisschen mehr über die MD-Variante von SO lernen ...
Dave Jones
3

Wenn Sie raspivid zum Aufzeichnen verwenden, ist dies "möglich", da es einen Patch für die Unterstützung großer Dateien gibt, bei denen die Größe> 2 GB ist ( -D_FILE_OFFSET_BITS=64erforderlich für Flags, die an gcc gesendet werden). Sie müssen jedoch die Userland- Quelle selbst kompilieren .

Es ist jedoch zu beachten, dass Sie sehr vorsichtig sein sollten, da beim Ausfüllen der Systempartition unter Linux ein sehr schlechtes Verhalten auftreten kann. Du solltest also eine separate Partition für deine langen Videos erstellen.

Es kann auch eine gute Idee sein, die Bitrate zu verringern, wenn Sie Probleme mit der Dateigröße haben.

Linus
quelle
4
Wenn es akzeptabel ist, können Sie auch ein intermittierendes Skript ausführen (z. B. über cron), um den aktuellen raspividProzess zu stoppen , die Ausgabedatei zu verschieben und erneut zu starten, sodass Sie eine Reihe kleinerer Dateien erhalten, die bestimmte Zeitabschnitte darstellen.
Goldlöckchen