srt 0.0.9 → 0.0.9.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # SRT [![Build Status](https://travis-ci.org/cpetersen/srt.png?branch=master)](https://travis-ci.org/cpetersen/srt)
1
+ # SRT [![Build Status](https://travis-ci.org/cpetersen/srt.png?branch=master)](https://travis-ci.org/cpetersen/srt) [![Code Climate](https://codeclimate.com/github/cpetersen/srt.png)](https://codeclimate.com/github/cpetersen/srt)
2
2
 
3
3
  SRT stands for SubRip text file format, which is a file for storing subtitles; This is a Ruby library for manipulating SRT files.
4
4
  Current functionality includes **parsing**, **appending**, **splitting** and **timeshifting** (constant, progressive and framerate-based).
@@ -60,8 +60,22 @@ The method `split` splits your subtitles at one (or more) points and returns an
60
60
  By default, the timecodes of the split parts are relatively shifted towards their beginnings (to line up with correspondingly split multi-part video);
61
61
  By additionally passing `:timeshift => false` you can prevent that behaviour and retain the original timecodes for each split part.
62
62
 
63
+ Pass the option `:renumber => false` to prevent the line sequence number from being reset for a segment.
64
+
65
+ ```ruby
66
+ parts = file.split( :at => "01:09:24,000", :renumber => false ) # Split the file in two at 01:09:24 but do not reset the sequence number on the second part
67
+ ```
68
+
63
69
  Example options for a multi-split: `{ :at => ["00:19:24,500", "01:32:09,120", ...] }`
64
70
 
71
+
72
+ Optionally, for multi-splitting, you can pass a ":every" option to split the subtitles at a fixed interval.
73
+
74
+ ```ruby
75
+ parts = file.split( :every => "00:01:00,000" ) # Split the file every 1 minute
76
+ ```
77
+ Note that the options :at and :every are mutually exclusive, and :at takes precedence.
78
+
65
79
  #### Timeshifting
66
80
 
67
81
  The method `timeshift` takes a hash and supports three different modes of timecode processing:
@@ -118,3 +132,4 @@ This is usually only useful if you have some background information about the de
118
132
  3. Commit your changes (`git commit -am 'Added some feature'`)
119
133
  4. Push to the branch (`git push origin my-new-feature`)
120
134
  5. Create new Pull Request
135
+
@@ -1,6 +1,7 @@
1
1
  module SRT
2
2
  class File
3
- def self.parse(input)
3
+ def self.parse(input, options = {})
4
+ @debug = options.fetch(:debug, false)
4
5
  if input.is_a?(String)
5
6
  parse_string(input)
6
7
  elsif input.is_a?(::File)
@@ -31,12 +32,12 @@ module SRT
31
32
 
32
33
  if (line.start_time = SRT::File.parse_timecode(mres["start_timecode"])) == nil
33
34
  line.error = "#{index}, Invalid formatting of start timecode, [#{mres["start_timecode"]}]"
34
- $stderr.puts line.error
35
+ $stderr.puts line.error if @debug
35
36
  end
36
37
 
37
38
  if (line.end_time = SRT::File.parse_timecode(mres["end_timecode"])) == nil
38
39
  line.error = "#{index}, Invalid formatting of end timecode, [#{mres["end_timecode"]}]"
39
- $stderr.puts line.error
40
+ $stderr.puts line.error if @debug
40
41
  end
41
42
 
42
43
  if mres["display_coordinates"]
@@ -44,7 +45,7 @@ module SRT
44
45
  end
45
46
  else
46
47
  line.error = "#{index}, Invalid Time Line formatting, [#{str}]"
47
- $stderr.puts line.error
48
+ $stderr.puts line.error if @debug
48
49
  end
49
50
  else
50
51
  line.text << str.strip
@@ -53,7 +54,7 @@ module SRT
53
54
  end
54
55
  rescue
55
56
  line.error = "#{index}, General Error, [#{str}]"
56
- $stderr.puts line.error
57
+ $stderr.puts line.error if @debug
57
58
  end
58
59
  end
59
60
  result
@@ -91,9 +92,19 @@ module SRT
91
92
  end
92
93
 
93
94
  def split(options)
94
- options = { :timeshift => true }.merge(options)
95
- if options[:at]
95
+ options = { :timeshift => true, :renumber => true }.merge(options)
96
+
97
+ split_points = []
98
+
99
+ if (options[:at])
96
100
  split_points = [options[:at]].flatten.map{ |timecode| SRT::File.parse_timecode(timecode) }.sort
101
+ elsif (options[:every])
102
+ interval = SRT::File.parse_timecode(options[:every])
103
+ max = lines.last.end_time
104
+ (interval..max).step(interval){ |t| split_points << t }
105
+ end
106
+
107
+ if (split_points.count > 0)
97
108
  split_offsprings = [SRT::File.new]
98
109
 
99
110
  reshift = 0
@@ -102,7 +113,7 @@ module SRT
102
113
  lines.each do |line|
103
114
  if split_points.empty? || line.end_time <= split_points.first
104
115
  cloned_line = line.clone
105
- cloned_line.sequence -= renumber
116
+ cloned_line.sequence -= renumber if options[:renumber]
106
117
  if options[:timeshift]
107
118
  cloned_line.start_time -= reshift
108
119
  cloned_line.end_time -= reshift
@@ -110,7 +121,7 @@ module SRT
110
121
  split_offsprings.last.lines << cloned_line
111
122
  elsif line.start_time < split_points.first
112
123
  cloned_line = line.clone
113
- cloned_line.sequence -= renumber
124
+ cloned_line.sequence -= renumber if options[:renumber]
114
125
  if options[:timeshift]
115
126
  cloned_line.start_time -= reshift
116
127
  cloned_line.end_time = split_points.first - reshift
@@ -123,7 +134,7 @@ module SRT
123
134
 
124
135
  split_offsprings << SRT::File.new
125
136
  cloned_line = line.clone
126
- cloned_line.sequence -= renumber
137
+ cloned_line.sequence -= renumber if options[:renumber]
127
138
  if options[:timeshift]
128
139
  cloned_line.start_time = 0
129
140
  cloned_line.end_time -= reshift
@@ -136,7 +147,7 @@ module SRT
136
147
 
137
148
  split_offsprings << SRT::File.new
138
149
  cloned_line = line.clone
139
- cloned_line.sequence -= renumber
150
+ cloned_line.sequence -= renumber if options[:renumber]
140
151
  if options[:timeshift]
141
152
  cloned_line.start_time -= reshift
142
153
  cloned_line.end_time -= reshift
@@ -198,8 +209,17 @@ module SRT
198
209
  end
199
210
  end
200
211
 
201
- def to_s
202
- lines.map { |l| [l.sequence, (l.display_coordinates ? l.time_str + l.display_coordinates : l.time_str), l.text, ""] }.flatten.join("\n")
212
+ def to_s(time_str_function=:time_str)
213
+ lines.map { |l| [l.sequence, (l.display_coordinates ? l.send(time_str_function) + l.display_coordinates : l.send(time_str_function)), l.text, ""] }.flatten.join("\n")
214
+ end
215
+
216
+ def to_webvtt
217
+ header = <<eos
218
+ WEBVTT
219
+ X-TIMESTAMP-MAP=MPEGTS:0,LOCAL:00:00:00.000
220
+
221
+ eos
222
+ header + to_s(:webvtt_time_str)
203
223
  end
204
224
 
205
225
  attr_writer :lines
@@ -32,8 +32,12 @@ module SRT
32
32
  sequence.nil? && start_time.nil? && end_time.nil? && text.empty?
33
33
  end
34
34
 
35
- def time_str
36
- [@start_time, @end_time].map { |t| sprintf("%02d:%02d:%02d,%s", t / 3600, (t % 3600) / 60, t % 60, sprintf("%.3f", t)[-3, 3]) }.join(" --> ")
35
+ def time_str(subframe_separator=",")
36
+ [@start_time, @end_time].map { |t| sprintf("%02d:%02d:%02d#{subframe_separator}%s", t / 3600, (t % 3600) / 60, t % 60, sprintf("%.3f", t)[-3, 3]) }.join(" --> ")
37
+ end
38
+
39
+ def webvtt_time_str
40
+ time_str(".")
37
41
  end
