enregistrer et diffuser des vidéos depuis la caméra simultanément

10

J'enregistre une vidéo de Pi en utilisant Camera Module avec 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()

J'ai utilisé séparément une combinaison de raspividet gstreamerpour diffuser des vidéos depuis pi sans aucun délai. Existe-t-il un moyen de stocker et de diffuser des séquences à l'aide de python simultanément ?

Ma pensée est qu'il doit y avoir un moyen d'utiliser la caméra comme entrée et de créer deux sources de sortie: une vidéo 720p pour le stockage et une vidéo 240p réduite pour le streaming à l'aide de gstreamer ...?

Koogee
la source
Si vous canalisez, raspividvous pouvez teela sortie vers un fichier et gstreamer ou quoi que ce soit d'autre (voir man tee). Tant qu'un flux est directement sur le disque, cela n'ajoutera pas beaucoup de surcharge, mais si vous souhaitez traiter l'entrée dans deux formats différents simultanément, je pense que ce sera trop de travail pour le pi à gérer.
goldilocks
Pouvez-vous gentiment publier un exemple dans le code?
koogee

Réponses:

5

La teecommande lit à partir de l'entrée standard et copie dans n'importe quel nombre de fichiers plus la sortie standard par défaut, voir man teepour plus de détails. Cela signifie que vous pouvez demander à tee de créer un fichier à partir de l'entrée, puis de diriger la sortie vers autre chose.

L'ajout d'un tuyau supplémentaire ajoute en théorie un peu d'inefficacité. Quant à savoir si cela est important ou non, vous devrez juger par vous-même en utilisant votre propre méthode de streaming. Ma méthode actuelle n'est pas satisfaisante en pleine résolution. Ce n'est pas un énorme intérêt pour le moment mais quand il le sera, j'essaierai de trouver quelque chose de mieux (par exemple, soi-disant gstreamer fonctionne mieux que clvc).

Cependant, il convient de noter que le fichier enregistré localement sur le pi en même temps est de qualité parfaite, de sorte que l'activité n'interfère pas avec raspivid. Voici un exemple:

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

J'ai divisé cela en deux lignes pour plus de lisibilité; vous pouvez appuyer sur retour après |(pipe) et terminer la commande comme vous pouvez rompre une ligne avec \. Vous pouvez remplacer le cvlcpar ce que vous voulez. Encore une fois, bien que le flux soit de mauvaise qualité, il test_video.h264est sorti parfait.

Si je baisse la résolution à 640x360, cet arrangement est très bien, avec une seconde ou deux de latence, ce que j'obtiens normalement. Je ne pense pas que le teeou le deuxième tuyau fasse une différence dans la qualité du flux; ceux-ci sont capables d'un débit beaucoup plus élevé que nécessaire ici et ne nécessitent pas beaucoup de ressources système.

Le CPU a fonctionné à 35-45%, ce qui est le même que lors du streaming vidéo sans tee.

Boucles d'or
la source
Merci pour votre commentaire. Comme je veux le faire dans mon script, j'ai regardé l'API PiCamera 1.9 et il existe une méthode record_sequencequi prend un splitter_portparamètre. Il existe également un exemple d'enregistrement jusqu'à 4 sorties simultanées de la caméra.
koogee
J'ai du mal à lier ensemble l'enregistrement d'un flux 240p et d'une vidéo 720p pour le stockage qui se divise toutes les heures, mais je pense que c'est une direction prometteuse.
koogee
8

Rien de mal du tout avec la réponse goldilocks ci-dessus, mais voici une autre qui traite spécifiquement de l'API picamera. Vous pouvez utiliser une sortie personnalisée pour effectuer une telle division (autant de façons que vous le souhaitez) et envoyer la sortie vers une variété de destinations. Dans votre cas, si vous vouliez enregistrer dans un fichier et un socket, vous pourriez faire quelque chose comme ceci:

#!/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
la source