nagrywać i przesyłać strumieniowo wideo z kamery jednocześnie

10

Nagrywam wideo z Pi przy użyciu modułu kamery z 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()

Użyłem osobno kombinacji raspividi gstreamerdo strumieniowego przesyłania wideo z pi bez żadnych opóźnień. Czy istnieje sposób na przechowywanie i przesyłanie strumieniowe materiału przy użyciu Pythona jednocześnie ?

Myślę, że musi istnieć sposób na wykorzystanie kamery jako wejścia i stworzenie dwóch źródeł wyjściowych: wideo 720p do przechowywania i zmniejszone wideo 240p do przesyłania strumieniowego za pomocą gstreamer ...?

koogee
źródło
Jeśli używasz pipingu, raspividmożesz teewyprowadzić dane wyjściowe do pliku i gstreamera lub cokolwiek innego (patrz man tee). Tak długo, jak jeden strumień jest prosto na dysk, nie spowoduje to dużego obciążenia, ale jeśli chcesz przetwarzać dane wejściowe w dwóch różnych formatach jednocześnie, myślę, że będzie to zbyt dużo pracy dla pi.
złotowłosy
Czy możesz uprzejmie zamieścić przykład w kodzie?
koogee

Odpowiedzi:

5

teeKomenda czyta ze standardowego wejścia i kopiuje do dowolnej liczby plików plus produkcję standardowej domyślnie zobaczyć man teewięcej szczegółów. Oznacza to, że możesz poprosić tee o utworzenie pliku na podstawie danych wejściowych, a następnie potokowanie danych wyjściowych do czegoś innego.

Dodanie dodatkowej rury teoretycznie dodaje nieco nieefektywności. Jeśli chodzi o to, czy jest to znaczące, czy nie, będziesz musiał sam ocenić, korzystając z własnej metody przesyłania strumieniowego. Moja obecna metoda nie jest zadowalająca przy pełnej rozdzielczości. W tej chwili nie jest to duże zainteresowanie, ale kiedy to nastąpi, spróbuję znaleźć coś lepszego (np. Rzekomo gstreamer działa lepiej niż clvc).

Warto jednak zauważyć, że plik zapisany lokalnie na pi w tym samym czasie ma doskonałą jakość, więc aktywność nie przeszkadza w malowaniu. Oto przykład:

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

Podzieliłem to na dwie linie dla czytelności; możesz nacisnąć return after |(potok) i zakończyć polecenie tak, jak możesz przerwać linię \. Możesz zamienić na cvlcco chcesz. Znów, chociaż strumień był niskiej jakości, test_video.h264wyszedł idealnie.

Jeśli obniżę rozdzielczość do 640x360, to ustawienie jest w porządku, z drugim lub dwoma opóźnieniami, które zwykle otrzymuję. Nie sądzę, aby teedruga lub druga rura miała jakikolwiek wpływ na jakość strumienia; są one zdolne do znacznie większej przepustowości niż jest to konieczne i nie wymagają dużo zasobów systemowych.

Procesor działał na poziomie 35–45%, czyli tak samo jak podczas przesyłania strumieniowego wideo sans tee.

Złotowłosa
źródło
Dziękuję za Twój post. Ponieważ chcę to zrobić w swoim skrypcie, przyjrzałem się API PiCamera 1.9 i istnieje metoda, record_sequencektóra przyjmuje splitter_portparametr. Istnieje również przykład nagrywania do 4 jednoczesnych wyjść z kamery.
koogee
Trudno mi się trochę związać, nagrywając strumień 240p i wideo 720p do przechowywania, które dzieli się co godzinę, ale czuję, że jest to obiecujący kierunek.
koogee
8

W powyższej odpowiedzi nie ma nic złego, ale oto dodatkowa, która dotyczy konkretnie API Picamera. Możesz użyć niestandardowego wyjścia, aby wykonać taki podział (na wiele sposobów) i wysłać wynik do różnych miejsc docelowych. W twoim przypadku, jeśli chcesz nagrać do pliku i gniazda, możesz zrobić coś takiego:

#!/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
źródło