Skip to content

Instantly share code, notes, and snippets.

@Konstantinusz
Created April 6, 2015 20:01
Show Gist options
  • Save Konstantinusz/0a436f57de5236265f9e to your computer and use it in GitHub Desktop.
Save Konstantinusz/0a436f57de5236265f9e to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby
require "optparse"
require "time"
require "tmpdir"
abr=96
size=495
input_file=""
output_file=""
gamma =1.0
colour_sat=1.0
preset="veryslow"
resize_width=640
OptionParser.new do |opts|
# Default banner is "Usage: #{opts.program_name} [options]".
# Argument must match a regular expression.
opts.on("-s", "--size SIZE",/[0-9]+/ ,"video size with audio in megabytes (1024*1024)") {|arg| size = arg.to_i}
opts.on("-a", "--audio-bitrate ABR",/[0-9]+/, "audio bitrate in kbps") {|arg| abr = arg.to_i}
opts.on("-i", "--input INPUT_VIDEO_FILENAME",/.+/i,"video filename to process") {|arg| input_file = arg}
opts.on("-o", "--output OUTPUT_VIDEO_FILENAME",/.+/i,"video filename to write output") {|arg| output_file = arg}
opts.on("-g", "--gamma GAMMA",/[0-9]+(?:\.[0-9]+)?/,"gamma to apply") {|arg| gamma = arg}
opts.on("-c", "--colour-saturation SAT",/[0-9]+(?:\.[0-9]+)?/,"colour saturation to apply") {|arg| colour_sat = arg}
opts.on("-p", "--encoding-preset PRESET",["fast","medium","slow","veryslow"],"AVC encoding preset") {|arg| preset = arg}
opts.on("-r", "--resize-width WIDTH",/[0-9]+/,"resize width to new WIDTH") {|arg| resize_width = arg.to_i}
opts.on_tail("-h", "--help", "Show this message") do
STDERR.puts opts
exit
end
begin
# Parse and remove options from ARGV.
opts.parse!
rescue OptionParser::ParseError => error
# Without this rescue, Ruby would print the stack trace
# of the error. Instead, we want to show the error message,
# suggest -h or --help, and exit 1.
$stderr.puts error
$stderr.puts "(-h or --help will show valid options)"
exit 1
end
end
script_path=File.dirname(__FILE__)
working_dir=Dir.mktmpdir
system "ln -s #{script_path}/ffms2.dll #{working_dir}/ffms2.dll"
system "ln -s #{script_path}/MaskTools.dll #{working_dir}/MaskTools.dll"
system "ln -s #{script_path}/ylevels.avsi #{working_dir}/ylevels.avsi"
system "ln -s \"#{File.expand_path(input_file)}\" \"#{working_dir}/#{input_file}\""
ret=%x{ffmpeg -i \"#{input_file}\" 2>&1}
d=Time.parse(ret.scan(/Duration\:(.*?)\,/).flatten[0])
width_height=ret.scan(/,\s*([0-9]+)x([0-9]+)/).flatten.map{|z| z.to_i}
width=width_height[0]
height=width_height[1]
ar=width.fdiv height
a=(resize_width.fdiv ar).round
resize_height=(a % 4)<=1 ? a - (a % 4) : a + 4 - (a % 4)
duration_in_sec=3600*d.hour+60*d.min+d.sec
target_bytes = size * 1024 * 1024
audio_bytes = ((abr * 1000) / 8) * duration_in_sec
bitrate=(((target_bytes - audio_bytes) / duration_in_sec * 8).fdiv 1000).round
avs_content=<<END
loadplugin("ffms2.dll")
loadplugin("MaskTools.dll")
import("ylevels.avsi")
ffvideosource("#{input_file}")
lanczos4resize(#{resize_width},#{resize_height})
ylevels(gamma=#{gamma})
tweak(0,#{colour_sat},0,1)
END
input_file_avs="#{input_file}.avs"
File.write("#{working_dir}/#{input_file_avs}",avs_content)
pass_1_preset=preset
pass_1_bit_rate=bitrate
pass_2_preset=preset
pass_2_bit_rate=bitrate
command=%Q{wine #{script_path}/avs2yuv.exe \"#{working_dir}/#{input_file_avs}\" - | ffmpeg -y -f yuv4mpegpipe -i - -an -pass 1 -vcodec libx264 -preset #{pass_1_preset} -pass 1 -b:v #{pass_1_bit_rate}k -movflags +faststart -threads 0 -wpredp 2 -f mp4 pass1.mp4 && wine "#{script_path}/avs2yuv.exe" "#{working_dir}/#{input_file_avs}" - | ffmpeg -y -f yuv4mpegpipe -i - -i #{input_file} -map 0:v -map 1:a -c:v libx264 -preset #{pass_2_preset} -b:v #{pass_2_bit_rate}k -ac 2 -c:a libvorbis -b:a #{abr.to_s}k -strict -2 -pass 2 -movflags +faststart -threads 0 -wpredp 2 -y \"#{output_file}\"}
puts command
binding.local_variables.each{|z| puts "#{z} -> #{temp=eval(z.to_s).to_s.gsub("\n","\\n");temp.size>70 ? temp[0..69]+"..." : temp}"}
system command
FileUtils.remove_entry_secure working_dir
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment