Created
August 8, 2016 07:54
-
-
Save czj/33617d92ead34f415bc0b3419338708c to your computer and use it in GitHub Desktop.
Recompression vidéo H264/H265
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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