From be4586dc5365b31ccdee69ae8d2fc28cc1b507fb Mon Sep 17 00:00:00 2001 From: shoofle Date: Sat, 3 Aug 2024 14:10:01 -0400 Subject: [PATCH] first round of trying to get it to work on pi5. ffmpeg hardcoding removed. --- Pipfile | 1 + Pipfile.lock | 14 ++++-- readme.md | 10 ++++- webcam.py | 121 +++++++++++++++++++++++++-------------------------- 4 files changed, 80 insertions(+), 66 deletions(-) diff --git a/Pipfile b/Pipfile index 03ffc95..7ff9270 100644 --- a/Pipfile +++ b/Pipfile @@ -6,6 +6,7 @@ name = "pypi" [packages] opencv-python = "*" wakepy = "*" +numpy = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index c3bff7c..b748f2b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "943975627c31fb661a3a1e3a77e80b2e5634baf439d615ccba41a14d7edf09b1" + "sha256": "7b5a783544ab25fe0461f649a9e204e85f0fae1e9864e057c5ce075d5cb63eca" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,14 @@ ] }, "default": { + "jeepney": { + "hashes": [ + "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806", + "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755" + ], + "markers": "sys_platform == 'linux'", + "version": "==0.8.0" + }, "numpy": { "hashes": [ "sha256:08458fbf403bff5e2b45f08eda195d4b0c9b35682311da5a5a0a0925b11b9bd8", @@ -64,7 +72,7 @@ "sha256:f1659887361a7151f89e79b276ed8dff3d75877df906328f14d8bb40bb4f5101", "sha256:f9cf5ea551aec449206954b075db819f52adc1638d46a6738253a712d553c7b4" ], - "markers": "python_version >= '3.10'", + "index": "pypi", "version": "==2.0.1" }, "opencv-python": { @@ -78,7 +86,6 @@ "sha256:fc182f8f4cda51b45f01c64e4cbedfc2f00aff799debebc305d8d0210c43f251" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==4.10.0.84" }, "wakepy": { @@ -87,7 +94,6 @@ "sha256:fee0722b554a859724f6f47ec28db1d513f15097f235b09ebb1b58f545f90db2" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==0.9.1" } }, diff --git a/readme.md b/readme.md index 3e57cb4..47f0724 100644 --- a/readme.md +++ b/readme.md @@ -4,4 +4,12 @@ this progrram opens a fullscreen window showing a feed from camera 0 with a dela it will collect a lot of video files in the videos/ folder, and use them for showing a long (multiple minutes) delay it also holds ontoo a buffer of a couple hundred frames to show shorter delays (like 5 oor 30 seconds) it doesn't currently do anything to handle missing files, but it would be nice to give it a "default" swirly portal looking video to show -hopefully this'll run on a raspberry pi in the desert. \ No newline at end of file +hopefully this'll run on a raspberry pi in the desert. + +sudo apt install libfdk-aac2 libfdk-aac-dev python3-opencv +sudo apt install obs-studio # optional for testing? + +sudo apt install python3-pipenv +pipenv lock # ? +pipenv install +pipenv run python3 webcam.py \ No newline at end of file diff --git a/webcam.py b/webcam.py index f2cbfc7..168b800 100644 --- a/webcam.py +++ b/webcam.py @@ -12,15 +12,13 @@ def five_minute_segment_from(the_time): def path_to_video_at(time_stamp): return 'videos/' + str(time_stamp) + '.mkv' # mkv required for h264 encoding -os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"]="hwaccel;vaapi;hw_decoders_any;vaapi,vdpau" # maybe this enables hardware accelerated ffmpeg? - #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, cv2.CAP_FFMPEG) +camera = cv2.VideoCapture(0) if not camera.isOpened(): print("Cannot open camera") exit() @@ -35,7 +33,7 @@ video_writer = cv2.VideoWriter(path_to_video_at(last_time_stamp), ) # video feed from previously captured video -old_time = cv2.VideoCapture(path_to_video_at(last_time_stamp), cv2.CAP_FFMPEG) +old_time = cv2.VideoCapture(path_to_video_at(last_time_stamp)) # fullscreen window yess good cv2.namedWindow("mirror", cv2.WINDOW_NORMAL) @@ -46,65 +44,66 @@ idx = 0 # current index into the frame queue short_term_delay_frames = 20 # hoow many frames back are we going in the buffer when we're on a short term delay? longterm = False # are we shoowing a long term delay? (versus a sshort term delay) -with keep.presenting(): - while(True): - if last_time_stamp != five_minute_segment_from(datetime.now()): - # find file older than our long delay - old_file = path_to_video_at(five_minute_segment_from(datetime.now() - long_delay - timedelta(minutes=1))) - if os.path.isfile(old_file): - print(f"deleting old file {old_file}") - os.remove(old_file) - - video_writer.release() - newly_recording_file = path_to_video_at(five_minute_segment_from(datetime.now())) - - print(f"opening {newly_recording_file} too record this upcoming ssegment to") - video_writer = cv2.VideoWriter(newly_recording_file, - fourcc, - camera.get(cv2.CAP_PROP_FPS), - (int(camera.get(3)), int(camera.get(4))), - (cv2.VIDEOWRITER_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY) - ) - - - if old_time.isOpened(): - old_time.release() - - new_file = path_to_video_at(five_minute_segment_from(datetime.now() - long_delay)) - print(f"opening the previously recorded file {new_file} to read from for long mirror") - old_time = cv2.VideoCapture(new_file, cv2.CAP_FFMPEG) - - - 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 - - prev_frame_valid, prev_frame = queue[(idx - short_term_delay_frames) % len(queue)] - old_frame_valid, old_frame = old_time.read() - if not longterm and prev_frame_valid: - cv2.imshow('mirror', prev_frame) - elif longterm and old_frame_valid: - cv2.imshow('mirror', old_frame) - - 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 - - idx = (idx + 1) % len(queue) +#with keep.presenting(): +while(True): + if last_time_stamp != five_minute_segment_from(datetime.now()): + # find file older than our long delay + old_file = path_to_video_at(five_minute_segment_from(datetime.now() - long_delay - timedelta(minutes=1))) + if os.path.isfile(old_file): + print(f"deleting old file {old_file}") + os.remove(old_file) + + video_writer.release() + newly_recording_file = path_to_video_at(five_minute_segment_from(datetime.now())) + + print(f"opening {newly_recording_file} too record this upcoming ssegment to") + video_writer = cv2.VideoWriter(newly_recording_file, + fourcc, + camera.get(cv2.CAP_PROP_FPS), + (int(camera.get(3)), int(camera.get(4))), + (cv2.VIDEOWRITER_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY) + ) + + + if old_time.isOpened(): + old_time.release() + + new_file = path_to_video_at(five_minute_segment_from(datetime.now() - long_delay)) + print(f"opening the previously recorded file {new_file} to read from for long mirror") + old_time = cv2.VideoCapture(new_file, cv2.CAP_FFMPEG) + + + 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 + + prev_frame_valid, prev_frame = queue[(idx - short_term_delay_frames) % len(queue)] + old_frame_valid, old_frame = old_time.read() + if not longterm and prev_frame_valid: + cv2.imshow('mirror', prev_frame) + elif longterm and old_frame_valid: + cv2.imshow('mirror', old_frame) + + 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 + + idx = (idx + 1) % len(queue) # After the loop release the cap object camera.release() -out.release() +old_time.release() +video_writer.release() # Destroy all the windows cv2.destroyAllWindows()