Created
August 15, 2021 03:14
-
-
Save ThatCoolCoder/64ea921b0eaf036b25d9ecc812d3802f to your computer and use it in GitHub Desktop.
A little program to automatically capture video from a webcam for a set amount of time. Features configurable frame rate and ability to shutdown when finished. Actually made so I can see what I do in my sleep.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pygame.camera | |
import pygame.image | |
import moviepy.video.io.ImageSequenceClip | |
import os.path | |
import time | |
import shutil | |
import sys | |
import re | |
import platform | |
TITLE = ''' | |
Auto Webcam Program | |
------------------- | |
''' | |
DEFAULT_DURATION = 300 | |
DEFAULT_FRAME_RATE = 1 / 10 | |
DEFAULT_LOGGING_INTERVAL = 30 | |
OUTPUT_DIRECTORY = 'webcam-output/' | |
VIDEO_OUTPUT_FILE = os.path.join(OUTPUT_DIRECTORY, '_output.mp4') | |
def get_camera_from_user(): | |
camera_idxs = pygame.camera.list_cameras() | |
if len(camera_idxs) == 0: | |
print('Could not find any camera') | |
sys.exit() | |
print('Available cameras: ') | |
cameras = [] | |
for camera_idx in camera_idxs: | |
camera = pygame.camera.Camera(camera_idx) | |
cameras.append(camera) | |
print(f'{camera_idx}: {camera.dev.getdisplayname()}') | |
camera_idx = input('Enter a camera number from above to use: ') | |
try: | |
return cameras[int(camera_idx)] | |
except: | |
print('Invalid camera number') | |
sys.exit() | |
def get_value_from_user(prompt, converter, default_value): | |
''' Get a value from the user using input. | |
Use converter to turn it into the correct format. | |
If conversion fails, default_value is returned | |
''' | |
value = input(f'{prompt} (defaults to {default_value}): ') | |
try: | |
return converter(value) | |
except: | |
print('Invalid input, using default') | |
return default_value | |
def ask_shutdown_when_finished(): | |
return input('Do you want the computer to shutdown when recording is finished? (y/n) ') == 'y' | |
def clear_directory(directory_name): | |
for filename in os.listdir(directory_name): | |
file_path = os.path.join(directory_name, filename) | |
try: | |
if os.path.isfile(file_path) or os.path.islink(file_path): | |
os.unlink(file_path) | |
elif os.path.isdir(file_path): | |
shutil.rmtree(file_path) | |
except Exception as e: | |
print('Failed to delete %s. Reason: %s' % (file_path, e)) | |
def create_video_file(frame_rate): | |
# sorting function from https://stackoverflow.com/a/33159707/12650706 | |
image_files = [os.path.join(OUTPUT_DIRECTORY, img) for img in os.listdir(OUTPUT_DIRECTORY)] | |
image_files.sort(key=lambda f: int(re.sub('\D', '', f))) | |
clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(image_files, fps=1 / frame_rate) | |
clip.write_videofile(VIDEO_OUTPUT_FILE) | |
if __name__ == '__main__': | |
print(TITLE) | |
frame_count = 0 | |
pygame.camera.init() | |
camera = get_camera_from_user() | |
camera.start() | |
duration = 60 * get_value_from_user('Enter duration of recording in minutes', float, DEFAULT_DURATION / 60) | |
frame_rate = 1 / get_value_from_user('Enter frames per second of recording', int, int(1 / DEFAULT_FRAME_RATE)) | |
logging_interval = get_value_from_user('Enter logging interval in seconds', int, DEFAULT_LOGGING_INTERVAL) | |
shutdown_when_finished = ask_shutdown_when_finished() | |
if not os.path.exists(OUTPUT_DIRECTORY): | |
os.makedirs(OUTPUT_DIRECTORY) | |
clear_directory(OUTPUT_DIRECTORY) | |
print('Recording...') | |
start_time = time.time() | |
time_elapsed = 0 | |
while time_elapsed < duration: | |
frame_start = time.time() | |
img = camera.get_image() | |
pygame.image.save(img, os.path.join(OUTPUT_DIRECTORY, str(frame_count + 1) + '.jpg')) | |
frame_count += 1 | |
if (frame_count * frame_rate) % logging_interval == 0: | |
print(f'Recorded {int(time_elapsed)}s out of {duration}s') | |
frame_end = time.time() | |
# Use max here to stop duration being negative in first, laggy frames | |
time.sleep(max(0, frame_rate - (frame_end - frame_start))) | |
time_elapsed = time.time() - start_time | |
pygame.camera.quit() | |
print('Creating video file...') | |
create_video_file(frame_rate) | |
print('Done') | |
if shutdown_when_finished: | |
print('Shutting down...') | |
platform_name = platform.system().lower() | |
if platform_name == 'windows': | |
os.system('shutdown -s') | |
elif platform_name == 'linux': | |
os.system('shutdown') | |
else: | |
print(f'Shutdown not supported on {platform_name}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment