gravar e transmitir vídeo da câmera simultaneamente

10

Estou gravando vídeo do Pi usando o Camera Module com 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()

Usei separadamente uma combinação de raspivide gstreamerpara transmitir vídeo de pi sem demora. Existe uma maneira de armazenar e transmitir imagens usando python simultaneamente ?

Meu pensamento é que deve haver uma maneira de usar a câmera como entrada e criar duas fontes de saída: um vídeo 720p para armazenamento e um vídeo 240p reduzido para streaming usando o gstreamer ...?

koogee
fonte
Se você estiver canalizando, raspividpoderá teeenviar para um arquivo e gstreamer ou qualquer outra coisa (consulte man tee). Contanto que um fluxo seja direto para o disco, isso não sobrecarregará muito, mas se você quiser processar a entrada em dois formatos diferentes simultaneamente, acho que haverá muito trabalho para o pi manipular.
goldilocks
Você pode gentilmente postar um exemplo no código?
koogee

Respostas:

5

O teecomando lê da entrada padrão e copia para qualquer número de arquivos, além da saída padrão por padrão; consulte man teepara obter mais detalhes. Isso significa que você pode pedir ao tee para criar um arquivo a partir da entrada e depois direcionar a saída para outra coisa.

A adição de um tubo extra em teoria adiciona um pouco de ineficiência. Se isso é significativo ou não, você terá que julgar por si mesmo usando seu próprio método de streaming. Meu método atual não é satisfatório em resolução total. Não é um grande interesse no momento, mas quando for, tentarei encontrar algo melhor (por exemplo, supostamente o gstreamer funciona melhor que o clvc).

No entanto, vale ressaltar que o arquivo salvo localmente no pi ao mesmo tempo é de qualidade perfeita, para que a atividade não interfira no raspivid. Aqui está um exemplo:

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

Eu quebrei isso em duas linhas para facilitar a leitura; você pode pressionar return after |(pipe) e finalizar o comando da mesma maneira que pode quebrar uma linha \. Você pode substituir o cvlccom o que quiser. Novamente, embora o fluxo tenha sido de baixa qualidade, test_video.h264saiu perfeito.

Se eu abaixar a resolução para 640x360, esse arranjo é bom, com um ou dois segundos de latência que é normalmente o que recebo. Não acho que o teeou o segundo tubo faça alguma diferença na qualidade do fluxo; eles são capazes de uma taxa de transferência muito maior do que o necessário aqui e não exigem muito em termos de recursos do sistema.

A CPU funcionou entre 35 e 45%, o mesmo que ocorre ao transmitir vídeo sem tee.

Cachinhos Dourados
fonte
Obrigado pelo seu post. Como eu quero fazer isso dentro do meu script, eu estive analisando a API PiCamera 1.9 e existe um método record_sequenceque aceita um splitter_portparâmetro. Há também um exemplo de gravação de até 4 saídas simultâneas da câmera.
koogee
Estou lutando um pouco para amarrar juntos a gravação de um fluxo de 240p e vídeo 720p para armazenamento que se divide a cada hora, mas acho que essa é uma direção promissora.
koogee
8

Nada de errado com os goldilocks responde acima, mas aqui está outro que lida especificamente com a API picamera. Você pode usar uma saída personalizada para realizar essa divisão (quantas vezes quiser) e enviar a saída para vários destinos. No seu caso, se você quiser gravar em um arquivo e um soquete, poderá fazer algo assim:

#!/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
fonte