Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement