storyboard 0.3.1 → 0.4.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.
data/CHANGELOG ADDED
@@ -0,0 +1,16 @@
1
+ 0.4.0
2
+
3
+ Added two new options to Storyboard:
4
+ --preview [NUMBER] will output only the first NUMBER of frames that have subtitles.
5
+ if --preview is used with -c (forcing a scene change scan), it may include more than
6
+ NUMBER of frames, as the scene changes will also be included.
7
+
8
+ -n [NUMBER] nudges the timestamps forward or back in time by NUMBER seconds.
9
+ Combined with --preview this lets you more quickly line up the subtitles. Error detection
10
+ on nudging is nonexistant, and so if you nudge them too far forward or back they could
11
+ cause an error.
12
+
13
+ The following example will move the subtitles back 2 seconds, and render a 25 frame PDF:
14
+
15
+ storyboard -n -2 --preview 25 Video.mkv
16
+
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- storyboard (0.3.0)
4
+ storyboard (0.4.0)
5
5
  levenshtein-ffi
6
6
  mime-types (>= 1.19)
7
7
  mini_magick
data/README.md CHANGED
@@ -18,17 +18,17 @@ Storyboard will try to generate a file at `/path/to/video-file.pdf` containing t
18
18
  $ ls .
19
19
  ShowName.1x01.EpisodeName.pdf ShowName.1x02.AnotherEpisode.pdf ShowName.1x03.ThirdEp.pdf
20
20
 
21
- You can see available commands by running the program without any options
21
+ To quickly test if the subtitles that are used look ok, you can use the `--preview NUMBER` option, which generates a PDF with as many pages as you specify, defaulting to 10.
22
22
 
23
- Usage: storyboard [options] videofile [output_directory]
24
- -v, --[no-]verbose Run verbosely
25
- --[no-]scenes Detect scene changes. This increases the time it takes to generate a file.
26
- -ct FLOAT Scene detection threshold. 0.2 is too low, 0.8 is too high. Play with it!
27
- -s, --subs FILE SRT subtitle file to use. Will skip extracting/downloading one.
28
- --make x,y,z Filetypes to output
29
- (pdf, mobi, epub)
30
- -h, --help Show this message
23
+ storyboard --preview /path/to/video-file.mkv
31
24
 
25
+ If the subtitles are off, you can nudge them back or forward with the `-n TIME` option. This can be positive or negative, and if you make it too large it can cause Storyboard to throw an error. This would nudge the subtitles back 2 seconds, and generate just the preview PDF.
26
+
27
+ storyboard -n -2 --preview /path/to/video-file.mkv
28
+
29
+ You can see all the available options by using the help option:
30
+
31
+ storyboard -h
32
32
 
33
33
  ## Requirements
34
34
 
data/bin/storyboard CHANGED
@@ -22,12 +22,14 @@ unless Storyboard.magick_installed?
22
22
  exit
23
23
  end
24
24
 
25
- options = {:scenes => true, :verbose => true, :types => ['pdf'], :scene_threshold => 0.4}
25
+ options = {:nudge => 0, :verbose => true, :types => ['pdf'], :scene_threshold => 0.4}
26
26
 
27
27
  # think about them
28
28
  options[:consolidate_frame_threshold] = 0.4
29
29
  options[:max_width] = 600
30
30
 
31
+ puts "Running Storyboard #{Storyboard::VERSION}"
32
+
31
33
  LOG = Logger.new(STDOUT)
32
34
  LOG.level = Logger::INFO
33
35
 
@@ -43,16 +45,27 @@ opts.on("-c", "--[no-]scenes", "Detect scene changes. This increases the time it
43
45
  options[:scenes] = v
44
46
  end
45
47
 
46
- opts.on("-ct", Float, "Scene detection threshold. 0.2 is too low, 0.8 is too high. Play with it!") do |f|
47
- options[:scene_threshold] = f
48
+ opts.on("--preview [FRAMES]", Integer, "Only render the specified number (default 10) of subtitled images.", "Unless the -c flag is used, scene detection will be skipped") do |n|
49
+ options[:preview] = n || 10
50
+ options[:scenes] ||= false
51
+ end
52
+
53
+ opts.on("-n", "--nudge TIME", Float, "Nudge the subtitles forward or backward. TIME is the number of seconds.", "Use this with the --preview option to quickly check and adjust the subtitle timings.") do |time|
54
+ options[:nudge] = time
48
55
  end
49
56
 
57
+ #opts.on("--make x,y,z", Array, "Filetypes to output", '(pdf, mobi, epub)') do |types|
58
+ # options[:types] = types
59
+ #end
60
+
50
61
  opts.on("-s", "--subs FILE", "SRT subtitle file to use. Will skip extracting/downloading one.") do |s|
51
62
  options[:subs] = s
52
63
  end
53
64
 
54
- opts.on("--make x,y,z", Array, "Filetypes to output", '(pdf, mobi, epub)') do |types|
55
- options[:types] = types
65
+ opts.on('--update', "Update Storyboard to the latest available version") do |u|
66
+ # This execs in the current environment, I believe.
67
+ puts `gem update storyboard`
68
+ exit
56
69
  end
57
70
 
58
71
  opts.on_tail("-h", "--help", "Show this message") do
@@ -67,6 +80,10 @@ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument => e
67
80
  exit 1
68
81
  end
69
82
 
83
+ options[:scenes] = true if options[:scenes].nil?
84
+
85
+ p options
86
+
70
87
  if ARGV.size < 1
71
88
  puts "videofile required"
72
89
  puts opts.to_s
@@ -35,12 +35,7 @@ class Storyboard
35
35
  #downloader = Suby::Downloader::OpenSubtitles.new(suby_file, 'en')
36
36
  # try Addic7ed first, as, on average, it seems a bit better.
37
37
  downloader = nil
38
- begin
39
- LOG.debug("Searching for subtitles on Addic7ed")
40
- #downloader = Suby::Downloader::Addic7ed.new(suby_file, 'en')
41
- rescue Exception => e
42
- LOG.debug(e)
43
- end
38
+
44
39
 
45
40
  if downloader.nil?
46
41
  LOG.info("Searching for subtitles on OpenSubtitles")
@@ -89,8 +84,8 @@ class Storyboard
89
84
  end
90
85
  when :time
91
86
  if l =~ /^(#{TIME_REGEX}) --> (#{TIME_REGEX})$/
92
- page[:start_time] = STRTime.parse($1)
93
- page[:end_time] = STRTime.parse($2)
87
+ page[:start_time] = STRTime.parse($1) + @options[:nudge]
88
+ page[:end_time] = STRTime.parse($2) + @options[:nudge]
94
89
  phase = :text
95
90
  else
96
91
  raise "Bad SRT File: Should have time range but got '#{l}'"
@@ -1,3 +1,3 @@
1
1
  class Storyboard
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/storyboard.rb CHANGED
@@ -34,12 +34,22 @@ class Storyboard
34
34
  # bit of a temp hack so I don't have to wait all the time.
35
35
  @subtitles.save if options[:verbose]
36
36
 
37
-
38
37
  @renderers << Storyboard::PDFRenderer.new(self) if options[:types].include?('pdf')
39
38
 
40
39
  run_scene_detection if options[:scenes]
41
40
  consolidate_frames
41
+
42
+
43
+ # If the preview flag is set, do a quick count of how many subtitled frames fall before it.
44
+ if @options[:preview]
45
+ stop_time = @subtitles.pages[@options[:preview]].start_time.value
46
+ @stop_frame = @capture_points.count {|f| stop_time > f.value }
47
+ else
48
+ @stop_frame = @capture_points.count
49
+ end
50
+
42
51
  extract_frames
52
+
43
53
  render_output
44
54
 
45
55
  cleanup
@@ -58,7 +68,7 @@ class Storyboard
58
68
  end while !stdout.eof?
59
69
  }
60
70
  pbar.finish
61
- LOG.info("#{@capture_points.count} scenes registered")
71
+ LOG.info("#{@capture_points.count} scenes found and added to the timeline")
62
72
  end
63
73
 
64
74
  def consolidate_frames
@@ -80,9 +90,14 @@ class Storyboard
80
90
 
81
91
  def extract_frames
82
92
  pool = Thread::Pool.new(2)
83
- pbar = ProgressBar.create(:title => " Extracting Frames", :format => '%t [%c/%C|%B] %e', :total => @capture_points.count)
93
+ pbar = ProgressBar.create(:title => " Extracting Frames", :format => '%t [%c/%C|%B] %e', :total => @stop_frame )
84
94
 
85
95
  @capture_points.each_with_index {|f,i|
96
+ if i >= @stop_frame
97
+ pool.shutdown
98
+ return
99
+ end
100
+
86
101
  # It's *massively* quicker to jump to a bit before where we want to be, and then make the incrimental jump to
87
102
  # exactly where we want to be.
88
103
  seek_primer = (f.value < 1.000) ? 0 : -1.000
@@ -103,8 +118,9 @@ class Storyboard
103
118
  end
104
119
 
105
120
  def render_output
106
- pbar = ProgressBar.create(:title => " Rendering Output", :format => '%t [%c/%C|%B] %e', :total => @capture_points.count)
121
+ pbar = ProgressBar.create(:title => " Rendering Output", :format => '%t [%c/%C|%B] %e', :total => ( @options[:preview] || @capture_points.count ))
107
122
  @capture_points.each_with_index {|f,i|
123
+ next if i >= @stop_frame
108
124
  image_name = File.join(@options[:save_directory], "%04d.jpg" % [i])
109
125
  capture_point_subtitles = @subtitles.pages.select { |page| f.value >= page.start_time.value and f.value <= page.end_time.value }.first
110
126
  begin
@@ -138,6 +154,7 @@ class Storyboard
138
154
  def setup
139
155
  @options[:basename] = File.basename(options[:file], ".*")
140
156
  @options[:work_dir] = Dir.mktmpdir
157
+ raise "Unable to create temporary directory" unless File.directory?(@options[:work_dir])
141
158
  Dir.mkdir(@options[:write_to]) unless File.directory?(@options[:write_to])
142
159
  @options[:save_directory] = File.join(@options[:work_dir], 'raw_frames')
143
160
  Dir.mkdir(@options[:save_directory]) unless File.directory?(@options[:save_directory])
data/setup/osx.sh CHANGED
@@ -78,7 +78,7 @@ if [ -x /usr/local/bin/convert ]; then
78
78
  printf '%s ok %s\n' "$(tput setaf 2)" "$(tput op)"
79
79
  else
80
80
  printf '%s have to install %s\n' "$(tput setaf 1)" "$(tput op)"
81
- brew install imagemagick
81
+ brew install imagemagick libtool
82
82
  fi
83
83
 
84
84
  echo -n "Checking for Ghostscript"
metadata CHANGED
@@ -1,145 +1,171 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: storyboard
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- - 1
9
- version: 0.3.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Mark Olson
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2013-01-22 00:00:00 -05:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2013-01-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: nokogiri
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- version: "0"
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
30
22
  type: :runtime
31
- version_requirements: *id001
32
- - !ruby/object:Gem::Dependency
33
- name: mini_magick
34
23
  prerelease: false
35
- requirement: &id002 !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- segments:
40
- - 0
41
- version: "0"
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mini_magick
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
42
38
  type: :runtime
43
- version_requirements: *id002
44
- - !ruby/object:Gem::Dependency
45
- name: prawn
46
39
  prerelease: false
47
- requirement: &id003 !ruby/object:Gem::Requirement
48
- requirements:
49
- - - ">="
50
- - !ruby/object:Gem::Version
51
- segments:
52
- - 0
53
- version: "0"
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: prawn
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
54
  type: :runtime
55
- version_requirements: *id003
56
- - !ruby/object:Gem::Dependency
57
- name: ruby-progressbar
58
55
  prerelease: false
59
- requirement: &id004 !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- segments:
64
- - 0
65
- version: "0"
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: ruby-progressbar
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
66
70
  type: :runtime
67
- version_requirements: *id004
68
- - !ruby/object:Gem::Dependency
69
- name: levenshtein-ffi
70
71
  prerelease: false
71
- requirement: &id005 !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- segments:
76
- - 0
77
- version: "0"
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: levenshtein-ffi
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
78
86
  type: :runtime
79
- version_requirements: *id005
80
- - !ruby/object:Gem::Dependency
81
- name: path
82
87
  prerelease: false
83
- requirement: &id006 !ruby/object:Gem::Requirement
84
- requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- segments:
88
- - 1
89
- - 3
90
- - 0
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: path
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
91
101
  version: 1.3.0
92
102
  type: :runtime
93
- version_requirements: *id006
94
- - !ruby/object:Gem::Dependency
95
- name: rubyzip
96
103
  prerelease: false
97
- requirement: &id007 !ruby/object:Gem::Requirement
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- segments:
102
- - 0
103
- version: "0"
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 1.3.0
110
+ - !ruby/object:Gem::Dependency
111
+ name: rubyzip
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
104
118
  type: :runtime
105
- version_requirements: *id007
106
- - !ruby/object:Gem::Dependency
107
- name: term-ansicolor
108
119
  prerelease: false
109
- requirement: &id008 !ruby/object:Gem::Requirement
110
- requirements:
111
- - - ">="
112
- - !ruby/object:Gem::Version
113
- segments:
114
- - 0
115
- version: "0"
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: term-ansicolor
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
116
134
  type: :runtime
117
- version_requirements: *id008
118
- - !ruby/object:Gem::Dependency
119
- name: mime-types
120
135
  prerelease: false
121
- requirement: &id009 !ruby/object:Gem::Requirement
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- segments:
126
- - 1
127
- - 19
128
- version: "1.19"
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: mime-types
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '1.19'
129
150
  type: :runtime
130
- version_requirements: *id009
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '1.19'
131
158
  description: Generate PDFs and eBooks from video files
132
- email:
133
- - "\"theothermarkolson@gmail.com\""
134
- executables:
159
+ email:
160
+ - ! '"theothermarkolson@gmail.com"'
161
+ executables:
135
162
  - storyboard
136
163
  extensions: []
137
-
138
164
  extra_rdoc_files: []
139
-
140
- files:
165
+ files:
141
166
  - .gitignore
142
167
  - .rvmrc
168
+ - CHANGELOG
143
169
  - Gemfile
144
170
  - Gemfile.lock
145
171
  - INSTALL.md
@@ -179,38 +205,29 @@ files:
179
205
  - vendor/suby/spec/suby/filename_parser_spec.rb
180
206
  - vendor/suby/spec/suby_spec.rb
181
207
  - vendor/suby/suby.gemspec
182
- has_rdoc: true
183
208
  homepage: http://github.com/markolson/storyboard
184
209
  licenses: []
185
-
186
210
  post_install_message:
187
211
  rdoc_options: []
188
-
189
- require_paths:
212
+ require_paths:
190
213
  - lib
191
214
  - vendor/suby
192
- required_ruby_version: !ruby/object:Gem::Requirement
193
- requirements:
194
- - - ">="
195
- - !ruby/object:Gem::Version
196
- segments:
197
- - 1
198
- - 9
199
- - 3
215
+ required_ruby_version: !ruby/object:Gem::Requirement
216
+ none: false
217
+ requirements:
218
+ - - ! '>='
219
+ - !ruby/object:Gem::Version
200
220
  version: 1.9.3
201
- required_rubygems_version: !ruby/object:Gem::Requirement
202
- requirements:
203
- - - ">="
204
- - !ruby/object:Gem::Version
205
- segments:
206
- - 0
207
- version: "0"
221
+ required_rubygems_version: !ruby/object:Gem::Requirement
222
+ none: false
223
+ requirements:
224
+ - - ! '>='
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
208
227
  requirements: []
209
-
210
228
  rubyforge_project:
211
- rubygems_version: 1.3.6
229
+ rubygems_version: 1.8.23
212
230
  signing_key:
213
231
  specification_version: 3
214
232
  summary: Video to PDF/ePub generator
215
233
  test_files: []
216
-