Skip to content

Instantly share code, notes, and snippets.

@constructor-s
Created July 18, 2020 04:14
Show Gist options
  • Save constructor-s/850a36279a8e5a8a101ccb83ef5459b9 to your computer and use it in GitHub Desktop.
Save constructor-s/850a36279a8e5a8a101ccb83ef5459b9 to your computer and use it in GitHub Desktop.
Raspberry Pi continous camera recording with built-in picamera and frame timestamp in Python (very low CPU usage)
import picamera
from picamera import PiCamera
import time
import signal
import sys
import threading
from datetime import datetime
CAMERA_WAIT_SEC = 1
CAMERA_ROTATE_SEC = 1800
CAMERA_H264_QUALITY = 25
CAMERA_ANNOTATE_TEXT_SIZE = 16
CAMERA_FPS = 24
camera = PiCamera(sensor_mode=4, framerate=24)
# camera.rotation = 180
camera.resolution = (640,480)
camera.annotate_text_size = CAMERA_ANNOTATE_TEXT_SIZE
camera.annotate_background = picamera.Color('black')
print(camera.sensor_mode, camera.resolution, camera.framerate)
stop_event = threading.Event()
def signal_handler(signal, frame):
print('Stopping...')
stop_event.set()
signal.signal(signal.SIGINT, signal_handler)
#now = datetime.now()
#file = 'Videos/' + now.strftime("%Y%m%d_%H%M%S") + '.h264'
#print('Starting recording to:', file)
#camera.start_recording(file, quality=40)
counter = 0
while not stop_event.is_set():
now = datetime.now()
file = 'Videos/' + now.strftime("%Y%m%d_%H%M%S") + '.h264'
print()
print('Recording to file', counter, '; filename:', file, end='')
sys.stdout.flush()
if counter == 0:
camera.start_recording(file, quality=CAMERA_H264_QUALITY)
else:
camera.split_recording(file, quality=CAMERA_H264_QUALITY)
for _ in range(round(CAMERA_ROTATE_SEC * 1.0 / CAMERA_WAIT_SEC)):
print('.', end='')
camera.annotate_text = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
camera.wait_recording(CAMERA_WAIT_SEC)
if stop_event.is_set():
break
counter += 1
camera.stop_recording()
@constructor-s
Copy link
Author

import picamera
from picamera import PiCamera
import time
import signal
import sys
import os
import threading
from datetime import datetime
import subprocess

CAMERA_WAIT_SEC = 1
CAMERA_ROTATE_SEC = 1800
CAMERA_H264_QUALITY = 30
CAMERA_ANNOTATE_TEXT_SIZE = 32
CAMERA_FPS = 15
CAMERA_RECORD_FOLDER = 'Videos'

class FileConvertThread(threading.Thread):
    def __init__(self, dryrun=False):
        super().__init__()
        self.dryrun = dryrun

    def run(self):
        files = os.listdir(CAMERA_RECORD_FOLDER)
        files.sort()
        for f in files:
            f = os.path.join(CAMERA_RECORD_FOLDER, f)
            fmkv = f[:-4] + 'mkv'
            if f.endswith('.h264'):
                # MKV file size is expected to be larger than h265
                if not os.path.exists(fmkv) or os.path.getsize(fmkv) < os.path.getsize(f):
                    command = ["ffmpeg", 
                                # "-r", str(CAMERA_FPS),
                                "-i", f, 
                                "-vcodec", "copy", 
                                fmkv]
                    print(command)
                    if not self.dryrun:
                        try:
                            print(subprocess.check_output(' '.join(command), shell=True).decode())
                            if os.path.getsize(fmkv) >= os.path.getsize(f):
                                print("Removing:", f)
                                os.remove(f)
                        except Exception as ex:
                            print('File conversion failed:')
                            print(ex)

        print('FileConvertThread finished')

    @staticmethod
    def runConvertThread():
        convert_thread = FileConvertThread()
        # threads.append(convert_thread)
        convert_thread.start()
        return convert_thread


camera = PiCamera(sensor_mode=4, framerate=CAMERA_FPS)
# camera.rotation = 180
camera.resolution = (1296,972)
camera.annotate_text_size = CAMERA_ANNOTATE_TEXT_SIZE
camera.annotate_background = picamera.Color('black')
print(camera.sensor_mode, camera.resolution, camera.framerate)

stop_event = threading.Event()
def signal_handler(signal, frame):
    print('Stopping...')
    stop_event.set()
signal.signal(signal.SIGINT, signal_handler)

#now = datetime.now()
#file = 'Videos/' + now.strftime("%Y%m%d_%H%M%S") + '.h264'
#print('Starting recording to:', file)
#camera.start_recording(file, quality=40)

counter = 0
while not stop_event.is_set():
    now = datetime.now()
    file = os.path.join(CAMERA_RECORD_FOLDER, now.strftime("%Y%m%d_%H%M%S") + '.h264')
    print()
    print('Recording to file', counter, '; filename:', file, end='')
    sys.stdout.flush()
    if counter == 0:
        convert_thread = FileConvertThread.runConvertThread()
        camera.start_recording(file, quality=CAMERA_H264_QUALITY)
    else:
        camera.split_recording(file, quality=CAMERA_H264_QUALITY)
        convert_thread = FileConvertThread.runConvertThread()

    for i in range(round(CAMERA_ROTATE_SEC * 1.0 / CAMERA_WAIT_SEC)):
        print('.', end='')
        camera.annotate_text = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        camera.wait_recording(CAMERA_WAIT_SEC)
        if stop_event.is_set():
            break

    counter += 1

camera.stop_recording()
convert_thread = FileConvertThread.runConvertThread()

convert_thread.join()

@constructor-s
Copy link
Author

@reboot screen -dmS cam bash -c 'cd /home/pi/ && python3 video_cam.py; exec bash'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment