subconv 0.1.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.
@@ -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