¿Puedo grabar un video de 24 horas en la Raspberry Pi con módulo de cámara?

12

Dado que tengo una tarjeta SD con capacidad suficiente, ¿es teóricamente posible grabar un video de 24 horas con un módulo de cámara o la duración de la grabación es limitada? ¿Alguien ha probado esto?

¿Crees que 64 GB son suficientes en una calidad de grabación de 360p?

Joel
fuente

Respuestas:

20

Debo admitir que no estaba al tanto de la limitación de 2 Gb en la acumulación de stock de raspivid (mencionado en la respuesta de Linus). Una alternativa (si no desea volver a compilar el país de usuario) sería utilizar picamera (Python admite punteros de archivos de 64 bits listos para usar ). Por ejemplo, lo siguiente debería grabar un video de pantalla panorámica de 360p en H.264 felizmente durante 24 horas:

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()

La siguiente parte de la pregunta es si eso encajará en una tarjeta SD de 64 Gb. Mi presentimiento es "probablemente", pero verifiquemos que ...

El codificador H.264 de Pi puede recibir un límite de velocidad de bits con el bitrateparámetro en el método start_recording de picamera o el --bitrateparámetro en raspivid. Tanto en raspivid como en picamera, este valor predeterminado es 17Mbps (megabits por segundo), por lo que, en teoría, un video de 24 horas grabado con la configuración predeterminada no podría ser mayor que:

  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 ... eso es más grande de lo que esperaba, pero está bien. Una cosa a tener en cuenta es que el valor predeterminado de 17Mbps debe ser útil en la resolución de grabación predeterminada, que es 1080p completo en el caso de raspivid (aunque picamera tiene por defecto la resolución de pantalla o 720p en el caso de que no se muestre) parecía "más amigable" cuando lo escribí). Si solo está grabando a 360p, probablemente pueda salirse con un límite de bitrate mucho más bajo.

La otra cosa a tener en cuenta es que el límite de velocidad de bits es solo eso: un límite superior. Si el codificador no necesita los 17 millones de bits para producir una representación suficientemente buena del movimiento de un segundo, no usará tantos. Al jugar con la cuantización del codificador (que es el qualityparámetro en picamera, y el--qpparámetro en raspivid) también podemos ajustar la idea del codificador de lo que significa "suficientemente bueno". La calidad está representada por un valor entre 0 y 40. Los valores más bajos significan una mejor calidad, por lo que 1 es increíblemente bueno y 40 es ridículamente malo. Los valores típicos "suficientemente buenos" son alrededor de 20-25. El valor 0 (que también es el predeterminado) parece ser especial; No estoy seguro de lo que significa exactamente para el codificador (tendría que preguntar eso a los desarrolladores de firmware), pero parece producir una calidad similar a valores alrededor de 15-20 (es decir, muy bueno).

Entonces, suponiendo una calidad promedio (digamos 20), ¿qué tipo de tasa de bits necesitamos para grabar videos de pantalla panorámica de 360p? Ejecuté la siguiente línea de comando raspivid dos veces para grabar 30 segundos de video, luego pasé la primera grabación agitando la cámara (bajo el supuesto de que más movimiento significa más ancho de banda requerido, y queremos probar los límites aquí), y el segundo con la escena absolutamente estática:

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

Los archivos resultantes tenían 673675 bytes (658Kb) y 2804555 bytes (2.7Mb) de tamaño respectivamente, por lo que las velocidades de bits producidas por el codificador fueron:

  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)

Por lo tanto, conectando esos valores a la ecuación anterior, podemos esperar de manera realista 24 horas de video usando configuraciones similares para obtener entre 1.8Gb y 7.5Gb de tamaño. Podemos asegurarnos de que definitivamente no será más grande que eso al establecer la tasa de bits en algo como 750000, que sabemos le dará al codificador suficiente espacio para reproducir el movimiento con la calidad deseada (20), o podría experimentar con cualidades más bajas (por ejemplo, 25 ) para ver si serían aceptables y luego reducir el límite de velocidad de bits en consecuencia. Dicho esto, vale la pena tener en cuenta que es probable que rompa 2Gb con el archivo, por lo que, como se mencionó anteriormente, es probable que se encuentre con el problema del puntero de archivo de 64 bits a menos que use Python o recompile userland.

Como referencia, aquí está el script de Python de arriba modificado para incluir los límites que acabamos de discutir:

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()

Finalmente, solo para responder al comentario de Ricitos de Oro sobre la respuesta de Linus: dividir el archivo de video en varias partes es bastante fácil (y aliviará fácilmente cualquier preocupación de puntero de archivo de 64 bits). Con raspivid, puede usar el --segmentparámetro para especificar que se abra un nuevo archivo cada n milisegundos, por ejemplo, para grabar un archivo por cada hora ( %02del nombre de archivo se sustituirá por un número, por ejemplo, 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

Alternativamente, con picamera podría usar el método record_sequence para dividir en función del tiempo:

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)

O basado en el tamaño del archivo. En el ejemplo a continuación, lo configuré para que produzca 100 archivos que se transfieren una vez que cada uno alcanza> 1Mb, y coloqué el iterador de salida en su propia función solo para demostrar que también es posible usar iteradores infinitos con record_sequence:

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

O ... bueno, ¡cualquier límite que se te ocurra para el código!

Dave Jones
fuente
+1 He editado su respuesta espectacular para incluir el resaltado de sintaxis.
Jacobm001
Ah, gracias - probablemente debería aprender un poco más de la variante MD de SO en algún momento ...
David Jones
3

Si está utilizando raspivid para grabar, es "posible", ha habido un parche para admitir archivos grandes, donde el tamaño> 2 GB ( -D_FILE_OFFSET_BITS=64se requiere en las banderas suministradas a gcc). Sin embargo, debe compilar la fuente del usuario por sí mismo.

Sin embargo, debe tenerse en cuenta que debe tener mucho cuidado, ya que si llena la partición del sistema en Linux, puede producirse un comportamiento muy malo. Por lo tanto, debe crear una partición separada para sus videos largos.

También puede ser una buena idea disminuir la velocidad de bits si tiene problemas con el tamaño del archivo.

Linus
fuente
44
Si es aceptable, también puede ejecutar un script intermitente (por ejemplo, vía cron) para detener el raspividproceso actual , pasar el archivo de salida e iniciarlo nuevamente, de modo que termine con una serie de archivos más pequeños que representan segmentos de tiempo específicos.
Ricitos de oro