storyboard 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
-