Czy mogę nagrać 24-godzinny film na Raspberry Pi z modułem kamery?

12

Biorąc pod uwagę, że mam kartę SD o wystarczającej pojemności, czy teoretycznie możliwe jest nagrywanie 24-godzinnego wideo za pomocą modułu kamery, czy też czas nagrywania jest ograniczony? Czy ktoś tego próbował?

Czy uważasz, że 64 GB wystarcza na jakość nagrywania 360p?

Joel
źródło

Odpowiedzi:

20

Muszę przyznać, że nie wiedziałem o ograniczeniu 2 Gb w podstawowej wersji raspivid (wspomnianej w odpowiedzi Linusa). Alternatywą (jeśli nie masz ochoty na rekompilację przestrzeni użytkownika) byłoby użycie Picamera (Python obsługuje 64-bitowe wskaźniki plików od razu po wyjęciu z pudełka). Na przykład następujące osoby powinny nagrywać szerokoekranowe wideo 360p w formacie H.264 przez 24 godziny:

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

Następna część pytania dotyczy tego, czy zmieści się na karcie SD 64 GB. Moje przeczucie jest „prawdopodobnie”, ale sprawdźmy, czy ...

Enkoder Pi H.264 może otrzymać limit bitrate przy pomocy bitrateparametru w metodzie start_recording w picamerze lub --bitrateparametru w trybie raspivid. Zarówno w wersji Raspivid, jak i Picamera domyślnie jest to 17 Mb / s (megabitów na sekundę), więc teoretycznie 24-godzinny film nagrany przy ustawieniu domyślnym nie może być większy niż:

  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 ... to większe niż się spodziewałem, ale dobrze. Należy pamiętać, że domyślna 17 Mb / s ma być użyteczna przy domyślnej rozdzielczości nagrywania, która w przypadku raspivid jest pełna 1080p (chociaż domyślnie picamera ma rozdzielczość wyświetlania lub 720p w przypadku braku wyświetlania wydawało mi się „bardziej przyjazne”, kiedy to napisałem). Jeśli nagrywasz tylko w rozdzielczości 360p, prawdopodobnie uda Ci się uzyskać znacznie niższy limit przepływności.

Inną rzeczą, o której należy pamiętać, jest to, że limit bitrate jest właśnie taki: górny limit. Jeśli koder nie potrzebuje wszystkich 17 milionów bitów, aby uzyskać wystarczająco dobrą reprezentację ruchu jednej sekundy, nie użyje tak wielu. qualityBawiąc się kwantyzacją enkodera (który jest parametrem w picamerze i--qpparametr w raspivid) możemy również dostosować pojęcie enkodera o tym, co znaczy „wystarczająco dobry”. Jakość jest reprezentowana przez wartość od 0 do 40. Niższe wartości oznaczają lepszą jakość, więc 1 jest niesamowicie dobra, a 40 jest absurdalnie zła. Typowe wartości „wystarczająco dobre” wynoszą około 20–25. Wartość 0 (która jest również wartością domyślną) wydaje się być wyjątkowa; Nie jestem do końca pewien, co to znaczy dla kodera (trzeba by zapytać programistów), ale wydaje się, że zapewnia ono podobną jakość do wartości około 15-20 (tj. Bardzo dobrze).

Przy założeniu średniej jakości (powiedzmy 20), jakiej przepływności potrzebujemy, aby nagrywać wideo 360p na dużym ekranie? Dwukrotnie uruchomiłem poniższą linię poleceń, aby nagrać wideo o wartości 30 sekund, a następnie pierwsze nagranie machałem kamerą (zakładając, że więcej ruchu oznacza wymaganą większą szerokość pasma, a tutaj chcemy przetestować ograniczenia), a następnie drugi ze sceną absolutnie statyczną:

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

Pliki wynikowe miały rozmiar odpowiednio 673675 bajtów (658 KB) i 2804555 bajtów (2,7 Mb), więc bitrate generowane przez koder wynosiły:

  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)

W związku z tym, podłączając te wartości do powyższego równania, możemy realistycznie oczekiwać 24-godzinnego wideo przy użyciu podobnych ustawień, które będą miały rozmiar od 1,8 Gb do 7,5 Gb. Możemy upewnić się, że zdecydowanie nie będzie większy, ustawiając bitrate na wartość 750000, co, jak wiemy, da koderowi wystarczająco dużo miejsca do odtworzenia ruchu z pożądaną jakością (20), lub możesz eksperymentować z niższymi właściwościami (np. 25 ), aby sprawdzić, czy byłyby one dopuszczalne, a następnie odpowiednio obniżyć limit przepływności. To powiedziawszy, warto pamiętać, że prawdopodobnie złamiesz 2 Gb z plikiem, więc jak wspomniano powyżej, możesz napotkać problem z 64-bitowym wskaźnikiem pliku, chyba że użyjesz Pythona lub ponownie skompilujesz przestrzeń użytkownika.

Dla odniesienia, oto skrypt Pythona z powyższej wersji zmodyfikowany w celu uwzględnienia omówionych limitów:

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

Wreszcie, aby odpowiedzieć na komentarz goldilocks na odpowiedź Linusa: podzielenie pliku wideo na wiele części jest dość łatwe (i łatwo złagodziłoby wszelkie obawy dotyczące wskaźnika pliku 64-bitowego). W raspivid możesz użyć --segmentparametru, aby określić, że nowy plik powinien być otwierany co n milisekund, np. Aby nagrywać jeden plik na godzinę ( %02dnazwa pliku zostanie zastąpiona liczbą, np. 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

Alternatywnie za pomocą Picamera możesz użyć metody record_sequence , aby podzielić według czasu:

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)

Lub na podstawie rozmiaru pliku. W poniższym przykładzie ustawiłem go tak, aby generował 100 plików po przewinięciu, gdy każdy osiągnie> 1Mb, i umieściłem iterator wyjściowy we własnej funkcji, aby zademonstrować, że można również używać iteratorów nieskończonych 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

Lub ... cóż, bez względu na limit, jaki możesz wymyślić dla kodu!

Dave Jones
źródło
+1 Zredagowałem twoją skądinąd spektakularną odpowiedź, aby uwzględnić wyróżnianie składni.
Jacobm001
Ach, dziękuję - w pewnym momencie powinienem prawdopodobnie nauczyć się nieco więcej wariantu MD SO
Dave Jones
3

Jeśli używasz raspivid do nagrywania, jest to „możliwe”, pojawiła się łatka do obsługi dużych plików, których rozmiar> 2 GB ( -D_FILE_OFFSET_BITS=64jest wymagany w flagach dostarczanych do gcc). Musisz jednak samodzielnie skompilować źródło przestrzeni użytkownika .

Należy jednak pamiętać, że należy bardzo uważać, ponieważ jeśli zapełnisz partycję systemową w systemie Linux, może wystąpić bardzo złe zachowanie. Powinieneś więc utworzyć oddzielną partycję dla swoich długich filmów.

Dobrym pomysłem może być również zmniejszenie przepływności, jeśli masz problemy z rozmiarem pliku.

Linus
źródło
4
Jeśli jest to do zaakceptowania, możesz również uruchomić przerywany skrypt (np. Via cron), aby zatrzymać bieżący raspividproces, przejść do pliku wyjściowego i uruchomić go ponownie, tak aby uzyskać serię mniejszych plików reprezentujących określony przedział czasu.
Złotowłosa