#!/bin/env python3.8 import argparse import logging import sys import signal import subprocess import datetime import os.path import time import urllib.request, urllib.parse from goprocam import GoProCamera, constants # setup logging facilities logging.basicConfig(level=logging.INFO) def setup_cam(dev='gp0'): logging.info(f"Connecting to gopro camera at {dev}") return GoProCamera.GoPro(ip_address=GoProCamera.GoPro.getWebcamIP(dev), mac_address='0e:7c:80:b5:82:0e', camera=constants.gpcontrol, webcam_device=dev) def configure_cam(gp, resolution="720p", fps="60", fov="0", autooff=constants.Setup.AutoOff.Never): gp.video_settings(resolution, fps) gp.gpControlSet(constants.Setup.AUTO_OFF, autooff) def take_photo(gp, outdir='.'): logging.info('Snapping picture!') mediauri = gp.take_photo() medianame = os.path.basename(urllib.parse.urlparse(mediauri).path) outpath = os.path.join(outdir, medianame) logging.info(f"Saving to {outpath}") urllib.request.urlretrieve(mediauri, filename=outpath) def webcam(gp, outdir='.', resolution=constants.Webcam.Resolution.R720p, fov=constants.Webcam.FOV.Wide): # prepare v4l2 device if not os.path.exists('/dev/video9'): logging.info('Creating v4l2 device node at /dev/video9') subprocess.run([ 'doas -n modprobe v4l2loopback video_nr=9 card_label=GoPro9 exclusive_caps=1' ], shell=True, check=True) logging.info('Starting webcam mode') gp.webcamFOV(fov) gp.startWebcam(resolution) try: # gracefull handle sigterm def sigterm_handler(sig, frame): raise SystemExit('SIGTERM') signal.signal(signal.SIGTERM, sigterm_handler) # pipe video from camera to v4l2 device udp_stream = f"udp://{gp.getWebcamIP()}:8554" ffmpeg_args = [ f"ffmpeg -hide_banner -loglevel warning -probesize 3072 -fflags nobuffer -flags low_delay -i {udp_stream} -vsync 2 -ar 44100 -vcodec rawvideo -pix_fmt yuv420p -f v4l2 /dev/video9" ] logging.info('Running ffmpeg') # [ # 'ffmpeg -hide_banner -loglevel warning -probesize 5000 -analyzeduration 22000 -r 30 -i udp://@:8554 -an -vcodec rawvideo -pix_fmt yuv420p -r 30 -s 1280x720 -flush_packets 1 -f v4l2 /dev/video9' # ] subprocess.run(ffmpeg_args, shell=True, check=True) except (KeyboardInterrupt, SystemExit, Exception): # allow camera to shut down time.sleep(1) # stop webcam mode logging.info('Stopping webcam mode') gp.stopWebcam() # done logging.info('Exiting...') parser = argparse.ArgumentParser(description='gopro cli utility') parser.add_argument('-o', '--output', nargs=1, type=str, metavar='OUTPUT', default='.', help='Directory to save files to.') parser.add_argument('-r', '--resolution', nargs=1, type=str, metavar='RES', choices=('1080', '720', '420'), default='1080p', help='Video resolution') parser.add_argument('-f', '--fps', nargs=1, type=str, metavar='FPS', default='60', help='Video frame rate') parser.add_argument('-v', '--fov', nargs=1, type=str, metavar='FOV', choices=('wide', 'linear', 'narrow'), default='wide', help='Video field of view') parser.add_argument('--take-photo', action='store_true', help='Take a photo and save it to OUTPUT.') parser.add_argument('--webcam', action='store_true', help='Start webcam mode and register as v4l2 device') args = parser.parse_args() # get camera network device from environment # should be up and connected (with an ip address assigned) gp = setup_cam(os.getenv('GOPRO_DEVICE', 'gp0')) # configure_cam(gp, resolution=args.resolution, fps=args.fps, fov=args.fov) try: if args.take_photo: take_photo(gp, args.output) if args.webcam: webcam(gp) except Exception as err: logging.error(f"error: {err}") exit(1)