38
42
  end
39
43
  end
@@ -1,3 +1,3 @@
1
1
  module SRT
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.9.2"
3
3
  end
@@ -0,0 +1,4 @@
1
+ A
2
+ 00:00:51,413111 ===* 00:00:53,3102222
3
+ === Era uma vez,
4
+
@@ -0,0 +1,2 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
@@ -1,4 +1,5 @@
1
1
  require 'srt'
2
+ require 'spec_helper'
2
3
 
3
4
  describe SRT do
4
5
 
@@ -26,6 +27,20 @@ describe SRT do
26
27
  end
27
28
 
28
29
  describe SRT::File do
30
+ describe '#parse' do
31
+ context "parsing with debug true" do
32
+ it "should be verbose when failing" do
33
+ $stderr.should_receive(:puts).once
34
+ SRT::File.parse(File.open("./spec/invalid.srt"), debug: true).errors.should_not be_empty
35
+ end
36
+ end
37
+ context "parsing with debug false" do
38
+ it "should raise exception silently" do
39
+ $stderr.should_not_receive(:puts)
40
+ SRT::File.parse(File.open("./spec/invalid.srt")).errors.should_not be_empty
41
+ end
42
+ end
43
+ end
29
44
 
30
45
  describe ".parse_id" do
31
46
  it "should convert the id string (#[id]) to an int representing the sequence number" do
@@ -281,6 +296,71 @@ describe SRT do
281
296
  result[2].lines.last.sequence.should eq(212)
282
297
  end
283
298
  end
299
+
300
+ context "when passing { :at => \"00:19:24,500\", :every => \"00:00:01,000\" }" do
301
+ let(:result) { file.split( :at => "00:19:24,500", :every => "00:00:01,000" ) }
302
+
303
+ it "should return an array containing two SRT::File instances, ignoring :every" do
304
+ result.length.should eq(2)
305
+ result[0].class.should eq(SRT::File)
306
+ result[1].class.should eq(SRT::File)
307
+ end
308
+ end
309
+
310
+ context "when passing { :every => \"00:05:00,000\" }" do
311
+ let(:result) { file.split( :every => "00:05:00,000" ) }
312
+
313
+ it "should return an array containing nine SRT::File instances" do
314
+ result.length.should eq(9)
315
+ (0...result.count).each do |n|
316
+ result[n].class.should eq(SRT::File)
317
+ end
318
+ end
319
+ end
320
+
321
+ context "when passing { :at => \"00:19:24,500\", :renumber => false }" do
322
+ let(:result) { file.split( :at => "00:19:24,500", :renumber => false ) }
323
+
324
+ it "sequence for the last line of first part should be the sequence for the first line of second part" do
325
+ result[0].lines.last.text.should == result[1].lines.first.text
326
+ result[0].lines.last.sequence.should == result[1].lines.first.sequence
327
+ end
328
+ end
329
+
330
+ context "when passing { :at => \"00:19:24,500\", :renumber => true }" do
331
+ let(:result) { file.split( :at => "00:19:24,500", :renumber => true ) }
332
+
333
+ it "first line of second part's number should be one" do
334
+ result[1].lines.first.sequence.should == 1
335
+ end
336
+
337
+ it "sequence for the last line of first part should have different number than the sequence for the first line of second part" do
338
+ result[0].lines.last.text.should == result[1].lines.first.text
339
+ result[0].lines.last.sequence.should_not == result[1].lines.first.sequence
340
+ end
341
+ end
342
+
343
+ context "when passing { :at => \"00:19:24,500\", :timeshift => false }" do
344
+ let(:result) { file.split( :at => "00:19:24,500", :timeshift => false ) }
345
+
346
+ it "time for last line of first part should be the time for first line of second part" do
347
+ result[0].lines.last.text.should == result[1].lines.first.text
348
+ result[0].lines.last.time_str.should == result[1].lines.first.time_str
349
+ end
350
+ end
351
+
352
+ context "when passing { :at => \"00:19:24,500\", :timeshift => true }" do
353
+ let(:result) { file.split( :at => "00:19:24,500", :timeshift => true ) }
354
+
355
+ it "start_time of first line in second part should be 0" do
356
+ result[1].lines.first.start_time.should == 0
357
+ end
358
+
359
+ it "time for last line of first part should not be the time for first line of second part" do
360
+ result[0].lines.last.text.should == result[1].lines.first.text
361
+ result[0].lines.last.time_str.should_not == result[1].lines.first.time_str
362
+ end
363
+ end
284
364
  end
