subtool 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +20 -0
- data/.travis.yml +9 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +42 -0
- data/LICENSE +20 -0
- data/README.md +40 -0
- data/Rakefile +39 -0
- data/bin/subtool +80 -0
- data/features/files/malformed.srt +1 -0
- data/features/files/simple.srt +12 -0
- data/features/filter.feature +55 -0
- data/features/help.feature +20 -0
- data/features/import_export.feature +31 -0
- data/features/step_definitions/filter.rb +5 -0
- data/features/step_definitions/import_export.rb +25 -0
- data/features/support/env.rb +65 -0
- data/lib/subtool.rb +5 -0
- data/lib/subtool/export/srt.rb +38 -0
- data/lib/subtool/filter/delay.rb +14 -0
- data/lib/subtool/import/srt.rb +40 -0
- data/lib/subtool/subtitle.rb +10 -0
- data/lib/subtool/version.rb +3 -0
- data/subtool.gemspec +21 -0
- metadata +102 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
subtool (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
aruba (0.5.1)
|
10
|
+
childprocess (~> 0.3.6)
|
11
|
+
cucumber (>= 1.1.1)
|
12
|
+
rspec-expectations (>= 2.7.0)
|
13
|
+
builder (3.1.4)
|
14
|
+
childprocess (0.3.6)
|
15
|
+
ffi (~> 1.0, >= 1.0.6)
|
16
|
+
cucumber (1.2.1)
|
17
|
+
builder (>= 2.1.2)
|
18
|
+
diff-lcs (>= 1.1.3)
|
19
|
+
gherkin (~> 2.11.0)
|
20
|
+
json (>= 1.4.6)
|
21
|
+
diff-lcs (1.1.3)
|
22
|
+
ffi (1.2.0)
|
23
|
+
gherkin (2.11.5)
|
24
|
+
json (>= 1.4.6)
|
25
|
+
json (1.7.5)
|
26
|
+
multi_json (1.1.0)
|
27
|
+
rake (10.0.2)
|
28
|
+
rspec-expectations (2.12.0)
|
29
|
+
diff-lcs (~> 1.1.3)
|
30
|
+
simplecov (0.6.1)
|
31
|
+
multi_json (~> 1.0)
|
32
|
+
simplecov-html (~> 0.5.3)
|
33
|
+
simplecov-html (0.5.3)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
aruba
|
40
|
+
rake
|
41
|
+
simplecov
|
42
|
+
subtool!
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
subtool is a copyrighted free software by creativ-IT.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
[](https://travis-ci.org/0livier/subtool) [](https://codeclimate.com/github/0livier/subtool)
|
2
|
+
|
3
|
+
subtool is a commandline tool that help fix the timing of subtitles files.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install it using the gem command:
|
8
|
+
|
9
|
+
gem install subtool
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
|
14
|
+
## Want another tool ?
|
15
|
+
|
16
|
+
There are several other tool to manipulate SRT files. Among them,
|
17
|
+
|
18
|
+
* https://github.com/remram44/srt-shift
|
19
|
+
* http://www.aegisub.org/
|
20
|
+
* https://github.com/thiagokimo/srt-shifter
|
21
|
+
* https://github.com/georgyvlad/srt
|
22
|
+
|
23
|
+
|
24
|
+
## Reporting Bugs
|
25
|
+
|
26
|
+
Thanks for taking the time of giving the project an opportunity to enhance. Please use the Github tracker.
|
27
|
+
|
28
|
+
|
29
|
+
## Submitting Patches or Pull Requests
|
30
|
+
|
31
|
+
* Fork the project.
|
32
|
+
* Make your feature addition or bug fix.
|
33
|
+
* Add tests for it. This is important so future version won't break unintentionally.
|
34
|
+
* Commit
|
35
|
+
* Send a pull request.
|
36
|
+
|
37
|
+
|
38
|
+
## Copyright
|
39
|
+
|
40
|
+
Copyright (c) 2012 creativ-IT. See LICENSE for legal mumbo jumbo.
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
require 'cucumber'
|
5
|
+
require 'cucumber/rake/task'
|
6
|
+
|
7
|
+
spec = eval(File.read('subtool.gemspec'))
|
8
|
+
|
9
|
+
# needed to have "rake gem"
|
10
|
+
Gem::PackageTask.new(spec) do |pkg|
|
11
|
+
end
|
12
|
+
|
13
|
+
Dir.mkdir 'tmp' unless File.exists?("tmp")
|
14
|
+
|
15
|
+
CUKE_RESULTS = 'tmp/results.html'
|
16
|
+
|
17
|
+
CLEAN << CUKE_RESULTS
|
18
|
+
|
19
|
+
desc 'Run features'
|
20
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
21
|
+
opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
|
22
|
+
opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
|
23
|
+
t.cucumber_opts = opts
|
24
|
+
t.fork = false
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Run features tagged as work-in-progress (@wip)'
|
28
|
+
Cucumber::Rake::Task.new('features:wip') do |t|
|
29
|
+
tag_opts = ' --tags ~@pending'
|
30
|
+
tag_opts = ' --tags @wip'
|
31
|
+
t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x -s#{tag_opts}"
|
32
|
+
t.fork = false
|
33
|
+
end
|
34
|
+
|
35
|
+
task :cucumber => :features
|
36
|
+
task 'cucumber:wip' => 'features:wip'
|
37
|
+
task :wip => 'features:wip'
|
38
|
+
|
39
|
+
task :default => [:features]
|
data/bin/subtool
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'pp'
|
6
|
+
require 'subtool'
|
7
|
+
|
8
|
+
options = OpenStruct.new(:delay => 1000.0)
|
9
|
+
|
10
|
+
option_parser = OptionParser.new do |opts|
|
11
|
+
opts.banner = 'Usage: subtool [options]'
|
12
|
+
|
13
|
+
opts.separator ''
|
14
|
+
opts.separator 'Specific options:'
|
15
|
+
|
16
|
+
opts.on('-d', '--delay SECONDS',
|
17
|
+
'Amount of seconds to add or removed. Can be formatted as a float (e.g. 3.3). Default is 1.') do |seconds|
|
18
|
+
options.delay = Float(seconds)*1000
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on('-i', '--input FILENAME',
|
22
|
+
'Input SRT filename. STDIN by default or if - is given.') do |filename|
|
23
|
+
options.input = filename unless filename == '-'
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on('-o', '--output FILENAME',
|
27
|
+
'Ouput SRT filename. STDOUT by default or if - is given.') do |filename|
|
28
|
+
options.output = filename unless filename == '-'
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
32
|
+
puts opts
|
33
|
+
|
34
|
+
# @TODO Put commands help
|
35
|
+
# command 'add' do
|
36
|
+
# description "Adds a delay to the srt file, making the subtitles displayed later."
|
37
|
+
# command 'remove' do
|
38
|
+
# description "Makes the subtitles displayed earlier."
|
39
|
+
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
|
43
|
+
# Another typical switch to print the version.
|
44
|
+
opts.on_tail('--version', 'Show version') do
|
45
|
+
puts Subtool::VERSION
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
option_parser.order!
|
51
|
+
|
52
|
+
if ARGV.count == 0
|
53
|
+
puts option_parser
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
|
57
|
+
commands = ARGV.dup
|
58
|
+
|
59
|
+
ARGV.replace([options.input]) if options.input
|
60
|
+
subtitles = Subtool::Import::Srt.filehandler(ARGF)
|
61
|
+
|
62
|
+
# @Todo more filters otherwise the loop won't make any sense
|
63
|
+
while commands.count > 0
|
64
|
+
case (command = commands.shift.downcase)
|
65
|
+
when 'add', 'remove'
|
66
|
+
if commands[0] && commands[0].match(/^\d+(?:\.\d+)?$/)
|
67
|
+
delay = Float(commands.shift)*1000
|
68
|
+
else
|
69
|
+
delay = options.delay
|
70
|
+
end
|
71
|
+
Subtool::Filter::Delay.add_to(subtitles, command == 'add' ? delay : -delay)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# output
|
76
|
+
if options.output
|
77
|
+
Subtool::Export::Srt.file(options.output, subtitles)
|
78
|
+
else
|
79
|
+
Subtool::Export::Srt.stdout(subtitles)
|
80
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
\_o< QUACK
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Feature: Modifying Parser Import / Export should get and write content properly
|
2
|
+
|
3
|
+
In order to modify users' srt files
|
4
|
+
As a developer of subtool
|
5
|
+
I want it to modify them properly
|
6
|
+
|
7
|
+
Scenario: Adding delay
|
8
|
+
When I parse a Srt file named "features/files/simple.srt"
|
9
|
+
And I add a delay of 1 second
|
10
|
+
Then I should have the following subtitles:
|
11
|
+
| id | start | end | body |
|
12
|
+
| 1 | 21000 | 25400 | Altocumulus clouds occur between six thousand |
|
13
|
+
| 2 | 25600 | 28800 | and twenty thousand feet above ground level. |
|
14
|
+
| 3 | 3662100 | 7323200 | QUACK\n\\_o< |
|
15
|
+
|
16
|
+
Scenario: Adding delay
|
17
|
+
When I parse a Srt file named "features/files/simple.srt"
|
18
|
+
And I add a delay of -1.5 second
|
19
|
+
Then I should have the following subtitles:
|
20
|
+
| id | start | end | body |
|
21
|
+
| 1 | 18500 | 22900 | Altocumulus clouds occur between six thousand |
|
22
|
+
| 2 | 23100 | 26300 | and twenty thousand feet above ground level. |
|
23
|
+
| 3 | 3659600 | 7320700 | QUACK\n\\_o< |
|
24
|
+
|
25
|
+
Scenario: Adding a delay to a file and reparsing it
|
26
|
+
When I parse a Srt file named "features/files/simple.srt"
|
27
|
+
And I add a delay of 2.1 second
|
28
|
+
And I export the subtitles to a file named "tmp/output_simple.srt"
|
29
|
+
And I parse a Srt file named "tmp/output_simple.srt"
|
30
|
+
Then I should have the following subtitles:
|
31
|
+
| id | start | end | body |
|
32
|
+
| 1 | 22100 | 26500 | Altocumulus clouds occur between six thousand |
|
33
|
+
| 2 | 26700 | 29900 | and twenty thousand feet above ground level. |
|
34
|
+
| 3 | 3663200 | 7324300 | QUACK\n\\_o< |
|
35
|
+
|
36
|
+
|
37
|
+
Scenario: Adding delay
|
38
|
+
When I parse a Srt file named "features/files/simple.srt"
|
39
|
+
And I add a delay of -1.5 second
|
40
|
+
Then I should have the following subtitles:
|
41
|
+
| id | start | end | body |
|
42
|
+
| 1 | 18500 | 22900 | Altocumulus clouds occur between six thousand |
|
43
|
+
| 2 | 23100 | 26300 | and twenty thousand feet above ground level. |
|
44
|
+
| 3 | 3659600 | 7320700 | QUACK\n\\_o< |
|
45
|
+
|
46
|
+
Scenario: Adding a delay to a file and reparsing it
|
47
|
+
When I parse a Srt file named "features/files/simple.srt"
|
48
|
+
And I add a delay of 2.1 second
|
49
|
+
And I export the subtitles to a file named "tmp/output_simple.srt"
|
50
|
+
And I parse a Srt file named "tmp/output_simple.srt"
|
51
|
+
Then I should have the following subtitles:
|
52
|
+
| id | start | end | body |
|
53
|
+
| 1 | 22100 | 26500 | Altocumulus clouds occur between six thousand |
|
54
|
+
| 2 | 26700 | 29900 | and twenty thousand feet above ground level. |
|
55
|
+
| 3 | 3663200 | 7324300 | QUACK\n\\_o< |
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Getting Help
|
2
|
+
|
3
|
+
In order to RTFM
|
4
|
+
As a user of subtool
|
5
|
+
I want to get the manual
|
6
|
+
|
7
|
+
Scenario: Getting help with --help
|
8
|
+
When I call "subtool" with the argument "--help"
|
9
|
+
Then the exit status should be 0
|
10
|
+
Then the output should contain "Usage"
|
11
|
+
|
12
|
+
Scenario: exit status of 0
|
13
|
+
When I call "subtool" with the argument ""
|
14
|
+
Then the exit status should be 0
|
15
|
+
Then the output should contain "Usage"
|
16
|
+
|
17
|
+
Scenario: Getting help when no command is given
|
18
|
+
When I call "subtool" with the argument "-i features/files/simple.srt"
|
19
|
+
Then the exit status should be 0
|
20
|
+
Then the output should contain "Usage"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Feature: Parser Import / Export should get and write content properly
|
2
|
+
|
3
|
+
In order to modify users' srt files
|
4
|
+
As a developer of subtool
|
5
|
+
I want it to load and write them correctly
|
6
|
+
|
7
|
+
Scenario: Srt Loading
|
8
|
+
When I parse a Srt file named "features/files/simple.srt"
|
9
|
+
Then I should have the following subtitles:
|
10
|
+
| id | start | end | body |
|
11
|
+
| 1 | 20000 | 24400 | Altocumulus clouds occur between six thousand |
|
12
|
+
| 2 | 24600 | 27800 | and twenty thousand feet above ground level. |
|
13
|
+
| 3 | 3661100 | 7322200 | QUACK\n\\_o< |
|
14
|
+
|
15
|
+
|
16
|
+
Scenario: Writing file
|
17
|
+
When I parse a Srt file named "features/files/simple.srt"
|
18
|
+
And I export the subtitles to a file named "tmp/output_simple.srt"
|
19
|
+
And I parse a Srt file named "tmp/output_simple.srt"
|
20
|
+
Then I should have the following subtitles:
|
21
|
+
| id | start | end | body |
|
22
|
+
| 1 | 20000 | 24400 | Altocumulus clouds occur between six thousand |
|
23
|
+
| 2 | 24600 | 27800 | and twenty thousand feet above ground level. |
|
24
|
+
| 3 | 3661100 | 7322200 | QUACK\n\\_o< |
|
25
|
+
|
26
|
+
# need to call the binary since it does not capture the output of current process
|
27
|
+
Scenario: Writing file on STDOUT
|
28
|
+
When I call "subtool" with the argument "-i ../../features/files/simple.srt add 0"
|
29
|
+
Then the output should contain "1\n00:00:20,000 --> 00:00:24,400\nAltocumulus clouds occur between six thousand"
|
30
|
+
And the output should contain "2\n00:00:24,600 --> 00:00:27,800\nand twenty thousand feet above ground level."
|
31
|
+
And the output should contain "3\n01:01:01,100 --> 02:02:02,200\nQUACK"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'subtool'
|
2
|
+
|
3
|
+
When /^I call "([^"]+)"(?: with the arguments? "([^"]*)")?$/ do |app_name, parameters|
|
4
|
+
@app_name = app_name
|
5
|
+
step %(I run `#{app_name} #{parameters}`)
|
6
|
+
end
|
7
|
+
|
8
|
+
When /^I parse a Srt file named "([^"]+)"$/ do |filename|
|
9
|
+
@subtitles = Subtool::Import::Srt.file(filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
When /^I export the subtitles to a file named "(.+)"$/ do |filename|
|
13
|
+
Subtool::Export::Srt.file(filename, @subtitles)
|
14
|
+
end
|
15
|
+
|
16
|
+
When /^I export the subtitles to STDOUT$/ do
|
17
|
+
Subtool::Export::Srt.stdout(@subtitles)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
Then /^I should have the following subtitles:$/ do |table|
|
22
|
+
hasherize(table).each_with_index do |expected_values, i|
|
23
|
+
@subtitles[i].should === Subtool::Subtitle.new(expected_values[:id], expected_values[:start], expected_values[:end], expected_values[:body])
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
if RUBY_VERSION != '1.8.7'
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
SimpleCov.coverage_dir 'coverage/cucumber'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'aruba/cucumber'
|
8
|
+
|
9
|
+
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
10
|
+
LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
11
|
+
|
12
|
+
Before do
|
13
|
+
# Using "announce" causes massive warnings on 1.9.2
|
14
|
+
@puts = true
|
15
|
+
@original_rubylib = ENV['RUBYLIB']
|
16
|
+
ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
After do
|
20
|
+
ENV['RUBYLIB'] = @original_rubylib
|
21
|
+
end
|
22
|
+
|
23
|
+
# Starts with cucumber's built-in hashes method and adds a bit more magic:
|
24
|
+
#
|
25
|
+
# * Converts hash keys from stings to symbols
|
26
|
+
# * Converts numeric values into integers
|
27
|
+
# * Converts true/false strings into actual booleans
|
28
|
+
#
|
29
|
+
def hasherize(table)
|
30
|
+
table.hashes.map do |object|
|
31
|
+
result = {}
|
32
|
+
object.each do |attribute, value|
|
33
|
+
object[attribute] = to_boolean?(value)
|
34
|
+
object[attribute] = to_float?(object[attribute])
|
35
|
+
object[attribute] = to_integer?(object[attribute])
|
36
|
+
result[symbolize(attribute)] = object.delete(attribute) unless attribute.is_a?(Symbol)
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Converts human readable attribute names (e.g. 'transaction type') into rails-ready
|
45
|
+
# symbolized hash keys (e.g. :transaction type).
|
46
|
+
#
|
47
|
+
def symbolize(string)
|
48
|
+
string.to_sym
|
49
|
+
end
|
50
|
+
|
51
|
+
# Checks if the passed value contains only digits and underscores.
|
52
|
+
#
|
53
|
+
def to_integer?(value)
|
54
|
+
value.is_a?(String) && value.match(/^[\d_]+$/) ? value.to_i : value
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_float?(value)
|
58
|
+
value.is_a?(String) && value.match(/^[\d_]+\.[\d_]+$/) ? Float(value) : value
|
59
|
+
end
|
60
|
+
|
61
|
+
# Converts true/false/t/f strings into proper booleans.
|
62
|
+
#
|
63
|
+
def to_boolean?(value)
|
64
|
+
value.is_a?(String) && value.strip.match(/^(t|f|true|false)$/i) ? !!(value =~ /t|true/i) : value
|
65
|
+
end
|
data/lib/subtool.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Subtool
|
2
|
+
module Export
|
3
|
+
class Srt
|
4
|
+
|
5
|
+
def self.filehandler(fh, subtitles)
|
6
|
+
subtitles.each do |subtitle|
|
7
|
+
fh.write self.to_srt_entry(subtitle)
|
8
|
+
fh.write "\n\n"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.file(filename, subtitles)
|
13
|
+
fh = File.open(filename, 'w')
|
14
|
+
|
15
|
+
self.filehandler(fh, subtitles)
|
16
|
+
|
17
|
+
fh.close
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.stdout(subtitles)
|
21
|
+
self.filehandler($stdout, subtitles)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.to_srt_entry(subtitle)
|
25
|
+
"#{subtitle[:id]}\n#{self.time_to_s(subtitle[:start])} --> #{self.time_to_s(subtitle[:end])}\n#{subtitle[:body]}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.time_to_s(time)
|
29
|
+
hours = sprintf '%02d', time / 3600000
|
30
|
+
minutes = sprintf '%02d', (time/60000).modulo(60)
|
31
|
+
seconds = sprintf '%02d', (time/1000).modulo(60)
|
32
|
+
milliseconds = sprintf '%03d', time.modulo(1000)
|
33
|
+
"#{hours}:#{minutes}:#{seconds},#{milliseconds}"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Subtool
|
2
|
+
module Import
|
3
|
+
class Srt
|
4
|
+
|
5
|
+
def self.filehandler(fh)
|
6
|
+
subtitles = []
|
7
|
+
|
8
|
+
until fh.eof? do
|
9
|
+
|
10
|
+
number = Integer(fh.readline.strip)
|
11
|
+
position = self.parse_position(fh.readline.strip)
|
12
|
+
body = fh.readline("\n\n").strip
|
13
|
+
|
14
|
+
subtitles.push(Subtool::Subtitle.new(number, position[:start], position[:end], body))
|
15
|
+
end
|
16
|
+
|
17
|
+
subtitles
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.file(filename)
|
21
|
+
fh = File.open(filename)
|
22
|
+
subtitles = self.filehandler(fh)
|
23
|
+
fh.close
|
24
|
+
|
25
|
+
subtitles
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.parse_position(position)
|
29
|
+
matches = position.match(/^(\d\d):(\d\d):(\d\d),(\d\d\d) --> (\d\d):(\d\d):(\d\d),(\d\d\d)$/)
|
30
|
+
throw Exception.new("Can't parse #{position} as a valid time range") unless matches
|
31
|
+
matches = matches[1..8].map { |s| Integer(s) }
|
32
|
+
{
|
33
|
+
:start => matches[0]*60*60*1000 + matches[1]*60*1000 + matches[2]*1000 + matches[3],
|
34
|
+
:end => matches[4]*60*60*1000 + matches[5]*60*1000 + matches[6]*1000 + matches[7]
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/subtool.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
2
|
+
require File.join([File.dirname(__FILE__), 'lib', 'subtool', 'version.rb'])
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'subtool'
|
5
|
+
s.version = Subtool::VERSION
|
6
|
+
s.author = 'Olivier Garcia'
|
7
|
+
s.email = 'olivier@lol.cat'
|
8
|
+
s.homepage = 'http://linux-nerd.com'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.summary = 'CLI tool for manipulating subtitles files'
|
11
|
+
s.description = 'subtool is a library and CLI program to add (or remove) delay in subtitles files'
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = %w(lib)
|
17
|
+
|
18
|
+
s.add_development_dependency('rake')
|
19
|
+
s.add_development_dependency('aruba')
|
20
|
+
s.add_development_dependency('simplecov')
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: subtool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Olivier Garcia
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &26298140 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *26298140
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: aruba
|
27
|
+
requirement: &26297620 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *26297620
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: simplecov
|
38
|
+
requirement: &26297180 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *26297180
|
47
|
+
description: subtool is a library and CLI program to add (or remove) delay in subtitles
|
48
|
+
files
|
49
|
+
email: olivier@lol.cat
|
50
|
+
executables:
|
51
|
+
- subtool
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- .travis.yml
|
57
|
+
- Gemfile
|
58
|
+
- Gemfile.lock
|
59
|
+
- LICENSE
|
60
|
+
- README.md
|
61
|
+
- Rakefile
|
62
|
+
- bin/subtool
|
63
|
+
- features/files/malformed.srt
|
64
|
+
- features/files/simple.srt
|
65
|
+
- features/filter.feature
|
66
|
+
- features/help.feature
|
67
|
+
- features/import_export.feature
|
68
|
+
- features/step_definitions/filter.rb
|
69
|
+
- features/step_definitions/import_export.rb
|
70
|
+
- features/support/env.rb
|
71
|
+
- lib/subtool.rb
|
72
|
+
- lib/subtool/export/srt.rb
|
73
|
+
- lib/subtool/filter/delay.rb
|
74
|
+
- lib/subtool/import/srt.rb
|
75
|
+
- lib/subtool/subtitle.rb
|
76
|
+
- lib/subtool/version.rb
|
77
|
+
- subtool.gemspec
|
78
|
+
homepage: http://linux-nerd.com
|
79
|
+
licenses: []
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.10
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: CLI tool for manipulating subtitles files
|
102
|
+
test_files: []
|