#! /usr/bin/ruby
# manincure.rb version 0.1
$presetMasterList = []
$hashMasterList = []
$presetCount = 0
$outputCommands =[]
class Command
@@aPSNRmetric = {"metric" => 0, "opt" => 0, "value" => 0}
@@gPSNRmetric = {"metric" => 0, "opt" => 0, "value" => 0}
@@mSSIMmetric = {"metric" => 0, "opt" => 0, "value" => 0}
@@aBitratemetric = {"metric" => 0, "opt" => 0, "value" => 0}
@@timeMetric = {"metric" => 0, "staitcOpts" => 0}
def initialize(command, presetName, iteration)
@formattedCommand = '( '+command+' ) 2>/tmp/peakaboo.log'
@presetName = presetName
@iteration = iteration
end
def getFormattedCommand
@formattedCommand
end
def getIteration
@iteration
end
def run
puts '*'+`#{@formattedCommand}`
end
def parseLog
puts '*********'
puts '*'
@averagePSNR = `cat /tmp/peakaboo.log | grep "kb/s" | awk '{print $8}' | sed -e 's/Avg://'`
puts '* Average PSNR: '+@averagePSNR.to_s
if @averagePSNR.to_f > @@aPSNRmetric["metric"].to_f
@@aPSNRmetric["metric"] = @averagePSNR.chomp
@@aPSNRmetric["presetName"] = @presetName.chomp
end
@globalPSNR = `cat /tmp/peakaboo.log | grep "kb/s" | awk '{print $9}' | sed -e 's/Global://'`
puts '* Global PSNR: '+@globalPSNR.to_s
if @globalPSNR.to_f > @@gPSNRmetric["metric"].to_f
@@gPSNRmetric["metric"] = @globalPSNR.chomp
@@gPSNRmetric["presetName"] = @presetName.chomp
end
@meanSSIM = `cat /tmp/peakaboo.log | grep "SSIM" | awk '{print $5}' | sed -e 's/Y://'`
puts '* Mean SSIM: '+@meanSSIM.to_s
if @meanSSIM.to_f > @@mSSIMmetric["metric"].to_f
@@mSSIMmetric["metric"] = @meanSSIM.chomp
@@mSSIMmetric["presetName"] = @presetName.chomp
end
@averageBitrate = `cat /tmp/peakaboo.log | grep kb/s:*| awk '{print $NF}' | awk -F\: '{print $2}'`
puts '* Average Bitrate: '+@averageBitrate.to_s
if ((@averageBitrate.to_f < @@aBitratemetric["metric"].to_f) || (@@aBitratemetric["metric"].to_f == 0))
@@aBitratemetric["metric"] = @averageBitrate.chomp
@@aBitratemetric["presetName"] = @presetName.chomp
end
puts '* Elapsed Time: '+@elapsedTime.to_s
if ( (@elapsedTime < @@timeMetric["metric"].to_f) || (@@timeMetric["metric"].to_f == 0) )
@@timeMetric["metric"] = @elapsedTime.to_s
@@timeMetric["presetName"] = @presetName.chomp
end
puts '*'
puts '*********'
end
def compareMetrics
puts '*********'
puts '*'
puts '* Results'
puts '*'
puts '*********'
puts '*'
puts '* The best average PSNR is '+@@aPSNRmetric["metric"].to_s+' from '+@@aPSNRmetric["presetName"].to_s
puts '* The best global PSNR is '+@@gPSNRmetric["metric"].to_s+' from '+@@gPSNRmetric["presetName"].to_s
puts '* The best mean SSIM is '+@@mSSIMmetric["metric"].to_s+' from '+@@mSSIMmetric["presetName"].to_s
puts '* The lowest bitrate is '+@@aBitratemetric["metric"].to_s+' from '+@@aBitratemetric["presetName"].to_s
puts '*'
puts '*********'
puts '*********'
end
def runReadAndParse(command, j)
#puts command.getFormattedCommand
puts '*'
puts '* Running: '+@presetName
puts '*'
startTime = Time.new
command.run
endTime = Time.new
@elapsedTime = endTime.to_f - startTime.to_f
command.parseLog
end
def buildDiv
div = '
| Setting | Bitrate | Avg. PSNR | Glo. PSNR | SSIM |
| '+@presetName.chomp+' | '+@averageBitrate.chomp+' | '+@averagePSNR.chomp+' | '+@globalPSNR.chomp+' | '+@meanSSIM.chomp+' |
'
@div = div
end
def Web
web = {}
web["row"] = '| '+@presetName.chomp+' | '+@averageBitrate.chomp+' | '+@averagePSNR.chomp+' | '+@globalPSNR.chomp+' | '+@meanSSIM.chomp+' |
'
return web
end
end
def buildWebPage(outputCommands)
web = []
puts 'Peakaboo Results'
puts '| Setting | Bitrate | Avg. PSNR | Glo. PSNR | SSIM |
'
outputCommands.each do |command|
web = command.Web
puts web["row"]
end
puts '
'
puts ''
end
class PresetClass
@@columnWidth=40
def initialize
rawPresets = readPresetPlist
presetStew = []
presetStew = rawPresets.split("\n")
presetStew = cleanStew(presetStew)
presetBreaks = findPresetBreaks(presetStew)
i = 0
while i <= presetBreaks.size
if i == 0 #first preset
$presetMasterList[i] = presetStew.slice(0..presetBreaks[i].to_i)
elsif i < presetBreaks.size #middle presets
$presetMasterList[i] = presetStew.slice(presetBreaks[i-1].to_i..presetBreaks[i].to_i)
else #final preset
$presetMasterList[i] = presetStew.slice(presetBreaks[i-1].to_i..presetStew.length)
end
i += 1
end
buildPresetHash
displayCommandStrings
end
def readPresetPlist # Grab the .plist and store it in presets
homeLocation = `echo $HOME`.chomp
inputFile = homeLocation+'/Library/Application\ Support/HandBrake/UserPresets.plist'
parseCommand = 'cat '+inputFile+' | sed -e \'s/<[a-z]*>//\' -e \'s/<\/[a-z]*>//\' -e \'/<[?!]/d\' '
puts "\n\n"
rawPresets = `#{parseCommand}`
end
def cleanStew(presetStew) #remove tabbed white space
presetStew.each do |oneline|
oneline.strip!
end
end
def findPresetBreaks(presetStew) #figure out where each preset starts and ends
i = 0
j = 0
presetBreaks =[]
presetStew.each do |presetLine|
if presetLine =~ /AudioBitRate/
presetBreaks[j] = i-1
j += 1
end
i += 1
end
return presetBreaks
end
def buildPresetHash #fill up $hashMasterList with hashes of all key/value pairs
j = 0
$presetMasterList.each do |singleServing| #iterate presets
tempHash = Hash.new
i = 1
while i < singleServing.length
tempHash[singleServing[i]] = singleServing[i+1]
i += 2
end
$hashMasterList[j]=tempHash
j += 1
end
end
def displayCommandStrings
$hashMasterList.each do |hash|
if hash.key?("PresetName")
#displayHeader(hash)
generateCLIString(hash)
end
end
end
def displayHeader(hash)
puts "*" * @@columnWidth
puts '* '+hash["PresetName"].to_s.center(@@columnWidth-4)+' *'
puts '~' * @@columnWidth
puts hash["PresetDescription"].to_s.center(@@columnWidth).gsub(/\n/," ").scan(/\S.{0,#{@@columnWidth-2}}\S(?=\s|$)|\S+/)
puts '~' * @@columnWidth
puts "#{hash["FileCodecs"]}".center(@@columnWidth)
if hash["Type"].to_i == 1
puts "Custom Preset".center(@@columnWidth)
end
if hash["Default"].to_i == 1
puts "This is your default preset.".center(@@columnWidth)
end
puts "~" * @@columnWidth
# puts "\n"
end
def generateCLIString(hash)
commandString = ""
commandString << './HandBrakeCLI -i ~/Movies/DVD_VIDEO -c 8 -o /Volumes/Walter/'
commandString << hash["PresetName"].gsub(' ', '_')
commandString << '.'
#Filename suffix
case hash["FileFormat"]
when /MP4/
commandString << "mp4 "
when /AVI/
commandString << "avi "
when /OGM/
commandString << "ogm "
when /MKV/
commandString << "mkv "
end
#Video encoder
if hash["VideoEncoder"] != "FFmpeg"
commandString << " -e "
if hash["VideoEncoder"] == "x264 (h.264 Main)"
commandString << "x264"
elsif hash["VideoEncoder"] == "x264 (h.264 iPod)"
commandString << "x264b30"
else
commandString << hash["VideoEncoder"].to_s.downcase
end
end
#VideoRateControl
case hash["VideoQualityType"].to_i
when 0
commandString << " -S " << hash["VideoTargetSize"]
when 1
commandString << " -b " << hash["VideoAvgBitrate"]
when 2
commandString << " -q " << hash["VideoQualitySlider"]
end
#FPS
if hash["VideoFramerate"] != "Same as source"
if hash["VideoFramerate"] == "23.976 (NTSC Film)"
commandString << " -r " << "23.976"
elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
commandString << " -r " << "29.97"
else
commandString << " -r " << hash["VideoFramerate"]
end
end
#Audio bitrate
commandString << " -B " << hash["AudioBitRate"]
#Audio samplerate
commandString << " -R " << hash["AudioSampleRate"]
#Audio encoder
commandString << " -E "
case hash["FileCodecs"]
when /AAC/
commandString << "faac"
when /AC-3/
commandString << "ac3"
when /Vorbis/
commandString << "vorbis"
when /MP3/
commandString << "lame"
end
#Container
commandString << " -f "
case hash["FileFormat"]
when /MP4/
commandString << "mp4"
when /AVI/
commandString << "avi"
when /OGM/
commandString << "ogm"
when /MKV/
commandString << "mkv"
end
#Cropping
if !hash["PictureAutoCrop"].to_i
commandString << " --crop "
commandString << hash["PictureTopCrop"]
commandString << ":"
commandString << hash["PictureBottomCrop"]
commandString << ":"
commandString << hash["PictureLeftCrop"]
commandString << ":"
commandString << hash["PictureRightCrop"]
end
#Dimensions
if hash["PictureWidth"].to_i != 0
commandString << " -w "
commandString << hash["PictureWidth"]
end
if hash["PictureHeight"].to_i != 0
commandString << " -l "
commandString << hash["PictureHeight"]
end
#Subtitles
if hash["Subtitles"] != "None"
commandString << " -s "
commandString << hash["Subtitles"]
end
#x264 Options
if hash["x264Option"] != ""
commandString << " -x "
commandString << hash["x264Option"]
end
#Booleans
if hash["ChapterMarkers"].to_i == 1 then commandString << " -m" end
if hash["PictureDeinterlace"].to_i == 1 then commandString << " -d" end
if hash["PicturePAR"].to_i == 1 then commandString << " -p" end
if hash["VideoGrayScale"].to_i == 1 then commandString << " -g" end
if hash["VideoTwoPass"].to_i == 1 then commandString << " -2" end
if hash["VideoTurboTwoPass"].to_i == 1 then commandString << " -T" end
# That's it, print to screen now
$outputCommands[$presetCount] = Command.new(commandString, hash["PresetName"], $presetCount)
$outputCommands[$presetCount].runReadAndParse($outputCommands[$presetCount], $presetCount)
$presetCount += 1
#puts "*" * @@columnWidth
puts "\n"
end
end
PresetClass.new
$outputCommands[0].compareMetrics
buildWebPage($outputCommands)