Hoof

ruby script for my phone to help me crop and trim video
			#!/usr/bin/env ruby

INPUTDIR = "./storage/dcim/OpenCamera"
OUTPUTDIR = "./storage/movies"
# clear the screen
puts `clear`

# do the needed dirs exists?
raise "input directory must exist" unless Dir.exist? INPUTDIR
raise "output directory must exist" unless Dir.exist? OUTPUTDIR

# has a file been passed in?
targetVid = File.expand_path(ARGV[0]) if ARGV[0]

# start building the final command as an array
cmdArray = ["ffmpeg -y -noautorotate"]

# get latest video path as a string unless the target vid exists
unless targetVid
	vids = Dir.glob("VID*", base: INPUTDIR)
	maxTime = nil
	newestFile = nil
	vids.each do |f|
		target = File.join(INPUTDIR, f)
		modTime = File.mtime(target)
		if maxTime.nil? or modTime > maxTime 
			newestFile = target
			maxTime = modTime
		end
	end

	puts newestFile
	targetVid = newestFile
end
input = targetVid.chomp()


# get the width and height and rotation
dataString = `ffprobe -show_streams #{input} 2>&1`
# get the width and height

matches = /^width=([0-9]*)/.match(dataString)
if matches
	vidWidth =matches[1].to_i
else
	errorMessage "width not found"
end
matches = /^height=([0-9]*)/.match(dataString)
if matches
	vidHeight =matches[1].to_i
else
	errorMessage "error height not found"
end
matches = /^rotation=([-0-9]*)/.match(dataString)
if matches
	vidRotation =matches[1].to_i
else
	# no rotation detected
	vidRotation=0
end

puts "width: #{vidWidth}"
puts "height: #{vidHeight}"
puts "rotation: #{vidRotation}"


# add the input to the cmd array
cmdArray << "-i #{input}"

# make the video pinner?
puts "scale to 480px? (y/N)"
i = STDIN.gets.strip()
if i=='y'
	videoScale = 480
	vBrate = 800
	aBrate = 64
	frameRate = 15
else
	videoScale = 600
	vBrate = 1500
	aBrate = 96
	frameRate = 24
end
# set the rates
cmdArray << "-b:a #{aBrate}k -b:v #{vBrate}k -r #{frameRate}"



# get some info about the video	
durString =`ffmpeg -i #{input} 2>&1 | grep Duration:`

# duration is "Duration: (HH:MM:SS), ..."
matches = /.*Duration: ([0-9:\.]*),/.match(durString)
if matches
	INPUT_DURATION = matches[1]
else
	errorMessage "Duration not detected"
end

# set the scaling for the video filter
if vidRotation == -90
  scale = "#{videoScale}:-2"
else 
  scale = "-2:#{videoScale}"
end
   
# begin building the video filter  
videoFilter="-filter:v scale=#{scale}:force_original_aspect_ratio=decrease"


# split the string to get the vid name
pathParts = input.split("/")

# the last part is the filename
fName = pathParts[-1]

puts "Resizing #{fName}"

# define output file
output = OUTPUTDIR+"/"+fName

puts "Crop? (y/N)"
i = STDIN.gets.downcase.strip()

if i == "y"
	# begin building the crop string
	cropString =",crop=#{videoScale}:#{videoScale}"
	puts "crop from:\n  a : top\n  b : center\n  c : bottom"
	x = STDIN.gets.strip()
	crop = case x  
	when 'a'
		cropString+=":0:0"
	when 'b'
		#center crop?
	when 'c'
		cropString+=":iw-#{videoScale}:ih-#{videoScale}"
	end 
	# add the crop to the video filter
	videoFilter+=cropString
end
# add the video filter 
cmdArray << videoFilter

# trim...
puts "Trim? (y/N)"
i = STDIN.gets.downcase.strip()
if i == 'y'
	# get the trim start
	puts "trim start time in MM:SS format. Leave blank to trim from start of video"
	trimStart = STDIN.gets.strip()
	trimStart = "00:00" if trimStart.empty?
	cmdArray << "-ss #{trimStart}"

	# get the trim end
	puts "trim end time in MM:SS format. Leave blank to trim to end of video"
	trimEnd = STDIN.gets.strip() 
	trimEnd = INPUT_DURATION if trimEnd.empty?
	cmdArray << "-to #{trimEnd}"
end

# append the output
cmdArray << "#{output}"

# what is the actual command?
cmd = cmdArray.join(" ")
puts "Run  #{cmd}? (Y/n)"
i=STDIN.gets.strip
puts `#{cmd}` unless i=='Y'