Last Updated: February 25, 2016
· erebusbat

GitShot script with support for Cinema Display

I wanted to start doing GitShots but at the office I have a Cinema display and want my pics to use that if available. This script will handle that and some other things. This allows me to keep my git hooks dead simple, but still have alot of flexability.


exit 0

snap_pic Script

!/usr/bin/env ruby

# encoding: UTF-8
require 'shellwords'
require 'optparse'
require 'ostruct'
require 'pathname'

# This uses the 'imagesnap' app (brew install imagesnap)
# and this script is based off of Victor Martinez original:
# This adds the ability to tell if I am connected to my Cinema Display and if
# so then use that camera for the pic.
# Can then use to create a movie
#  tlassemble ~/.gitshots -fps 5

# Can also use FFMPEG, but need to copy the images to a serial format.
# This will take up more disk space to produce, but the end file will be smaller than
# tlassemble
#   i=1; for f in ~/.gitshots/*.jpg; do cp -v $f "./images/$(printf '%04d' $i).jpg"; (( i ++ )); done
#   ffmpeg -r 5 -i ./images/%04d.jpg -c:v libx264 -r 15 -pix_fmt yuv420p Shots.m4v

# if for some reason your devices are different you can
# list them with `imagesnap -l`  see also
CAM_CINEMA = 'Display iSight'
CAM_ISIGHT = 'FaceTime HD Camera (Built-in)'

def cinema_display?
    display_info = `system_profiler SPDisplaysDataType`
    display_info =~ /LED Cinema Display/

def take_best_shot file_name, quite=false
    device = cinema_display? ? CAM_CINEMA : CAM_ISIGHT
    file = Shellwords.escape file_name
    puts "Capturing camera image into #{file}" unless quite
    system %Q{imagesnap -q -d "#{device}" #{file} &}

def get_defaults
        quite: false,
        dir: '~/.gitshots',
        file: "#{'%Y%m%d-%a-%H%M%S')}.jpg",  # 20131218-Wed-131403.jpg

def main
    options =
    parser  = do |opts|
        opts.banner = "Usage: snap_pic "

        opts.on('-f', '--file', "File name or path") do |v|
            options.file = v
        opts.on('-d', '--dir', "Path, ignored if --file is absolute") do |v|
            options.dir = v
        opts.on('-q', '--[no-]quite', "Shhh... I am hunting rabbits") do |v|
            options.quite = v
    parser.parse! ARGV

    # Ok now combine them
    options.dir.gsub! '~',  ENV['HOME'] if options.dir =~ /^~/
    options.file.gsub! '~', ENV['HOME'] if options.file =~ /^~/
    p = options.file
    if p.absolute?
        options.full_path = p
        p =
        p = p.realpath
        raise "Path does not exist: #{p}" unless
        options.full_path = p.join(options.file)
    options.full_path = options.full_path.to_s

    take_best_shot options.full_path, options.quite

main if $0 == __FILE__