Skip to content

Instantly share code, notes, and snippets.

@czj
Created August 8, 2016 07:54
Show Gist options
  • Save czj/33617d92ead34f415bc0b3419338708c to your computer and use it in GitHub Desktop.
Save czj/33617d92ead34f415bc0b3419338708c to your computer and use it in GitHub Desktop.
Recompression vidéo H264/H265
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'optparse'
require 'ostruct'
DEFAULT_X264_PARAMS = {
'b-adapt' => 2,
'ref' => 16,
'direct' => 'auto',
'trellis' => 2,
'analyse' => 'all',
'merange' => 24,
'me' => 'umh',
'rc-lookahead' => 48,
'bframes' => 6
}.freeze
def encoders
%w(x264 x265)
end
def video_sizes
%w(480p 576p 720p 1080p native)
end
def audio_formats
%w(mono stereo)
end
# All video file extension parsed by default
def accepted_file_extensions
%w(mp4 mts m2ts mov).flat_map { |e| [e, e.upcase] }
end
# By default use mono 64 kbps AAC audio, as we never have the need for stereo
# using smartphone / DSLR recordings
def audio_flags
if flags.audio == 'stereo'
'--ab 128'
else
'--ab 64 --mixdown mono'
end
end
def encoder_flags
flags.encoder = 'x264' unless flags.encoder == 'x265'
"-e #{flags.encoder}"
end
def size_flags
height = flags.resolution.to_i
width = (height * 16).div(9)
"--width #{width} --height #{height}" if height > 0
end
def x264_flags
params = DEFAULT_X264_PARAMS.dup
if flags.resolution.to_i > 720
params['rc-lookahead'] = 64
params['bframes'] = 8
end
values = params.map { |k, v| "#{k}=#{v}" }.join(':')
"-x '#{values}'"
end
# x264 presets guide : https://forum.handbrake.fr/viewtopic.php?f=6&t=19426
flags = OpenStruct.new
flags.optim = '--optimize --use-opencl --use-hwd --format mp4'
OptionParser.new do |opts|
opts.banner = 'Usage: video_recompress files [options]'
opts.on('-r', '--resolution [native]', video_sizes, 'Video height') do |o|
flags.resolution = o
end
opts.on('-a', '--audio-format [mono]', audio_formats, 'Audio format') do |o|
flags.audio = o
end
opts.on('-e', '--encoder [x264]', encoders, 'Force H265 encoding') do |o|
flags.encoder = o
end
opts.on('-o', '--output DIRECTORY', String, 'Destination directory') do |o|
flags.output = o
end
opts.on('-h', '--help', 'Displays help') do
puts opts
exit
end
end.parse!
# require 'pp'
# pp flags
#
mask = File.join(ARGV.last, "*.{#{accepted_file_extensions.join(',')}}")
puts "Globbing #{mask} ..."
Dir.glob(mask) do |entry|
puts "Processing : #{entry}\n"
next unless File.file? entry
source_dir = File.dirname(entry)
source_prefix = File.basename(entry, '.*')
# archive_dir = File.join(source_dir, '..', "out-#{flags.height}")
dest_dir = File.join(source_dir, '..', 'out-originals')
flags.output ||= File.join(dest_dir, "#{source_prefix} - .mp4")
# Dir.mkdir(flags.output)
# Compress video file
# -v0 flag disabled most of the verbosity
command = []
command << '/Applications/HandBrakeCLI -v0'
command << "-i '#{entry}'"
command << "-o '#{flags.output}'"
command << flags.optim
command << audio_flags
command << size_flags
command << "--quality #{flags.quality || 23}"
command << encoder_flags
command << x264_flags
command.compact!
command = command.join(' ')
puts "Running : #{command}\n"
# system command
# # We have to open the source file to read its mtime and attribute it to
# # the encoded file
# File.utime Time.now, File.new(entry).mtime, flags.destination
#
# # Move original file to archive directory
# Dir.mkdir(archive_dir)
# File.mv(source_file, archive_dir)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment