srt_subtitle_validator 0.1.7
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 +10 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +38 -0
- data/Rakefile +2 -0
- data/bin/srt_checker +6 -0
- data/lib/srt_subtitle_validator/cli.rb +57 -0
- data/lib/srt_subtitle_validator/srt_file.rb +43 -0
- data/lib/srt_subtitle_validator/validator.rb +89 -0
- data/lib/srt_subtitle_validator/version.rb +3 -0
- data/lib/srt_subtitle_validator.rb +26 -0
- data/srt_subtitle_validator.gemspec +27 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 76cc266523c735a5fb9a42a316b50100d589a02188590dff783924a4738abb1f
|
4
|
+
data.tar.gz: 351be1177c397d13ff9b6e5c26c4e61de2f25c227eb84824ebc1e25cd95b5d25
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 870c37daededdda8ebc614c8f2dcef8bf07b4253e3ff98f783eb452e366523e70e1994264b011994440b0376979b0dfbb801896ad46ecbdcfcc7c3f4de077d3d
|
7
|
+
data.tar.gz: b679b8d97f323a55cd95dc1e4374edd82ffe48e4bfa4ed350756a140e5a82b0be4b045edb863b8c5be90b553f4d3b605a8a1e48c2fcfe73455f54097c8e489f9
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Lukáš Pokorný
|
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
|
13
|
+
all 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
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# SRT subtitle validator & converter
|
2
|
+
|
3
|
+
Check SRT file and try to fix it.
|
4
|
+
|
5
|
+
* Convert to UTF-8
|
6
|
+
* Convert line-endings to UNIX/Linux
|
7
|
+
* Recreate number counter sequence
|
8
|
+
|
9
|
+
## Why?
|
10
|
+
Because in my case Plex server & TV doesn't show subtitle correctly.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
```ruby
|
14
|
+
gem install 'srt_subtitle_validator'
|
15
|
+
```
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
* Process files are overwritten with results.
|
20
|
+
* For all processed files are created backup.
|
21
|
+
|
22
|
+
|
23
|
+
### For analyze
|
24
|
+
```
|
25
|
+
srt_checker check <path to SRT file(s)>
|
26
|
+
```
|
27
|
+
|
28
|
+
### For direct convert
|
29
|
+
```
|
30
|
+
srt_checker convert <path to SRT file(s)>
|
31
|
+
```
|
32
|
+
|
33
|
+
### General options
|
34
|
+
`--output, -o` : Specify output directory of file. By default its same as input
|
35
|
+
|
36
|
+
`--without_backup` : Skip creating backup files.
|
37
|
+
|
38
|
+
`--encoding, -e` : Encoding of input file. By default it's windows-1250
|
data/Rakefile
ADDED
data/bin/srt_checker
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'srt_subtitle_validator'
|
2
|
+
require 'thor'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
if %w(--version -v).include?(ARGV.first)
|
6
|
+
puts "Srt Subtitle Validator #{SrtSubtitleValidator::VERSION}"
|
7
|
+
exit(0)
|
8
|
+
end
|
9
|
+
module SrtSubtitleValidator
|
10
|
+
class Cli < Thor
|
11
|
+
|
12
|
+
class_option :version, type: :boolean, aliases: '-v', group: :main,
|
13
|
+
desc: 'Show version number and quit'
|
14
|
+
|
15
|
+
def self.srt_default_options
|
16
|
+
method_option :without_backup, :default => false, :type => :boolean, :desc => 'Skip backuping original SRT file'
|
17
|
+
method_option :output, :aliases => '-o', :default => nil, :type => :string, :desc => 'Output directory (file)'
|
18
|
+
method_option :encoding, :aliases => '-e', :default => Encoding::CP1250, :type => :string, :desc => 'Output directory (file)'
|
19
|
+
end
|
20
|
+
|
21
|
+
srt_default_options
|
22
|
+
desc 'check', 'Check SRT file. '
|
23
|
+
|
24
|
+
def check(*files)
|
25
|
+
files_to_convert = Array.new
|
26
|
+
Array(files).each do |file|
|
27
|
+
validator = SrtSubtitleValidator::Validator.new(file)
|
28
|
+
say("\n == #{validator.file_name} -> ")
|
29
|
+
if validator.valid?
|
30
|
+
say 'SRT file is valid', :green
|
31
|
+
else
|
32
|
+
say 'SRT file is invalid, with following errors: ', :red, true
|
33
|
+
validator.srt.errors.each { |e| say "* #{e}" }
|
34
|
+
files_to_convert << validator
|
35
|
+
end
|
36
|
+
end
|
37
|
+
if files_to_convert.any? && yes?("Try to convert #{files_to_convert.length} files ?")
|
38
|
+
files_to_convert.each{|f| f.convert_srt(options[:output], options[:without_backup])}
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
srt_default_options
|
44
|
+
desc 'convert', 'Check files and fix them if needed'
|
45
|
+
|
46
|
+
def convert(*files)
|
47
|
+
Array(files).each do |file|
|
48
|
+
validator = SrtSubtitleValidator::Validator.new(file)
|
49
|
+
unless validator.valid?
|
50
|
+
validator.convert_srt(options[:output], options[:without_backup])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
SrtSubtitleValidator::Cli.start
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module SrtSubtitleValidator
|
2
|
+
class SrtFile
|
3
|
+
attr_reader :blocks, :length
|
4
|
+
attr_accessor :errors
|
5
|
+
def initialize(source, logger = nil)
|
6
|
+
@logger = logger || Logger.new(STDOUT)
|
7
|
+
@errors = Array.new
|
8
|
+
x = source.dup.encode(Encoding::UTF_8).gsub(/\r/, '')
|
9
|
+
@srt_dialog_blocks = Hash.new
|
10
|
+
@blocks = x.split(/^\r?\n+/m).map { |n| i = SrtBlock.new(n); @srt_dialog_blocks[i.dialog_number] = i; i }
|
11
|
+
@length = !@blocks.empty? && @blocks.last.dialog_number || 0
|
12
|
+
@errors << 'File is zero size' if @length.zero?
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
unless @blocks.count == @length
|
17
|
+
@errors << 'Numbers sequence is corrupted'
|
18
|
+
end
|
19
|
+
@errors.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
class SrtBlock
|
23
|
+
attr_accessor :dialog_number, :dialog_time, :dialog_text
|
24
|
+
def initialize(*args)
|
25
|
+
case args.count
|
26
|
+
when 1
|
27
|
+
blok = args[0].split("\n")
|
28
|
+
@dialog_number = blok.shift.to_i
|
29
|
+
@dialog_time = blok.shift
|
30
|
+
@dialog_text = blok.join("\n")
|
31
|
+
when 3
|
32
|
+
@dialog_number, @dialog_time, @dialog_text = args
|
33
|
+
else
|
34
|
+
raise ArgumentError
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
[@dialog_number, @dialog_time, @dialog_text].join("\n") + "\n\n"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'srt_subtitle_validator/srt_file'
|
2
|
+
class InvalidFile < ArgumentError; end
|
3
|
+
module SrtSubtitleValidator
|
4
|
+
class Validator
|
5
|
+
|
6
|
+
require 'logger'
|
7
|
+
require 'tempfile'
|
8
|
+
|
9
|
+
attr_reader :srt, :path, :file_name
|
10
|
+
|
11
|
+
def initialize(file_path, encoding = nil, logger = nil)
|
12
|
+
@logger = logger || Logger.new(STDOUT)
|
13
|
+
@path = File.absolute_path(file_path).strip
|
14
|
+
raise InvalidFile unless File.extname(@path) == '.srt'
|
15
|
+
@file_name = File.basename(@path)
|
16
|
+
parse_srt(File.read(@path, :encoding => (encoding || Encoding::UTF_8)))
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
@srt.valid?
|
21
|
+
end
|
22
|
+
|
23
|
+
def convert_srt(output, skip_backup = false)
|
24
|
+
skip_backup ||= output_file(output) != @path
|
25
|
+
backup_original_file unless !!skip_backup
|
26
|
+
@new_srt = Tempfile.new([@file_name.gsub('.srt', ''), '.srt'])
|
27
|
+
recalculate_number_sequence
|
28
|
+
|
29
|
+
@logger.info ' > Save as UTF-8 encoded file...'
|
30
|
+
@new_srt.flush
|
31
|
+
FileUtils.copy(@new_srt.path, output_file(output))
|
32
|
+
@new_srt.close
|
33
|
+
@new_srt.unlink
|
34
|
+
end
|
35
|
+
|
36
|
+
def missing_numbers
|
37
|
+
@missing_numbers ||= (Array(1..@srt.length) - @srt.blocks.map(&:dialog_number))
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def recalculate_number_sequence
|
43
|
+
@logger.info ' > Create new number sequence...'
|
44
|
+
@srt.blocks.each_with_index do |block, index|
|
45
|
+
number = index + 1
|
46
|
+
n = SrtSubtitleValidator::SrtFile::SrtBlock.new(number, block.dialog_time, block.dialog_text)
|
47
|
+
@new_srt.write(n.to_s)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def output_file(output = nil)
|
52
|
+
if output.to_s.empty?
|
53
|
+
@path
|
54
|
+
else
|
55
|
+
if File.directory?(output)
|
56
|
+
File.join(output, @file_name)
|
57
|
+
else
|
58
|
+
output
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def backup_original_file
|
65
|
+
@logger.info ' > Create backup...'
|
66
|
+
backup_suffix = 1
|
67
|
+
possible_backup_file = @path + '.' + backup_suffix.to_s
|
68
|
+
while File.exist?(possible_backup_file)
|
69
|
+
possible_backup_file = @path + '.' + (backup_suffix += 1).to_s
|
70
|
+
raise StandardError if backup_suffix >= 66
|
71
|
+
end
|
72
|
+
FileUtils.cp(@path, possible_backup_file)
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_srt(raw, with_fallback = true)
|
76
|
+
begin
|
77
|
+
@srt = SrtSubtitleValidator::SrtFile.new(raw)
|
78
|
+
rescue ArgumentError => e
|
79
|
+
if e.to_s == 'invalid byte sequence in UTF-8' && with_fallback
|
80
|
+
parse_srt(raw.force_encoding(Encoding::CP1250), false)
|
81
|
+
@srt.errors << 'Invalid encoding'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'srt_subtitle_validator/version'
|
2
|
+
# require 'srt_subtitle_validator/srt_file'
|
3
|
+
require 'srt_subtitle_validator/validator'
|
4
|
+
|
5
|
+
module SrtSubtitleValidator
|
6
|
+
# Your code goes here...
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class String
|
11
|
+
def blank?
|
12
|
+
to_s == ''
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class NilClass
|
17
|
+
def blank?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Array
|
23
|
+
def blank?
|
24
|
+
empty?
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'srt_subtitle_validator/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'srt_subtitle_validator'
|
8
|
+
spec.version = SrtSubtitleValidator::VERSION
|
9
|
+
spec.authors = ['Lukáš Pokorný']
|
10
|
+
spec.email = ['luk4s.pokorny@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'SRT subtitle file checker, validator'
|
13
|
+
spec.description = 'For check encoding and srt subtitle number sequence'
|
14
|
+
spec.homepage = 'https://github.com/luk4s/srt-subtitle-validator'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = 'bin'
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
25
|
+
|
26
|
+
spec.add_runtime_dependency 'thor', '~> 0.20'
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: srt_subtitle_validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lukáš Pokorný
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.20'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.20'
|
69
|
+
description: For check encoding and srt subtitle number sequence
|
70
|
+
email:
|
71
|
+
- luk4s.pokorny@gmail.com
|
72
|
+
executables:
|
73
|
+
- srt_checker
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/srt_checker
|
83
|
+
- lib/srt_subtitle_validator.rb
|
84
|
+
- lib/srt_subtitle_validator/cli.rb
|
85
|
+
- lib/srt_subtitle_validator/srt_file.rb
|
86
|
+
- lib/srt_subtitle_validator/validator.rb
|
87
|
+
- lib/srt_subtitle_validator/version.rb
|
88
|
+
- srt_subtitle_validator.gemspec
|
89
|
+
homepage: https://github.com/luk4s/srt-subtitle-validator
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.7.7
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: SRT subtitle file checker, validator
|
113
|
+
test_files: []
|