from datetime import datetime, date, time, timedelta import os import cv2 import gpiod from gpiod import Direction, Value #from wakepy import keep def five_minute_segment_from(the_time): # this is mocked out too be a one minute segment instead return the_time.replace(second=0, microsecond=0) #return the_time.replace(minute=(the_time.minute // 1)*1, second=0, microsecond=0) def path_to_video_at(time_stamp): return 'videos/' + str(time_stamp) + '.mkv' # mkv required for h264 encoding #delay for long delay long_delay = timedelta(minutes=1) last_time_stamp = five_minute_segment_from(datetime.now()) # live webcam feed camera = cv2.VideoCapture(0) if not camera.isOpened(): print("Cannot open camera") exit() # video writer fourcc = cv2.VideoWriter_fourcc(*'H264') camera_fps = camera.get(cv2.CAP_PROP_FPS) video_writer = cv2.VideoWriter(path_to_video_at(last_time_stamp), fourcc, camera_fps, (int(camera.get(3)),int(camera.get(4))), #resolution (cv2.VIDEOWRITER_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY) ) # video feed from previously captured video twenty_four_hours_ago = cv2.VideoCapture(path_to_video_at(last_time_stamp - timedelta(hours=24))) twelve_hours_ago = cv2.VideoCapture(path_to_video_at(last_time_stamp - timedelta(hours=12))) five_minutes_ago = cv2.VideoCapture(path_to_video_at(last_time_stamp - timedelta(minutes=5))) # fullscreen window yess good cv2.namedWindow("mirror", cv2.WINDOW_NORMAL) cv2.setWindowProperty("mirror", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) queue = [(False, None)] * math.floor(camera_fps * 32) #queue of 32 seconds of frames idx = 0 # current index into the frame queue lines = { "five_second": 1, "thirty_second": 2, "five_minute": 3, "twelve_hour": 4, "twenty_four_hour": 5 } #with keep.presenting(): with gpiod.request_lines( "/dev/gpiochip0", consumer="mirror-to-yesterday", config={ lines.five_second: gpiod.LineSettings(direction=Direction.INPUT), lines.thirty_second: gpiod.LineSettings(direction=Direction.INPUT), lines.five_minute: gpiod.LineSettings(direction=Direction.INPUT), lines.twelve_hour: gpiod.LineSettings(direction=Direction.INPUT), lines.twenty_four_hour: gpiod.LineSettings(direction=Direction.INPUT) } ) as io_lines: while(True): if last_time_stamp != five_minute_segment_from(datetime.now()): # find file older than our long delay oldest_file_path = path_to_video_at(five_minute_segment_from(datetime.now() - timedelta(hours=24) - timedelta(minutes=10))) if os.path.isfile(oldest_file_path): print(f"deleting old file {oldest_file_path}") os.remove(oldest_file_path) video_writer.release() newly_recording_file_path = path_to_video_at(five_minute_segment_from(datetime.now())) print(f"opening {newly_recording_file_path} too record this upcoming ssegment to") video_writer = cv2.VideoWriter(newly_recording_file_path, fourcc, camera_fps, (int(camera.get(3)), int(camera.get(4))), (cv2.VIDEOWRITER_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY) ) if twenty_four_hours_ago.isOpened(): twenty_four_hours_ago.release() twenty_four_hours_ago = cv2.VideoCapture(path_to_video_at(five_minute_segment_from(datetime.now() - timedelta(hours=24)))) if twelve_hours_ago.isOpened(): twelve_hours_ago.release() twelve_hours_ago = cv2.VideoCapture(path_to_video_at(five_minute_segment_from(datetime.now() - timedelta(hours=12)))) if five_minutes_ago.isOpened(): five_minutes_ago.release() five_minutes_ago = cv2.VideoCapture(path_to_video_at(five_minute_segment_from(datetime.now() - timedelta(minutes=5)))) last_time_stamp = five_minute_segment_from(datetime.now()) ret, frame = camera.read() frame = cv2.flip(frame, 1) # record the frame to the appropriate file, and also to the short term buffer video_writer.write(frame) queue[idx] = ret, frame frames = { "five_second": queue[(idx - math.floor(5*camera_fps)) % len(queue)], "thirty_second": queue[(idx - math.floor(30*camera_fps)) % len(queue)], "five_minute": five_minutes_ago.read(), "twelve_hour": twelve_hours_ago.read(), "twenty_four_hour": twenty_four_hours_ago.read(), } #valid, the_frame = frames.five_second if io_lines.get_value(lines.twenty_four_hour): valid, the_frame = frames.twenty_four_hour elif io_lines.get_value(lines.twelve_hour): valid, the_frame = frames.twelve_hour elif io_lines.get_value(lines.five_minute): valid, the_frame = frames.five_minute elif io_lines.get_value(lines.thirty_second): valid, the_frame = frames.thirty_second else: #if io_lines.get_value(lines.five_second) valid, the_frame = frames.five_second if valid: cv2.imshow("mirror", the_frame) idx = (idx + 1) % len(queue) key = cv2.waitKey(16) # listen for keyprress for 16 ms if key & 0xFF == ord('q') or key == 27: # q or esc break """if key & 0xFF == ord('a'): short_term_delay_frames += 1 if key & 0xFF == ord('d'): short_term_delay_frames -= 1 if key & 0xFF == ord('z'): longterm = not longterm""" # After the loop release the cap object camera.release() video_writer.release() twenty_four_hours_ago.release() twelve_hours_ago.release() five_minutes_ago.release() # Destroy all the windows cv2.destroyAllWindows()