titlekit 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +3 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +335 -0
- data/Rakefile +8 -0
- data/lib/titlekit/have.rb +90 -0
- data/lib/titlekit/job.rb +446 -0
- data/lib/titlekit/parsers/ass.rb +175 -0
- data/lib/titlekit/parsers/ass.treetop +72 -0
- data/lib/titlekit/parsers/srt.rb +139 -0
- data/lib/titlekit/parsers/srt.treetop +73 -0
- data/lib/titlekit/parsers/ssa.rb +201 -0
- data/lib/titlekit/parsers/ssa.treetop +72 -0
- data/lib/titlekit/specification.rb +131 -0
- data/lib/titlekit/utilities.rb +3 -0
- data/lib/titlekit/version.rb +3 -0
- data/lib/titlekit/want.rb +24 -0
- data/lib/titlekit.rb +9 -0
- data/spec/ass_spec.rb +113 -0
- data/spec/automatic_grouping/automatic_grouping_spec.rb +55 -0
- data/spec/automatic_grouping/dual_tracks/expected.srt +15 -0
- data/spec/automatic_grouping/dual_tracks/one.srt +11 -0
- data/spec/automatic_grouping/dual_tracks/out.srt +15 -0
- data/spec/automatic_grouping/dual_tracks/two.srt +11 -0
- data/spec/automatic_grouping/single_track/expected.srt +24 -0
- data/spec/automatic_grouping/single_track/one.srt +11 -0
- data/spec/automatic_grouping/single_track/out.srt +24 -0
- data/spec/automatic_grouping/single_track/two.srt +11 -0
- data/spec/encoding_detection/a/in.ass +0 -0
- data/spec/encoding_detection/b/in.srt +2389 -0
- data/spec/encoding_detection/b/out.srt +2389 -0
- data/spec/encoding_detection/c/in.srt +5320 -0
- data/spec/encoding_detection/c/out.srt +5320 -0
- data/spec/encoding_detection/encoding_detection_spec.rb +81 -0
- data/spec/files/ass/authentic.ass +0 -0
- data/spec/files/ass/hard.ass +37 -0
- data/spec/files/ass/simple.ass +28 -0
- data/spec/files/srt/authentic.srt +2708 -0
- data/spec/files/srt/coordinates.srt +13 -0
- data/spec/files/srt/simple.srt +12 -0
- data/spec/files/ssa/simple.ssa +26 -0
- data/spec/files/try/unsupported-output.try +0 -0
- data/spec/files/try/unsupported.try +7 -0
- data/spec/format_conversion/ass_srt/expected.srt +2327 -0
- data/spec/format_conversion/ass_srt/in.ass +485 -0
- data/spec/format_conversion/ass_srt/out.srt +2327 -0
- data/spec/format_conversion/format_conversion_spec.rb +112 -0
- data/spec/format_conversion/srt_ass/expected.ass +19 -0
- data/spec/format_conversion/srt_ass/in.srt +12 -0
- data/spec/format_conversion/srt_ass/out.ass +19 -0
- data/spec/format_conversion/srt_ssa/expected.ssa +19 -0
- data/spec/format_conversion/srt_ssa/in.srt +12 -0
- data/spec/format_conversion/srt_ssa/out.ssa +19 -0
- data/spec/format_conversion/ssa_srt/expected.srt +9 -0
- data/spec/format_conversion/ssa_srt/in.ssa +26 -0
- data/spec/format_conversion/ssa_srt/out.srt +9 -0
- data/spec/job_spec.rb +162 -0
- data/spec/simultaneous_subtitles/dual/ass/expected.ass +22 -0
- data/spec/simultaneous_subtitles/dual/ass/out.ass +22 -0
- data/spec/simultaneous_subtitles/dual/one.srt +11 -0
- data/spec/simultaneous_subtitles/dual/srt/expected.srt +27 -0
- data/spec/simultaneous_subtitles/dual/srt/out.srt +27 -0
- data/spec/simultaneous_subtitles/dual/ssa/expected.ssa +22 -0
- data/spec/simultaneous_subtitles/dual/ssa/out.ssa +22 -0
- data/spec/simultaneous_subtitles/dual/two.srt +11 -0
- data/spec/simultaneous_subtitles/simultaneous_subtitles_spec.rb +220 -0
- data/spec/simultaneous_subtitles/triple/ass/expected.ass +25 -0
- data/spec/simultaneous_subtitles/triple/ass/out.ass +25 -0
- data/spec/simultaneous_subtitles/triple/one.srt +11 -0
- data/spec/simultaneous_subtitles/triple/srt/expected.srt +55 -0
- data/spec/simultaneous_subtitles/triple/srt/out.srt +55 -0
- data/spec/simultaneous_subtitles/triple/ssa/expected.ssa +25 -0
- data/spec/simultaneous_subtitles/triple/ssa/out.ssa +25 -0
- data/spec/simultaneous_subtitles/triple/three.srt +11 -0
- data/spec/simultaneous_subtitles/triple/two.srt +11 -0
- data/spec/simultaneous_subtitles/triple_plus/ass/expected.ass +93 -0
- data/spec/simultaneous_subtitles/triple_plus/ass/out.ass +93 -0
- data/spec/simultaneous_subtitles/triple_plus/five.srt +11 -0
- data/spec/simultaneous_subtitles/triple_plus/four.srt +11 -0
- data/spec/simultaneous_subtitles/triple_plus/one.srt +11 -0
- data/spec/simultaneous_subtitles/triple_plus/six.srt +11 -0
- data/spec/simultaneous_subtitles/triple_plus/srt/expected.srt +149 -0
- data/spec/simultaneous_subtitles/triple_plus/srt/out.srt +149 -0
- data/spec/simultaneous_subtitles/triple_plus/ssa/expected.ssa +93 -0
- data/spec/simultaneous_subtitles/triple_plus/ssa/out.ssa +93 -0
- data/spec/simultaneous_subtitles/triple_plus/three.srt +11 -0
- data/spec/simultaneous_subtitles/triple_plus/two.srt +11 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/specifications_spec.rb +138 -0
- data/spec/srt_spec.rb +134 -0
- data/spec/ssa_spec.rb +90 -0
- data/spec/timecode_correction/double_reference/expected.srt +13 -0
- data/spec/timecode_correction/double_reference/in.srt +12 -0
- data/spec/timecode_correction/double_reference/out.srt +13 -0
- data/spec/timecode_correction/framerate/expected.srt +5 -0
- data/spec/timecode_correction/framerate/in.srt +4 -0
- data/spec/timecode_correction/framerate/out.srt +5 -0
- data/spec/timecode_correction/framerate_plus_reference/expected.srt +13 -0
- data/spec/timecode_correction/framerate_plus_reference/in.srt +12 -0
- data/spec/timecode_correction/framerate_plus_reference/out.srt +13 -0
- data/spec/timecode_correction/single_reference/expected.srt +13 -0
- data/spec/timecode_correction/single_reference/in.srt +12 -0
- data/spec/timecode_correction/single_reference/out.srt +13 -0
- data/spec/timecode_correction/timecode_correction_spec.rb +124 -0
- data/spec/transcoding/gb2312-ascii/in.srt +12 -0
- data/spec/transcoding/iso-8859-1_utf-8/expected.srt +12 -0
- data/spec/transcoding/iso-8859-1_utf-8/in.srt +11 -0
- data/spec/transcoding/iso-8859-1_utf-8/out.srt +12 -0
- data/spec/transcoding/transcoding_spec.rb +116 -0
- data/spec/transcoding/utf-8_gbk/expected.srt +12 -0
- data/spec/transcoding/utf-8_gbk/in.srt +11 -0
- data/spec/transcoding/utf-8_gbk/out.srt +12 -0
- data/spec/transcoding/windows-1252_utf-8/expected.srt +12 -0
- data/spec/transcoding/windows-1252_utf-8/in.srt +11 -0
- data/spec/transcoding/windows-1252_utf-8/out.srt +12 -0
- data/titlekit.gemspec +28 -0
- metadata +313 -0
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require File.join(File.expand_path(__dir__), 'spec_helper')
|
|
2
|
+
|
|
3
|
+
shared_examples 'a specification' do
|
|
4
|
+
|
|
5
|
+
describe '#new' do
|
|
6
|
+
it 'creates a new specification' do
|
|
7
|
+
expect(described_class.new).to be_a_kind_of(described_class)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe '#encoding' do
|
|
12
|
+
let(:specification) do
|
|
13
|
+
described_class.new.encoding('utf-8')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'returns the specification' do
|
|
17
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'returns the set encoding' do
|
|
21
|
+
expect(specification.encoding).to eq('utf-8')
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe '#file' do
|
|
26
|
+
let(:specification) do
|
|
27
|
+
described_class.new.file('the/path.srt')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'returns the specification' do
|
|
31
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'returns the set path' do
|
|
35
|
+
expect(specification.file).to eq('the/path.srt')
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe '#fps' do
|
|
40
|
+
let(:specification) do
|
|
41
|
+
described_class.new.fps(25)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'returns the specification' do
|
|
45
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'returns the set framerate' do
|
|
49
|
+
expect(specification.fps).to eq(25)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe '#reference' do
|
|
54
|
+
context 'specifying a minute' do
|
|
55
|
+
let(:specification) do
|
|
56
|
+
described_class.new.reference(:some_point, minutes: 3.5)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'returns the specification' do
|
|
60
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'returns the set named reference for a timecode' do
|
|
64
|
+
expect(specification.references[:some_point][:timecode]).to eq(210)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'specifying an SRT timecode' do
|
|
69
|
+
let(:specification) do
|
|
70
|
+
described_class.new.reference(:some_point, srt_timecode: '00:03:30,000')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'returns the specification' do
|
|
74
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'returns the set named reference for a timecode' do
|
|
78
|
+
expect(specification.references[:some_point][:timecode]).to eq(210)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'specifying an ASS timecode' do
|
|
83
|
+
let(:specification) do
|
|
84
|
+
described_class.new.reference(:some_point, ass_timecode: '0:03:30.00')
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'returns the specification' do
|
|
88
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'returns the set named reference for a timecode' do
|
|
92
|
+
expect(specification.references[:some_point][:timecode]).to eq(210)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context 'specifying an SSA timecode' do
|
|
97
|
+
let(:specification) do
|
|
98
|
+
described_class.new.reference(:some_point, ssa_timecode: '0:03:30.00')
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'returns the specification' do
|
|
102
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'returns the set named reference for a timecode' do
|
|
106
|
+
expect(specification.references[:some_point][:timecode]).to eq(210)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe Titlekit::Specification do
|
|
113
|
+
it_behaves_like 'a specification'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe Titlekit::Have do
|
|
117
|
+
it_behaves_like 'a specification'
|
|
118
|
+
|
|
119
|
+
describe '#reference' do
|
|
120
|
+
context 'specifying a subtitle' do
|
|
121
|
+
let(:specification) do
|
|
122
|
+
described_class.new.reference(:some_point, subtitle: 23)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'returns the specification' do
|
|
126
|
+
expect(specification).to be_a_kind_of(described_class)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'returns the set named reference for a subtitle' do
|
|
130
|
+
expect(specification.references[:some_point][:subtitle]).to eq(23)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
describe Titlekit::Want do
|
|
137
|
+
it_behaves_like 'a specification'
|
|
138
|
+
end
|
data/spec/srt_spec.rb
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require File.join(File.expand_path(__dir__), 'spec_helper')
|
|
2
|
+
|
|
3
|
+
describe Titlekit::SRT do
|
|
4
|
+
|
|
5
|
+
describe '.import' do
|
|
6
|
+
|
|
7
|
+
context 'with a simple file' do
|
|
8
|
+
let(:subtitles) do
|
|
9
|
+
Titlekit::SRT.import(File.read('spec/files/srt/simple.srt'))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'parses and builds 3 subtitles' do
|
|
13
|
+
expect(subtitles.length).to eq(3)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'parses and builds correct ids' do
|
|
17
|
+
expect(subtitles[0][:id]).to eq(1)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'parses and builds correct timecodes' do
|
|
21
|
+
expect(subtitles[1][:start]).to eq(24)
|
|
22
|
+
expect(subtitles[1][:end]).to eq(37.8)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'parses and builds correct lines' do
|
|
26
|
+
expect(subtitles[2][:lines]).to eq("- I ...\n- Enough!!!")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'with an authentic file' do
|
|
31
|
+
let(:subtitles) do
|
|
32
|
+
Titlekit::SRT.import(File.read('spec/files/srt/authentic.srt'))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'parses and builds 600 subtitles' do
|
|
36
|
+
expect(subtitles.length).to eq(600)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'parses and builds correct ids' do
|
|
40
|
+
expect(subtitles[599][:id]).to eq(600)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'parses and builds correct timecodes' do
|
|
44
|
+
expect(subtitles[299][:start]).to eq(1426.564)
|
|
45
|
+
expect(subtitles[299][:end]).to eq(1428.759)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'parses and builds correct lines' do
|
|
49
|
+
expect(subtitles[0][:lines]).to eq("<i>(male narrator) Previously\r\non Battlestar Galactica.</i>")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'with a file that contains coordinates' do
|
|
54
|
+
let(:subtitles) do
|
|
55
|
+
Titlekit::SRT.import(File.read('spec/files/srt/coordinates.srt'))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'parses and builds 3 subtitles' do
|
|
59
|
+
expect(subtitles.length).to eq(3)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'parses and builds correct ids' do
|
|
63
|
+
expect(subtitles[0][:id]).to eq(1)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'parses and builds correct timecodes' do
|
|
67
|
+
expect(subtitles[1][:start]).to eq(16)
|
|
68
|
+
expect(subtitles[1][:end]).to eq(32)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'parses and builds correct lines' do
|
|
72
|
+
expect(subtitles[2][:lines]).to eq("A: Still I'm implementing them; Whatevs.")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'ignores the display coordinates' do
|
|
76
|
+
# just fyi
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe '.export' do
|
|
82
|
+
it 'should export valid SRT' do
|
|
83
|
+
subtitles = [
|
|
84
|
+
{
|
|
85
|
+
id: 1,
|
|
86
|
+
start: 1.5,
|
|
87
|
+
end: 3.7,
|
|
88
|
+
lines: 'Eine feine Testung haben sie da!'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 2,
|
|
92
|
+
start: 1.5,
|
|
93
|
+
end: 3.7,
|
|
94
|
+
lines: '¡Sí claro! Pero que lastima que no es 100% español ...'
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: 3,
|
|
98
|
+
start: 1.5,
|
|
99
|
+
end: 3.7,
|
|
100
|
+
lines: 'Oh yeah ... 寧為太平犬,不做亂世人'
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
expected = <<-EXPECTED
|
|
105
|
+
1
|
|
106
|
+
00:00:01,500 --> 00:00:03,700
|
|
107
|
+
Eine feine Testung haben sie da!
|
|
108
|
+
|
|
109
|
+
2
|
|
110
|
+
00:00:01,500 --> 00:00:03,700
|
|
111
|
+
¡Sí claro! Pero que lastima que no es 100% español ...
|
|
112
|
+
|
|
113
|
+
3
|
|
114
|
+
00:00:01,500 --> 00:00:03,700
|
|
115
|
+
Oh yeah ... 寧為太平犬,不做亂世人
|
|
116
|
+
|
|
117
|
+
EXPECTED
|
|
118
|
+
|
|
119
|
+
expect(Titlekit::SRT.export(subtitles)).to eq(expected)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe '.build_timecode' do
|
|
124
|
+
it 'builds an SRT timecode from a float timecode value' do
|
|
125
|
+
expect(Titlekit::SRT.build_timecode(35.9678)).to eq('00:00:35,968')
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
describe '.parse_timecode' do
|
|
130
|
+
it 'obtains a float timecode value from an SRT timecode' do
|
|
131
|
+
expect(Titlekit::SRT.parse_timecode('00:00:35,968')).to eq(35.968)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
data/spec/ssa_spec.rb
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require File.join(File.expand_path(__dir__), 'spec_helper')
|
|
2
|
+
|
|
3
|
+
describe Titlekit::SSA do
|
|
4
|
+
|
|
5
|
+
describe '.import' do
|
|
6
|
+
|
|
7
|
+
context 'with a simple file' do
|
|
8
|
+
let(:subtitles) do
|
|
9
|
+
Titlekit::SSA.import(File.read('spec/files/ssa/simple.ssa'))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'parses and builds 3 subtitles' do
|
|
13
|
+
expect(subtitles.length).to eq(2)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'parses and builds correct ids' do
|
|
17
|
+
expect(subtitles[0][:id]).to eq(1)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'parses and builds correct timecodes' do
|
|
21
|
+
expect(subtitles[1][:start]).to eq(11.84)
|
|
22
|
+
expect(subtitles[1][:end]).to eq(14.74)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'parses and builds correct lines' do
|
|
26
|
+
expect(subtitles[1][:lines]).to eq("{\\a2}Story Script & Direction - MIYAZAKI Hayao")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '.export' do
|
|
32
|
+
it 'should export valid SSA' do
|
|
33
|
+
subtitles = [
|
|
34
|
+
{
|
|
35
|
+
start: 1.5,
|
|
36
|
+
end: 3.7,
|
|
37
|
+
lines: 'Eine feine Testung haben sie da!'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 2,
|
|
41
|
+
start: 1.5,
|
|
42
|
+
end: 3.7,
|
|
43
|
+
lines: '¡Sí claro! Pero que lastima que no es 100% español ...'
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 3,
|
|
47
|
+
start: 1.5,
|
|
48
|
+
end: 3.7,
|
|
49
|
+
lines: 'Oh yeah ... 寧為太平犬,不做亂世人'
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
expected = <<-EXPECTED
|
|
54
|
+
[Script Info]
|
|
55
|
+
ScriptType: v4.00
|
|
56
|
+
|
|
57
|
+
[V4 Styles]
|
|
58
|
+
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
|
|
59
|
+
Style: Default,Arial,16,16777215,16777215,16777215,-2147483640,0,0,1,3,0,2,70,70,40,0,0
|
|
60
|
+
Style: Middle,Arial,16,16777215,16777215,16777215,-2147483640,0,0,1,3,0,10,70,70,40,0,0
|
|
61
|
+
Style: Top,Arial,16,16777215,16777215,16777215,-2147483640,0,0,1,3,0,6,70,70,40,0,0
|
|
62
|
+
Style: EDF393,Arial,16,9696237,9696237,9696237,-2147483640,0,0,1,3,0,2,70,70,40,0,0
|
|
63
|
+
Style: F5E665,Arial,16,6678261,6678261,6678261,-2147483640,0,0,1,3,0,2,70,70,40,0,0
|
|
64
|
+
Style: FFC472,Arial,16,7521535,7521535,7521535,-2147483640,0,0,1,3,0,2,70,70,40,0,0
|
|
65
|
+
Style: FFA891,Arial,16,9545983,9545983,9545983,-2147483640,0,0,1,3,0,2,70,70,40,0,0
|
|
66
|
+
Style: 89BABE,Arial,16,12499593,12499593,12499593,-2147483640,0,0,1,3,0,2,70,70,40,0,0
|
|
67
|
+
|
|
68
|
+
[Events]
|
|
69
|
+
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
|
70
|
+
Dialogue: 0,0:00:01.50,0:00:03.70,Default,,0000,0000,0000,,Eine feine Testung haben sie da!
|
|
71
|
+
Dialogue: 0,0:00:01.50,0:00:03.70,Default,,0000,0000,0000,,¡Sí claro! Pero que lastima que no es 100% español ...
|
|
72
|
+
Dialogue: 0,0:00:01.50,0:00:03.70,Default,,0000,0000,0000,,Oh yeah ... 寧為太平犬,不做亂世人
|
|
73
|
+
EXPECTED
|
|
74
|
+
|
|
75
|
+
expect(Titlekit::SSA.export(subtitles)).to eq(expected)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe '.build_timecode' do
|
|
80
|
+
it 'builds an SSA timecode from a float timecode value' do
|
|
81
|
+
expect(Titlekit::SSA.build_timecode(35.9678)).to eq('0:00:35.97')
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe '.parse_timecode' do
|
|
86
|
+
it 'obtains a float timecode value from an SSA timecode' do
|
|
87
|
+
expect(Titlekit::SSA.parse_timecode('0:00:35.96')).to eq(35.96)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require File.join(File.expand_path(__dir__), '../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe Titlekit::Job do
|
|
4
|
+
|
|
5
|
+
describe 'Timecode correction' do
|
|
6
|
+
|
|
7
|
+
context 'Based on differing framerates' do
|
|
8
|
+
before(:all) do
|
|
9
|
+
@in = File.join(__dir__, 'framerate', 'in.srt')
|
|
10
|
+
@out = File.join(__dir__, 'framerate', 'out.srt')
|
|
11
|
+
@expected = File.join(__dir__, 'framerate', 'expected.srt')
|
|
12
|
+
|
|
13
|
+
File.delete(@out) if File.exist?(@out)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'runs the job' do
|
|
17
|
+
job = Titlekit::Job.new
|
|
18
|
+
|
|
19
|
+
have = job.have
|
|
20
|
+
have.file(@in)
|
|
21
|
+
have.fps(25)
|
|
22
|
+
|
|
23
|
+
want = job.want
|
|
24
|
+
want.file(@out)
|
|
25
|
+
want.fps(30)
|
|
26
|
+
|
|
27
|
+
expect(job.run).to be_true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'delivers the expected output' do
|
|
31
|
+
expect(FileUtils.compare_file(@out, @expected)).to be_true
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'Based on a single reference' do
|
|
36
|
+
before(:all) do
|
|
37
|
+
@in = File.join(__dir__, 'single_reference', 'in.srt')
|
|
38
|
+
@out = File.join(__dir__, 'single_reference', 'out.srt')
|
|
39
|
+
@expected = File.join(__dir__, 'single_reference', 'expected.srt')
|
|
40
|
+
|
|
41
|
+
File.delete(@out) if File.exist?(@out)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'runs the job' do
|
|
45
|
+
job = Titlekit::Job.new
|
|
46
|
+
|
|
47
|
+
have = job.have
|
|
48
|
+
have.file(@in)
|
|
49
|
+
have.reference('first subtitle', seconds: 2)
|
|
50
|
+
|
|
51
|
+
want = job.want
|
|
52
|
+
want.file(@out)
|
|
53
|
+
want.reference('first subtitle', seconds: 3.5)
|
|
54
|
+
|
|
55
|
+
expect(job.run).to be_true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'delivers the expected output' do
|
|
59
|
+
expect(FileUtils.compare_file(@out, @expected)).to be_true
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'Based on differing framerates plus a reference' do
|
|
64
|
+
before(:all) do
|
|
65
|
+
@in = File.join(__dir__, 'framerate_plus_reference', 'in.srt')
|
|
66
|
+
@out = File.join(__dir__, 'framerate_plus_reference', 'out.srt')
|
|
67
|
+
@expected = File.join(__dir__, 'framerate_plus_reference', 'expected.srt')
|
|
68
|
+
|
|
69
|
+
File.delete(@out) if File.exist?(@out)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'runs the job' do
|
|
73
|
+
job = Titlekit::Job.new
|
|
74
|
+
|
|
75
|
+
have = job.have
|
|
76
|
+
have.file(@in)
|
|
77
|
+
have.fps(25)
|
|
78
|
+
have.reference('first subtitle', subtitle: 0)
|
|
79
|
+
|
|
80
|
+
want = job.want
|
|
81
|
+
want.file(@out)
|
|
82
|
+
have.fps(23.976)
|
|
83
|
+
want.reference('first subtitle', seconds: 3.5)
|
|
84
|
+
|
|
85
|
+
expect(job.run).to be_true
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'delivers the expected output' do
|
|
89
|
+
expect(FileUtils.compare_file(@out, @expected)).to be_true
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context 'Based on two references' do
|
|
94
|
+
before(:all) do
|
|
95
|
+
@in = File.join(__dir__, 'double_reference', 'in.srt')
|
|
96
|
+
@out = File.join(__dir__, 'double_reference', 'out.srt')
|
|
97
|
+
@expected = File.join(__dir__, 'double_reference', 'expected.srt')
|
|
98
|
+
|
|
99
|
+
File.delete(@out) if File.exist?(@out)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'runs the job' do
|
|
103
|
+
job = Titlekit::Job.new
|
|
104
|
+
|
|
105
|
+
have = job.have
|
|
106
|
+
have.file(@in)
|
|
107
|
+
have.reference('first subtitle', seconds: 2.364)
|
|
108
|
+
have.reference('last subtitle', seconds: 24)
|
|
109
|
+
|
|
110
|
+
want = job.want
|
|
111
|
+
want.file(@out)
|
|
112
|
+
want.reference('first subtitle', seconds: 2.4)
|
|
113
|
+
want.reference('last subtitle', seconds: 32)
|
|
114
|
+
|
|
115
|
+
expect(job.run).to be_true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'delivers the expected output' do
|
|
119
|
+
expect(FileUtils.compare_file(@out, @expected)).to be_true
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
end
|