285
365
  end
286
366
 
@@ -383,6 +463,37 @@ END
383
463
  end
384
464
  end
385
465
  end
466
+
467
+ describe "#to_webvtt" do
468
+ context "when calling it on a short SRT file" do
469
+ let(:file) { SRT::File.parse(File.open("./spec/bsg-s01e01.srt")) }
470
+
471
+ before { file.lines = file.lines[0..2] }
472
+
473
+ it "should produce the exactly correct output" do
474
+ OUTPUT_WEBVTT =<<END
475
+ WEBVTT
476
+ X-TIMESTAMP-MAP=MPEGTS:0,LOCAL:00:00:00.000
477
+
478
+ 1
479
+ 00:00:02.110 --> 00:00:04.578
480
+ <i>(male narrator) Previously
481
+ on Battlestar Galactica.</i>
482
+
483
+ 2
484
+ 00:00:05.313 --> 00:00:06.871
485
+ Now you're telling me
486
+ you're a machine.
487
+
488
+ 3
489
+ 00:00:07.014 --> 00:00:08.003
490
+ The robot.
491
+ END
492
+ file.to_webvtt.should eq(OUTPUT_WEBVTT)
493
+ end
494
+ end
495
+ end
496
+
386
497
  end
387
498
  end
388
499
  end
@@ -10,6 +10,7 @@ Gem::Specification.new do |gem|
10
10
 
11
11
  gem.add_development_dependency('rake')
12
12
  gem.add_development_dependency('rspec')
13
+ gem.add_development_dependency('coveralls')
13
14
 
14
15
  gem.files = `git ls-files`.split($\)
15
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: srt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.9.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-02 00:00:00.000000000 Z
12
+ date: 2013-10-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: coveralls
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  description: Ruby gem for parsing srt (subtitle) files. SRT stands for SubRip text
47
63
  file format, which is a file for storing subtitles.
48
64
  email:
@@ -65,6 +81,8 @@ files:
65
81
  - spec/blackswan-part2.srt
66
82
  - spec/bsg-s01e01.srt
67
83
  - spec/coordinates-dummy.srt
84
+ - spec/invalid.srt
85
+ - spec/spec_helper.rb
68
86
  - spec/srt_spec.rb
69
87
  - spec/wotw-dubious.srt
70
88
  - srt.gemspec
@@ -82,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
82
100
  version: '0'
83
101
  segments:
84
102
  - 0
85
- hash: -455267047337616811
103
+ hash: 3664658785611759133
86
104
  required_rubygems_version: !ruby/object:Gem::Requirement
87
105
  none: false
88
106
  requirements:
@@ -91,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
109
  version: '0'
92
110
  segments:
93
111
  - 0
94
- hash: -455267047337616811
112
+ hash: 3664658785611759133
95
113
  requirements: []
96
114
  rubyforge_project:
97
115
  rubygems_version: 1.8.23
@@ -103,5 +121,7 @@ test_files:
103
121
  - spec/blackswan-part2.srt
104
122
  - spec/bsg-s01e01.srt
105
123
  - spec/coordinates-dummy.srt
124
+ - spec/invalid.srt
125
+ - spec/spec_helper.rb
106
126
  - spec/srt_spec.rb
107
127
  - spec/wotw-dubious.srt