grabar y transmitir video desde la cámara simultáneamente

10

Estoy grabando video de Pi usando Camera Module con picamera:

import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (640, 480)
    camera.start_recording('1.h264')
    camera.wait_recording(5)
    for i in range(2, 11):
        camera.split_recording('%d.h264' % i)
        camera.wait_recording(5)
    camera.stop_recording()

Por separado, he usado una combinación de raspividy gstreamerpara transmitir video desde pi sin demora. ¿Hay alguna manera de almacenar y transmitir secuencias usando Python simultáneamente ?

Mi opinión es que debe haber una manera de usar la cámara como entrada y crear dos fuentes de salida: un video de 720p para almacenamiento y un video de 240p reducido para transmitir usando gstreamer ...

koogee
fuente
Si está canalizando raspivid, podría teeenviar la salida a un archivo y gstreamer o cualquier otra cosa (ver man tee). Siempre y cuando una transmisión sea directa al disco, no agregará mucha sobrecarga, pero si desea procesar la entrada en dos formatos diferentes simultáneamente, creo que será demasiado trabajo para el pi.
Ricitos de oro
¿Pueden publicar amablemente un ejemplo en código?
koogee el

Respuestas:

5

El teecomando lee de entrada estándar y copia a cualquier número de archivos más salida estándar por defecto, vea man teepara más detalles. Esto significa que puede pedirle a tee que cree un archivo a partir de la entrada y luego canalice la salida a otra cosa.

La adición de una tubería adicional en teoría agrega un poco de ineficiencia. En cuanto a si esto es significativo o no, tendrá que juzgar por sí mismo utilizando su propio método de transmisión. Mi método actual no es satisfactorio a plena resolución. No es un gran interés en este momento, pero cuando lo sea, intentaré encontrar algo mejor (por ejemplo, supuestamente gstreamer funciona mejor que clvc).

Sin embargo, vale la pena señalar que el archivo guardado localmente en el pi al mismo tiempo es de calidad perfecta, por lo que la actividad no interfiere con raspivid. Aquí hay un ejemplo:

raspivid -o - -t 0 | tee test_video.h264 |
cvlc -v stream:///dev/stdin --sout '#standard{access=http,mux=ts,dest=:8080' :demux=h264

Rompí esto en dos líneas para facilitar la lectura; puede presionar return after |(pipe) y finalizar el comando tal como puede romper una línea \. Puedes reemplazarlo cvlccon lo que quieras. Una vez más, aunque el flujo era de baja calidad, test_video.h264salió perfecto.

Si bajo la resolución a 640x360, esta disposición está bien, con un segundo o dos de latencia, que es lo que normalmente obtengo. No creo que la teesegunda tubería haga alguna diferencia en la calidad de la transmisión; Estos son capaces de un rendimiento mucho mayor que el necesario aquí y no requieren mucho en cuanto a recursos del sistema.

La CPU funcionó al 35-45%, que es lo mismo que cuando se transmite video sin tee.

Ricitos de oro
fuente
Gracias por tu publicación. Como quiero hacer esto dentro de mi script, he estado mirando la API de PiCamera 1.9 y hay un método record_sequenceque toma un splitter_portparámetro. También hay un ejemplo de grabación de hasta 4 salidas simultáneas desde la cámara.
koogee
Estoy luchando un poco por vincular la grabación de una transmisión de 240p y un video de 720p para almacenamiento que se divide cada hora, pero siento que esta es una dirección prometedora.
koogee
8

No hay nada de malo en la respuesta anterior de Ricitos de Oro, pero aquí hay otra que trata específicamente con la API de picamera. Puede usar una salida personalizada para realizar dicha división (tantas formas como desee) y enviar la salida a una variedad de destinos. En su caso, si desea grabar en un archivo y un socket, puede hacer algo como esto:

#!/usr/bin/env python

import io
import picamera
import socket


# An output (as far as picamera is concerned), is just a filename or an object
# which implements a write() method (and optionally the flush() and close()
# methods)
class MyOutput(object):
    def __init__(self, filename, sock):
        self.output_file = io.open(filename, 'wb')
        self.output_sock = sock.makefile('wb')

    def write(self, buf):
        self.output_file.write(buf)
        self.output_sock.write(buf)

    def flush(self):
        self.output_file.flush()
        self.output_sock.flush()

    def close(self):
        self.output_file.close()
        self.output_sock.close()


# Connect a socket to a remote server on port 8000
sock = socket.socket()
sock.connect(('my_server', 8000))

with picamera.PiCamera() as camera:
    camera.resolution = (640, 480)
    camera.framerate = 24

    # Construct an instance of our custom output splitter with a filename
    # and a connected socket
    my_output = MyOutput('output.h264', sock)

    # Record video to the custom output (we need to specify the format as
    # the custom output doesn't pretend to be a file with a filename)
    camera.start_recording(my_output, format='h264')
    camera.wait_recording(30)
    camera.stop_recording()
Dave Jones
fuente