Skip to content

Instantly share code, notes, and snippets.

@ThatCoolCoder
Created August 15, 2021 03:14
Show Gist options
  • Save ThatCoolCoder/64ea921b0eaf036b25d9ecc812d3802f to your computer and use it in GitHub Desktop.
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.
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