subconv 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 28cd6dd4e5675ee424b07b6ad013fb694e9145b8
4
+ data.tar.gz: b81878db9e8705adf103bd0ecd40466e54512f77
5
+ SHA512:
6
+ metadata.gz: a7ac077fc7d2691d74141d49e99051b0679202ac40625f8150846c0f625db85614e636a866db1916b465290143dae41549dd4b98f4712bffd4e11e2c6a7b4995
7
+ data.tar.gz: 646035c2eaaa3e9726621f552fdd44c0b27b56733f6a7dd70c4677e21fd72893e2748177727e027a6ab5719d9a8afc5ca0da0926f9d278922ed501431e034080
@@ -0,0 +1,39 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ /nbproject/
19
+
20
+ ## Documentation cache and generated files:
21
+ /.yardoc/
22
+ /_yardoc/
23
+ /doc/
24
+ /rdoc/
25
+
26
+ ## Environment normalization:
27
+ /.bundle/
28
+ /vendor/bundle
29
+ /lib/bundler/man/
30
+
31
+ # for a library or gem, you might want to ignore these files since the code is
32
+ # intended to run in multiple environments; otherwise, check them in:
33
+ Gemfile.lock
34
+
35
+ # .ruby-version
36
+ # .ruby-gemset
37
+
38
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
39
+ .rvmrc
@@ -0,0 +1,74 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.2
3
+ Exclude:
4
+ - '**/bin/**/*'
5
+ - '**/db/schema.rb'
6
+ - '**/config/**/*'
7
+ - '**/lib/tasks/*.rake'
8
+
9
+ # Use only ascii symbols in identifiers.
10
+ AsciiComments:
11
+ Enabled: false
12
+
13
+ # Document classes and non-namespace modules.
14
+ Documentation:
15
+ Enabled: false
16
+
17
+ # Limit lines to 79 characters.
18
+ LineLength:
19
+ Enabled: false
20
+
21
+ BlockDelimiters:
22
+ EnforcedStyle: semantic
23
+
24
+ MethodLength:
25
+ Max: 30
26
+
27
+ # Checks for proper usage of fail and raise.
28
+ #SignalException:
29
+ # Enabled: false
30
+
31
+ StringLiterals:
32
+ EnforcedStyle: single_quotes
33
+
34
+ # Avoid the use of attr. Use attr_reader and attr_accessor instead.
35
+ Attr:
36
+ Enabled: false
37
+
38
+ UnusedBlockArgument:
39
+ AutoCorrect: false
40
+
41
+ UnusedMethodArgument:
42
+ AutoCorrect: false
43
+
44
+ CyclomaticComplexity:
45
+ Max: 30
46
+
47
+ # https://github.com/bbatsov/ruby-style-guide/issues/395
48
+ RaiseArgs:
49
+ Enabled: false
50
+
51
+ AbcSize:
52
+ Max: 20
53
+
54
+ TrivialAccessors:
55
+ AllowPredicates: true
56
+
57
+ AlignHash:
58
+ EnforcedHashRocketStyle: table
59
+ EnforcedColonStyle: table
60
+
61
+ IndentArray:
62
+ EnforcedStyle: consistent
63
+
64
+ SignalException:
65
+ EnforcedStyle: semantic
66
+
67
+ #MultilineMethodCallIndentation:
68
+ # EnforcedStyle: indented
69
+ #
70
+ #MultilineOperationIndentation:
71
+ # EnforcedStyle: indented
72
+ #
73
+ #AlignParameters:
74
+ # Enabled: false
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.3
4
+ - 2.3.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Philipp Kerling
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,59 @@
1
+ [![Gem Version](https://badge.fury.io/rb/subconv.svg)](http://badge.fury.io/rb/subconv)
2
+ [![Dependency Status](https://gemnasium.com/pkerling/subconv.svg)](https://gemnasium.com/pkerling/subconv)
3
+ [![Build Status](https://travis-ci.org/pkerling/subconv.svg?branch=master)](https://travis-ci.org/pkerling/subconv)
4
+ [![Coverage Status](https://coveralls.io/repos/github/pkerling/subconv/badge.svg?branch=master)](https://coveralls.io/github/pkerling/subconv?branch=master)
5
+ [![Inline docs](http://inch-ci.org/github/pkerling/subconv.svg?branch=master)](http://inch-ci.org/github/pkerling/subconv)
6
+
7
+ subconv - Ruby SCC (EIA-608) to WebVTT subtitle converter
8
+ =========================================================
9
+
10
+ This Ruby Gem provides conversion of subtitle files in the .scc (Scenarist Closed
11
+ Captions) format to the more modern WebVTT format that can be used in browsers
12
+ with HTML5 videos.
13
+
14
+ The processing is modeled after [this paper by the W3C](https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html).
15
+
16
+ Installation
17
+ ------------
18
+ gem install subconv
19
+
20
+ Usage
21
+ -----
22
+ $ subconv --help
23
+ Usage: subconv [options] SCC-FILE
24
+ -o, --out-file FILENAME Write output to specified file instead of stdout
25
+ -f, --fps FPS Assume given video fps for timecode calculation (default: 29.97)
26
+ -c, --no-color Remove all color information from output
27
+ -F, --no-flash Remove all flash (blinking) information from output
28
+ -s, --simple-positions Convert to simple top/bottom center-aligned captions
29
+ -h, --help Show this help message and quit.
30
+
31
+ The API can also be used programmatically, the `bin/subconv` file is just an
32
+ example for this.
33
+
34
+ Supported features
35
+ ------------------
36
+ * EIA-608 parsing and conversion to WebVTT
37
+ * Pop-on captions
38
+ * Full positioning
39
+ * All special characters defined in the standard
40
+ * All colors
41
+ * Italics
42
+ * Underline
43
+ * Flash
44
+ * Optional removal of certain features during the conversion
45
+ * Color
46
+ * Flash
47
+ * Conversion of fine position information to just top/bottom center
48
+
49
+ Note that with all features removed, most browsers can display the captions as-is,
50
+ but for the colors etc. to work you will need to include a stylesheet that defines
51
+ appropriate styles. The one used in the W3C report is packaged here in `dist/eia608.css`.
52
+ Even then, browsers currently do not correctly support numerous settings yet. Infamously,
53
+ Firefox can not apply classes/styles inside cues at all.
54
+
55
+ Unsupported features
56
+ --------------------
57
+ * Roll-up captions
58
+ * Paint-on captions
59
+ * EIA-708
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new do |task|
7
+ task.options = ['--fail-level', 'warning']
8
+ end
9
+
10
+ task default: [:spec, :rubocop]
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ require 'subconv'
3
+ require 'optparse'
4
+
5
+ # Parse options
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = 'Usage: subconv [options] SCC-FILE'
9
+ opts.on('-o', '--out-file FILENAME', 'Write output to specified file instead of stdout') do |filename|
10
+ options[:out_file] = filename
11
+ end
12
+ opts.on('-f', '--fps FPS', 'Assume given video fps for timecode calculation (default: 29.97)') do |fps|
13
+ options[:fps] = fps
14
+ end
15
+ opts.on('-c', '--no-color', 'Remove all color information from output') do
16
+ options[:no_color] = true
17
+ end
18
+ opts.on('-F', '--no-flash', 'Remove all flash (blinking) information from output') do
19
+ options[:no_flash] = true
20
+ end
21
+ opts.on('-s', '--simple-positions', 'Convert to simple top/bottom center-aligned captions') do
22
+ options[:simple_positions] = true
23
+ end
24
+ opts.on_tail('-h', '--help', 'Show this help message and quit.') do
25
+ puts opts.help
26
+ exit
27
+ end
28
+ end.parse!
29
+ options[:in_file] = ARGV.pop
30
+ raise 'No SCC file given to process' unless options[:in_file]
31
+ options[:fps] = 29.97 if options[:fps].nil?
32
+
33
+ # Do conversion
34
+ reader = Subconv::Scc::Reader.new
35
+ File.open(options[:in_file], File::RDONLY) do |file|
36
+ reader.read(file, options[:fps].to_f)
37
+ end
38
+ captions = Subconv::Scc::Transformer.new.transform reader.captions
39
+ filter_options = {}
40
+ filter_options[:remove_color] = true if options[:no_color]
41
+ filter_options[:remove_flash] = true if options[:no_flash]
42
+ if options[:simple_positions]
43
+ filter_options[:merge_by_position] = true
44
+ filter_options[:xy_position_to_top_or_bottom] = true
45
+ end
46
+ Subconv::CaptionFilter.new(filter_options).process! captions
47
+ writer = Subconv::WebVtt::Writer.new trim_line_whitespace: true
48
+
49
+ # Write result
50
+ if options[:out_file]
51
+ File.open(options[:out_file], File::WRONLY | File::TRUNC | File::CREAT) do |file|
52
+ writer.write(file, captions)
53
+ end
54
+ else
55
+ writer.write(STDOUT, captions)
56
+ end
57
+
58
+ STDERR.write("#{captions.length} captions written\n")
@@ -0,0 +1,106 @@
1
+ /* default values */
2
+ ::cue {
3
+ line-height: 5.33vh;
4
+ font-size: 4.1vh;
5
+ font-family: monospace;
6
+ font-style: normal;
7
+ font-weight: normal;
8
+ background-color: black;
9
+ color: white;
10
+ }
11
+ /* special cue parts */
12
+ ::cue(c.transparent) {
13
+ color: transparent;
14
+ }
15
+ /* need to set this before changing color, otherwise the color is lost */
16
+ ::cue(c.semi-transparent) {
17
+ color: rgba(0, 0, 0, 0.5);
18
+ }
19
+ /* need to set this before changing color, otherwise the color is lost */
20
+ ::cue(c.opaque) {
21
+ color: rgba(0, 0, 0, 1);
22
+ }
23
+ ::cue(c.blink) {
24
+ text-decoration: blink;
25
+ }
26
+ ::cue(c.white) {
27
+ color: white;
28
+ }
29
+ ::cue(c.red) {
30
+ color: red;
31
+ }
32
+ ::cue(c.green) {
33
+ color: lime;
34
+ }
35
+ ::cue(c.blue) {
36
+ color: blue;
37
+ }
38
+ ::cue(c.cyan) {
39
+ color: cyan;
40
+ }
41
+ ::cue(c.yellow) {
42
+ color: yellow;
43
+ }
44
+ ::cue(c.magenta) {
45
+ color: magenta;
46
+ }
47
+ ::cue(c.bg_transparent) {
48
+ background-color: transparent;
49
+ }
50
+ /* need to set this before changing color, otherwise the color is lost */
51
+ ::cue(c.bg_semi-transparent) {
52
+ background-color: rgba(0, 0, 0, 0.5);
53
+ }
54
+ /* need to set this before changing color, otherwise the color is lost */
55
+ ::cue(c.bg_opaque) {
56
+ background-color: rgba(0, 0, 0, 1);
57
+ }
58
+ ::cue(c.bg_white) {
59
+ background-color: white;
60
+ }
61
+ ::cue(c.bg_green) {
62
+ background-color: lime;
63
+ }
64
+ ::cue(c.bg_blue) {
65
+ background-color: blue;
66
+ }
67
+ ::cue(c.bg_cyan) {
68
+ background-color: cyan;
69
+ }
70
+ ::cue(c.bg_red) {
71
+ background-color: red;
72
+ }
73
+ ::cue(c.bg_yellow) {
74
+ background-color: yellow;
75
+ }
76
+ ::cue(c.bg_magenta) {
77
+ background-color: magenta;
78
+ }
79
+ ::cue(c.bg_black) {
80
+ background-color: black;
81
+ }
82
+ /* Examples of combined colors */
83
+ ::cue(c.bg_white.bg_semi-transparent) {
84
+ background-color: rgba(255, 255, 255, 0.5);
85
+ }
86
+ ::cue(c.bg_green.bg_semi-transparent) {
87
+ background-color: rgba(0, 256, 0, 0.5);
88
+ }
89
+ ::cue(c.bg_blue.bg_semi-transparent) {
90
+ background-color: rgba(0, 0, 255, 0.5);
91
+ }
92
+ ::cue(c.bg_cyan.bg_semi-transparent) {
93
+ background-color: rgba(0, 255, 255, 0.5);
94
+ }
95
+ ::cue(c.bg_red.bg_semi-transparent) {
96
+ background-color: rgba(255, 0, 0, 0.5);
97
+ }
98
+ ::cue(c.bg_yellow.bg_semi-transparent) {
99
+ background-color: rgba(255, 255, 0, 0.5);
100
+ }
101
+ ::cue(c.bg_magenta.bg_semi-transparent) {
102
+ background-color: rgba(255, 0, 255, 0.5);
103
+ }
104
+ ::cue(c.bg_black.bg_semi-transparent) {
105
+ background-color: rgba(0, 0, 0, 0.5);
106
+ }
@@ -0,0 +1,5 @@
1
+ require 'subconv/version'
2
+ require 'subconv/scc/reader'
3
+ require 'subconv/scc/transformer'
4
+ require 'subconv/webvtt/writer'
5
+ require 'subconv/caption_filter'
@@ -0,0 +1,106 @@
1
+ module Subconv
2
+ # Two-dimensional screen position relative (both x and y position between 0 and 1) to the screen size
3
+ class Position
4
+ def initialize(x, y)
5
+ self.x = x
6
+ self.y = y
7
+ end
8
+
9
+ def ==(other)
10
+ # Ignore small differences in the position
11
+ self.class == other.class && (@x - other.x).abs < 0.01 && (@y - other.y).abs < 0.01
12
+ end
13
+
14
+ attr_reader :x, :y
15
+
16
+ # Force x position to be a float between 0 and 1
17
+ def x=(x)
18
+ x = x.to_f
19
+ fail RangeError, 'X position not between 0 and 1' unless x.between?(0.0, 1.0)
20
+ @x = x
21
+ end
22
+
23
+ # Force y position to be a float between 0 and 1
24
+ def y=(y)
25
+ y = y.to_f
26
+ fail RangeError, 'Y position not between 0 and 1' unless y.between?(0.0, 1.0)
27
+ @y = y
28
+ end
29
+ end
30
+
31
+ # Base class for all nodes
32
+ class CaptionNode; end
33
+
34
+ # Node that contains text
35
+ class TextNode < CaptionNode
36
+ def initialize(text)
37
+ @text = text
38
+ end
39
+
40
+ def ==(other)
41
+ self.class == other.class && @text == other.text
42
+ end
43
+
44
+ attr_accessor :text
45
+ end
46
+
47
+ # Node that contains other nodes
48
+ class ContainerNode < CaptionNode
49
+ def initialize(children = [])
50
+ self.children = children
51
+ end
52
+
53
+ def ==(other)
54
+ self.class == other.class && @children == other.children
55
+ end
56
+
57
+ attr_reader :children
58
+
59
+ def children=(children)
60
+ fail 'Children must be an array' unless children.class == Array
61
+ @children = children
62
+ end
63
+ end
64
+
65
+ # Special node used as root element for all content
66
+ class RootNode < ContainerNode; end
67
+
68
+ # Italics style node
69
+ class ItalicsNode < ContainerNode; end
70
+ # Underline style node
71
+ class UnderlineNode < ContainerNode; end
72
+ # Flash style node
73
+ class FlashNode < ContainerNode; end
74
+ # Color style node
75
+ class ColorNode < ContainerNode
76
+ # Color should be given as symbol, e.g. :white, :red, :blue, ...
77
+ def initialize(color, children = [])
78
+ super children
79
+ @color = color
80
+ end
81
+
82
+ def ==(other)
83
+ super(other) && @color == other.color
84
+ end
85
+
86
+ attr_accessor :color
87
+ end
88
+
89
+ # Caption displayed on the screen at a specific position for a given amount of time
90
+ class Caption
91
+ def initialize(params)
92
+ # :start, :middle or :end
93
+ @align = params[:align]
94
+ @timespan = params[:timespan]
95
+ # Position instance, :top or :bottom
96
+ @position = params[:position]
97
+ @content = params[:content]
98
+ end
99
+
100
+ def ==(other)
101
+ self.class == other.class && @timespan == other.timespan && @position == other.position && @content == other.content
102
+ end
103
+
104
+ attr_accessor :timespan, :position, :align, :content
105
+ end
106
+ end