Bisakah saya merekam video 24 jam di Raspberry Pi dengan modul kamera?

12

Mengingat saya memiliki kartu SD dengan kapasitas yang memadai, apakah secara teori dimungkinkan untuk merekam video 24 jam dengan modul kamera atau apakah durasi perekaman terbatas? Adakah yang pernah mencoba ini?

Apakah menurut Anda 64GB cukup pada kualitas perekaman 360p?

Joel
sumber

Jawaban:

20

Saya harus mengakui bahwa saya tidak mengetahui keterbatasan 2Gb dalam stok build raspivid (disebutkan dalam jawaban Linus). Alternatif (jika Anda tidak suka mengkompilasi ulang userland) adalah menggunakan kamera (Python mendukung 64-bit file pointer di luar kotak). Misalnya, berikut ini harus merekam video 360p layar lebar di H.264 dengan bahagia selama 24 jam:

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

Bagian selanjutnya dari pertanyaan ini adalah apakah itu akan sesuai dengan kartu SD 64Gb. Firasat saya "mungkin", tetapi mari kita verifikasi bahwa ...

The Pi H.264 encoder dapat diberikan batas bitrate dengan bitrateparameter di picamera ini start_recording metode, atau --bitrateparameter dalam raspivid. Dalam kedua raspivid dan pikamera ini standarnya menjadi 17Mbps (megabit per detik) sehingga secara teoritis video 24 jam yang direkam dengan pengaturan default tidak boleh lebih besar dari:

  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 ... itu lebih besar dari yang saya harapkan, tapi oke. Satu hal yang perlu diingat adalah bahwa default 17Mbps dimaksudkan untuk berguna pada resolusi perekaman default, yang 1080p penuh dalam kasus raspivid (meskipun picamera default untuk resolusi tampilan atau 720p dalam hal tidak ada tampilan karena itu sepertinya "lebih ramah" ketika saya menulisnya). Jika Anda hanya merekam pada 360p Anda mungkin bisa lolos dengan batas bitrate jauh lebih rendah.

Hal lain yang perlu diingat adalah bahwa batas bitrate hanya itu: batas atas. Jika pembuat enkode tidak memerlukan semua 17 juta bit untuk menghasilkan representasi gerak yang cukup baik untuk satu detik, ia tidak akan menggunakan sebanyak itu. Dengan mengutak-atik kuantisasi encoder (yang merupakan qualityparameter dalam picamera, dan--qpparameter dalam raspivid) kita juga dapat menyesuaikan ide pembuat kode tentang apa yang "cukup baik" artinya. Kualitas diwakili oleh nilai antara 0 dan 40. Nilai yang lebih rendah berarti kualitas yang lebih baik, sehingga 1 sangat bagus, dan 40 sangat buruk. Nilai khas "cukup baik" adalah sekitar 20-25. Nilai 0 (yang juga merupakan default) tampaknya khusus; Saya tidak yakin apa artinya encoder (Anda harus bertanya pada firmware devs itu), tetapi tampaknya menghasilkan kualitas yang sama dengan nilai sekitar 15-20 (yaitu sangat baik).

Jadi, dengan asumsi kualitas rata-rata (katakanlah 20), bitrate macam apa yang kita butuhkan untuk merekam video 360p layar lebar? Saya menjalankan baris perintah raspivid berikut dua kali untuk merekam video senilai 30 detik, kemudian menghabiskan rekaman pertama melambaikan kamera (dengan asumsi bahwa lebih banyak gerakan berarti lebih banyak bandwidth yang diperlukan, dan kami ingin menguji batas di sini), dan yang kedua dengan adegan benar-benar statis:

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

File yang dihasilkan masing-masing berukuran 673675 byte (658Kb) dan 2804555 byte (2,7Mb), sehingga bitrate yang dihasilkan oleh encoder adalah:

  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)

Karenanya, dengan memasukkan nilai-nilai tersebut ke dalam persamaan di atas, kita dapat secara realistis mengharapkan video senilai 24 jam menggunakan pengaturan serupa untuk berada di suatu tempat di antara ukuran 1,8Gb dan 7,5Gb. Kita dapat memastikan itu tidak akan lebih besar dari itu dengan menetapkan bitrate ke sesuatu seperti 750000 yang kita tahu akan memberikan ruang yang cukup bagi pembuat enkode untuk mereproduksi gerakan pada kualitas yang kita inginkan (20), atau Anda dapat bereksperimen dengan kualitas yang lebih rendah (mis. 25 ) untuk melihat apakah mereka dapat diterima, dan kemudian menurunkan batas bitrate yang sesuai. Yang mengatakan, perlu diingat bahwa Anda cenderung untuk memecahkan 2Gb dengan file, sehingga seperti yang disebutkan di atas Anda akan mengalami masalah penunjuk file 64-bit kecuali jika Anda menggunakan Python atau mengkompilasi ulang userland.

Untuk referensi, inilah skrip Python dari atas yang dimodifikasi untuk menyertakan batasan yang baru saja didiskusikan:

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

Akhirnya, hanya untuk menanggapi komentar goldilocks pada jawaban Linus: memecah file video menjadi beberapa bagian cukup mudah (dan akan dengan mudah meringankan kekhawatiran penunjuk file 64-bit). Dengan raspivid, Anda dapat menggunakan --segmentparameter untuk menentukan bahwa file baru harus dibuka setiap n milidetik, misalnya untuk merekam satu file untuk setiap jam ( %02ddalam nama file akan diganti dengan angka, misalnya 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

Atau, dengan picamera Anda dapat menggunakan metode record_afterence untuk membagi berdasarkan waktu:

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)

Atau berdasarkan ukuran file. Pada contoh di bawah ini, saya telah mengaturnya untuk menghasilkan 100 file berguling setelah masing-masing mencapai> 1Mb, dan menempatkan iterator keluaran dalam fungsinya sendiri hanya untuk menunjukkan bahwa mungkin untuk menggunakan iterator tak terbatas record_sequencejuga dengan :

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

Atau ... yah, batasan apa pun yang dapat Anda pikirkan tentang kodenya!

Dave Jones
sumber
+1 Saya telah mengedit jawaban Anda yang spektakuler untuk memasukkan penyorotan sintaksis.
Jacobm001
Ah, terima kasih - Saya mungkin harus belajar sedikit lebih banyak tentang varian MD SO di beberapa titik ...
Dave Jones
3

Jika Anda menggunakan raspivid untuk merekam itu "mungkin", telah ada tambalan untuk mendukung file besar, di mana ukuran> 2 GB ( -D_FILE_OFFSET_BITS=64diperlukan dalam flag yang disediakan untuk gcc). Namun Anda perlu mengkompilasi sumber userland sendiri.

Namun perlu dicatat, Anda harus sangat berhati-hati, karena jika Anda mengisi partisi sistem di Linux, perilaku yang sangat buruk dapat terjadi. Jadi, Anda harus membuat partisi terpisah untuk video panjang Anda.

Mungkin juga merupakan ide bagus untuk mengurangi bit-rate jika Anda memiliki masalah dengan ukuran file.

Linus
sumber
4
Jika itu dapat diterima, Anda juga bisa menjalankan skrip intermiten (misalnya via cron) untuk menghentikan raspividproses saat ini , memutar-mutar file output, dan mulai lagi, sehingga Anda berakhir dengan serangkaian file yang lebih kecil yang mewakili irisan waktu tertentu.
goldilocks