Skip to content

Instantly share code, notes, and snippets.

Created October 5, 2009 03:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/4234c8580a166428e5da to your computer and use it in GitHub Desktop.
Save anonymous/4234c8580a166428e5da to your computer and use it in GitHub Desktop.
require 'optparse'
require 'ostruct'
class Entry < OpenStruct
end
class Offset
def initialize(seconds, milliseconds)
@time = Time.at(seconds, milliseconds*1000).getutc
end
def shift(mode, seconds, milliseconds)
offset = seconds + milliseconds/1000.0
case mode
when &#039;add&#039;
@time + offset
when &#039;sub&#039;
@time - offset
end
end
def shift!(mode, seconds, milliseconds)
@time = self.shift(mode, seconds, milliseconds)
end
def to_s
format = &quot;%02d&quot;
hour = sprintf(format, @time.hour)
minute = sprintf(format, @time.min)
second = sprintf(format, @time.sec)
millisecond = sprintf(format, @time.usec/1000)
&quot;#{hour}:#{minute}:#{second},#{millisecond}&quot;
end
def self.from(s)
s =~ /(\d+):(\d+):(\d+),(\d+)/
hours, minutes, seconds, milliseconds = $1.to_i, $2.to_i, $3.to_i, $4.to_i
self.new(hours*60*60+minutes*60+seconds, milliseconds)
end
end
class Subtitle
@@parsers = {}
def initialize
@entries = []
end
def shift!(mode, seconds, milliseconds)
@entries.each do |entry|
entry.start_offset.shift! mode, seconds, milliseconds
entry.end_offset.shift! mode, seconds, milliseconds
end
end
def shift(mode, seconds, milliseconds)
new_subtitle = self.clone
new_subtitle.shift!(mode, seconds, milliseconds)
new_subtitle
end
def self.get_parser(name)
@@parsers[name.downcase]
end
def self.parse(text)
instance = self.new
instance.parse!(text)
instance
end
def self.parse_file(file)
self.parse(File.read(file))
end
def self.inherited(by)
@@parsers[by.name.downcase] = by
end
end
class Subrip (\d+:\d+:\d+,\d+)\n(.+?)(?:\n\n|\Z)/m).each do |id, start_offset, end_offset, sub|
@entries &lt; id,
:start_offset =&gt; Offset.from(start_offset),
:end_offset =&gt; Offset.from(end_offset),
:sub =&gt; sub)
end
end
def to_s
s = ""
@entries.each do |entry|
a = [entry.entry_id.to_s, "#{entry.start_offset.to_s} --&gt; #{entry.end_offset.to_s}", entry.sub]
s &lt;&lt; a.join(&quot;\n&quot;) &lt; "subrip"}
OptionParser.new do |opts|
opts.on('-o', '--operation MODE', 'Whether to add or subtract an offset') do |mode|
options[:mode] = mode
end
opts.on('-t', '--time TIME', 'The offset, formatted as "seconds,milliseconds"') do |time|
options[:offset] = time.split(",").map{|i|i.to_i}
end
opts.on('-f', '--format FORMAT', 'The format of the subtitles file (e.g. "subrip")') do |format|
options[:type] = format.downcase
end
end.parse!(args)
input_file, output_file = args
parser = Subtitle.get_parser(options[:type])
subs = parser.parse_file(input_file)
subs.shift!(options[:mode], *options[:offset])
File.open(output_file, 'w') do |f|
f.write subs.to_s
end
end
end
Application.new.run(ARGV.clone)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment