Могу ли я записать 24-часовое видео на Raspberry Pi с модулем камеры?

12

Учитывая, что у меня есть SD-карта достаточной емкости, теоретически возможно ли записать 24-часовое видео с помощью модуля камеры или продолжительность записи ограничена? Кто-нибудь пробовал это?

Как вы думаете, 64 ГБ будет достаточно для качества записи 360p?

Joel
источник

Ответы:

20

Я должен признать, что я не знал об ограничении в 2 Гб в билде распивид (упомянуто в ответе Линуса). Альтернативой (если вы не хотите перекомпилировать пользовательское пространство) будет использование picamera (Python поддерживает 64-битные файловые указатели из коробки). Например, следующее должно с радостью записывать широкоэкранное видео 360p в формате H.264 в течение 24 часов:

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

Следующая часть вопроса заключается в том, поместится ли она на SD-карту 64 Гб. Моя догадка "вероятно", но давайте проверим это ...

Кодер H.264 Пи может быть дан битрейт предел с bitrateпараметром в picamera в start_recording метода, или --bitrateпараметра в raspivid. И в raspivid, и в picamera это значение по умолчанию равно 17 Мбит / с (мегабит в секунду), поэтому теоретически 24-часовое видео, записанное с настройкой по умолчанию, не может быть больше, чем:

  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

Хм ... это больше, чем я ожидал, но хорошо. Следует иметь в виду, что значение по умолчанию, равное 17 Мбит / с, должно быть полезным при разрешении записи по умолчанию, которое составляет полное 1080p в случае распечатывания (хотя picamera по умолчанию имеет разрешение дисплея или 720p в случае отсутствия отображения, так как казалось "дружелюбнее", когда я это написал). Если вы записываете только в формате 360p, вы, вероятно, можете избежать гораздо более низкого битрейта.

Другая вещь, которую нужно иметь в виду, это то, что предел битрейта - это только верхний предел. Если кодировщику не нужны все 17 миллионов битов, чтобы получить достаточно хорошее представление о значении движения за одну секунду, он не будет использовать это количество. Путем манипулирования с квантованием кодера (который является qualityпараметром в Picamera, и--qpпараметр в raspivid) мы также можем настроить представление кодировщика о том, что означает «достаточно хороший». Качество представлено значением от 0 до 40. Более низкие значения означают лучшее качество, поэтому 1 - безумно хорошее, а 40 - смехотворно плохое. Типичные «достаточно хорошие» значения составляют около 20-25. Значение 0 (которое также является значением по умолчанию) представляется специальным; Я не уверен точно, что это значит для кодировщика (вам нужно спросить об этом разработчиков программного обеспечения), но, похоже, он дает схожее качество со значениями около 15-20 (то есть очень хорошо).

Итак, исходя из среднего качества (скажем, 20), какой битрейт нам нужен для записи широкоэкранного видео 360p? Я дважды выполнил следующую распущенную командную строку, чтобы записать 30-секундное видео, а затем провел первую запись, размахивая камерой (в предположении, что больше движения означает большую полосу пропускания, и мы хотим проверить здесь ограничения), и вторую со сценой абсолютно статично:

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

Полученные файлы имели размер 673675 байт (658 КБ) и 2804555 байт (2,7 МБ) соответственно, поэтому битрейты, создаваемые кодером:

  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)

Следовательно, вставляя эти значения в приведенное выше уравнение, мы можем реально ожидать, что видео за 24 часа, используя аналогичные настройки, будет иметь размер от 1,8 ГБ до 7,5 ГБ. Мы можем убедиться, что он определенно не будет больше этого, установив битрейт на что-то вроде 750000, что, как мы знаем, даст кодеру достаточно места для воспроизведения движения с нашим желаемым качеством (20), или вы можете поэкспериментировать с более низкими качествами (например, 25 ), чтобы увидеть, будут ли они приемлемыми, и затем соответственно снизить предел битрейта. Тем не менее, стоит иметь в виду, что вы, скорее всего, порвете файл размером 2 ГБ, поэтому, как уже упоминалось выше, вы можете столкнуться с проблемой 64-битного указателя файла, если вы не используете Python или не перекомпилируете пользовательское пространство.

Для справки вот скрипт Python сверху, модифицированный для включения только что обсужденных ограничений:

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

Наконец, просто чтобы ответить на комментарий Златовласки к ответу Линуса: разбить видеофайл на несколько частей довольно легко (и он легко облегчит любые проблемы с 64-битными указателями файлов). С помощью raspivid вы можете использовать --segmentпараметр, чтобы указать, что новый файл должен открываться каждые n миллисекунд, например, для записи одного файла за каждый час ( %02dв имени файла будет подставлено число, например 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

Кроме того, с Picamera вы можете использовать метод record_sequence для разделения на основе времени:

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)

Или в зависимости от размера файла. В приведенном ниже примере я настроил его на создание 100 файлов, прокручивающихся после того, как каждый из них достигнет> 1 МБ, и поместил выходной итератор в свою собственную функцию, чтобы продемонстрировать, что можно использовать и бесконечные итераторы 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

Или ... ну, какой бы предел вы ни думали о коде!

Дейв Джонс
источник
+1 Я отредактировал ваш по-другому впечатляющий ответ, чтобы включить подсветку синтаксиса.
Jacobm001
Ах, спасибо - я, вероятно, должен был бы узнать немного больше о варианте MD SO в какой-то момент ...
Дейв Джонс
3

Если вы используете raspivid для записи, это «возможно», был патч для поддержки больших файлов, размер которых> 2 ГБ ( -D_FILE_OFFSET_BITS=64требуется для флагов, предоставляемых gcc). Однако вы должны скомпилировать уровня пользователя источник самостоятельно.

Следует отметить, однако, что вы должны быть очень осторожны, потому что, если вы заполняете системный раздел в Linux, может произойти очень плохое поведение. Так что вы должны создать отдельный раздел для ваших длинных видео.

Также может быть хорошей идеей уменьшить скорость передачи данных, если у вас есть проблемы с размером файла.

Линус
источник
4
Если это приемлемо, вы также можете запустить прерывистый сценарий (например, через cron), чтобы остановить текущий raspividпроцесс, перенести выходной файл и запустить его снова, так что в итоге вы получите ряд меньших файлов, представляющих определенные отрезки времени.
Златовласка