secret
anonymous / ChuckHa
Last active

  • Download Gist
ChuckHa
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#!/usr/bin/env ruby
require 'optparse'
 
# create an empty hash to hold the options
options = {}
 
optparse = OptionParser.new do|opts|
opts.banner = "Usage: shift_subtitle [options] infile outfile"
 
opts.on('-h', '--help', 'Display this screen') do
puts opts
exit
end
opts.on('-o', '--operation [add|sub]', 'What type of operation to use') do|o|
if o == 'add' or o == 'sub'
options[:operation] = o
else
puts "operation must be 'add' or 'sub'."
exit
end
end
opts.on('-t', '--time [HH:[MM:[SS,[mmm]]]]', 'Amount of time to shift') do|t|
options[:time] = t
end
end
 
optparse.parse!
 
# make sure the files exist...
ARGV[0] ? options[:file1] = ARGV[0] : exit
ARGV[1] ? options[:file2] = ARGV[1] : exit
 
class SubtitleTime
attr_accessor :hours, :minutes, :seconds, :milliseconds
 
# reverse char by char block
# at first comma, set milli
# at first : set seconds, etc.
def initialize(time, modifier='add')
num = ''
set_sec,set_min,set_hour= false
time.reverse.each_char do|char|
if num =~ /\d\d\d/
@milliseconds = num.to_i
num = ''
set_sec = true
elsif char == ':' and set_sec
@seconds = num.to_i
num = ''
set_sec = false
set_min = true
elsif char == ':' and set_min
@minutes = num.to_i
num = ''
set_min = false
set_hour = true
elsif char == ':' and set_hour
@hours = num.to_i
num = ''
else
num = char + num
end
end
if set_sec
@seconds = num.to_i
elsif set_min
@minutes = num.to_i
elsif set_hour
@hours = num.to_i
end
@milliseconds = @milliseconds || 0
@seconds = @seconds || 0
@minutes = @minutes || 0
@hours = @hours || 0
@modifier = modifier
end
 
def change_hour(hours)
if @modifier == 'add'
@hours += hours
else
@hours -= hours
if @hours < 0
@hours = 0
end
end
end
 
def change_min(minutes)
if @modifier == 'add'
@minutes += minutes
if @minutes >= 60
hours = @minutes/60
change_hour(hours)
@minutes %= 60
end
else
@minutes -= minutes
if @minutes < 0
change_hour(1)
@minutes += 60
end
end
end
def change_sec(seconds)
if @modifier == 'add'
@seconds += seconds
if @seconds >= 60
minutes = @seconds/60
change_min(minutes)
@seconds %= 60
end
else
@seconds -= seconds
if @seconds < 0
change_min(1)
@seconds += 60
end
end
end
 
def change_milli(milli)
if @modifier == 'add'
@milliseconds += milli
if @milliseconds >= 1000
seconds = @milliseconds/1000
change_sec(seconds)
@milliseconds %= 1000
end
else
@milliseconds -= milli
if @milliseconds < 0
change_sec(1)
@milliseconds += 1000
end
end
end
def to_s
return sprintf("%02d:%02d:%02d,%03d", @hours, @minutes, @seconds, @milliseconds)
end
end
 
# turn the input time into a SubtitleTime object
time_mod = SubtitleTime.new(options[:time])
 
 
out_file = File.new(options[:file2], "w")
 
# every line that has timestamps
# take each time stamp split into h/m/s/ms
# apply the operation
# how to deal with carry overs?
IO.foreach(options[:file1]) do|line|
if (line =~ /-->/)
first = SubtitleTime.new(line.split(/ --> /)[0], options[:operation])
second = SubtitleTime.new(line.split(/ --> /)[1], options[:operation])
first.change_hour(time_mod.hours)
first.change_min(time_mod.minutes)
first.change_sec(time_mod.seconds)
first.change_milli(time_mod.milliseconds)
second.change_hour(time_mod.hours)
second.change_min(time_mod.minutes)
second.change_sec(time_mod.seconds)
second.change_milli(time_mod.milliseconds)
out_file.syswrite("#{first.to_s} --> #{second.to_s}\n")
else
out_file.syswrite(line)
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.