diff options
| author | Robert Günzler <r@gnzler.io> | 2021-02-23 13:41:37 +0100 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2021-04-26 02:09:46 +0200 |
| commit | 900e7d13e097c486fd002b724f065d4dea30ac33 (patch) | |
| tree | 02b95a735a6d564d1df9888dd51937fd5d620030 /bin | |
| parent | 0600844602da163a523ba629be5e912908e3b9bc (diff) | |
add bin/gpctl; gopro control cli
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/gpctl | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/bin/gpctl b/bin/gpctl new file mode 100755 index 0000000..e74a71f --- /dev/null +++ b/bin/gpctl @@ -0,0 +1,141 @@ +#!/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) |